Docs / Authentication
Authentication
Every TEO request must include a bearer API key. Keys are issued from the portal under Dashboard / API keys.
Sending the key
Pass the key in the Authorization header on every request:
Authorization: Bearer tfp_live_...
The key is opaque to the client. The portal never returns the raw value after the first reveal — store it in a secret manager.
Key types
| Prefix | Environment | Use for |
|---|---|---|
tfp_test_ | test | Local development, CI, integration tests |
tfp_live_ | live | Production traffic |
tfp_svc_ | service | Server-to-server jobs (no IP allowlist binding) |
Scopes
A key carries a list of scopes. The route checks each scope before reaching the handler. The minimum scope set for flight search is usage.read.
usage.read— read your own usageusage.write— manage keys, applications, webhooksbilling.read— read invoices and credit balancebilling.write— change plan, cancel subscription, redeem coupon
IP allowlists
Add CIDR ranges to TDP_API_KEYS_IP_ALLOWLIST (or via the portal). Requests from a non-allowlisted IP return 403 AUTH_IP_BLOCKED.
Revoking a key
Revoke from the portal or call POST /v1/keys/{id}/revoke. The grace period is 60 seconds; in-flight requests are allowed to complete.
External app example — fetch flights
Below is a minimal example for an external airport app (or any client) that wants to pull flight data from the TEO API. ReplaceYOUR_API_KEY with the key from your Dashboard / API keys.
Raw flights vs. TEOScore-ranked results
POST /v1/flights/search (shown below) returns raw flight data only — it does not include a TEOScore. To get flights already scored and ranked by TEOScore in a single call, use POST /v1/search instead. Both endpoints accept the same key and the same flights.search scope — the only difference is that /v1/search also runs TEOScore and returns a teoscoreOptions array alongside the flights.
cURL
curl -sS "https://teofetch-api.onrender.com/v1/flights/search" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"origin": "JFK",
"destination": "LHR",
"departureDate": "2026-08-15",
"returnDate": "2026-08-22",
"cabin": "economy",
"travelers": {"adults": 1},
"includeCash": true,
"includeAward": true
}'JavaScript (Node.js / Browser)
const API_KEY = "YOUR_API_KEY";
const BASE_URL = "https://teofetch-api.onrender.com";
async function searchFlights(origin, destination, departureDate) {
const res = await fetch(`${BASE_URL}/v1/flights/search`, {
method: "POST",
headers: {
"Authorization": `Bearer ${API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ origin, destination, departureDate, cabin: "economy", travelers: { adults: 1 }, includeCash: true, includeAward: true }),
});
if (!res.ok) throw new Error(`HTTP ${res.status}: ${await res.text()}`);
return await res.json();
}
// Usage
searchFlights("JFK", "LHR", "2026-08-15").then(console.log).catch(console.error);Python
import httpx
API_KEY = "YOUR_API_KEY"
BASE_URL = "https://teofetch-api.onrender.com"
def search_flights(origin: str, destination: str, departure_date: str):
r = httpx.post(
f"{BASE_URL}/v1/flights/search",
headers={"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"},
json={
"origin": origin,
"destination": destination,
"departureDate": departure_date,
"returnDate": None,
"cabin": "economy",
"travelers": {"adults": 1},
"includeCash": True,
"includeAward": True,
},
)
r.raise_for_status()
return r.json()
# Usage
print(search_flights("JFK", "LHR", "2026-08-15"))travelers is an object ({"adults": 1}). Set includeCash and/or includeAward to control which fare types come back: includeCash returns cash fares, includeAward returns award/points availability. Request both to compare them side by side. Award availability is strongest in premium cabins on long-haul routes.
For a full list of available endpoints and response schemas, see the API reference.