Developers
Sterling Travel & Tour — Partner API
Search, hold, add travellers, pay from your wallet and follow your bookings from your own systems.
Book flights for your customers from your own systems. Create a key on Organisation → API keys (shown once), send it as X-API-Key. Money is always integer minor units. Writes need Idempotency-Key. Each key has its own requests-per-minute limit (X-RateLimit-Limit / X-RateLimit-Remaining). Flow: search → hold an offer → upload each traveller's passport image (trips abroad) → add the travellers → pay from your organisation's wallet → poll the order until TICKETED.
Version 1.0.0 · openapi.json
curl -X POST {API}/v1/flights/search \
-H "X-API-Key: stt_live_…" -H "content-type: application/json" \
-d '{"slices":[{"origin":"ADD","destination":"NBO","date":"2026-12-01"}],"passengers":{"adults":1}}'FlightsSearch
post/v1/flights/searchSearch flights
Offers at your sell price, by currency then cheapest first (up to 200). A trip that starts outside Ethiopia is answered in two currencies: Ethiopian Airlines in ETB, the other airlines in USD — currencies lists them and each offer's price.currency says which. A company with a travel policy sees travelPolicy on each offer.
Request body (example)
{
"slices": [
{
"origin": "ADD",
"destination": "NBO",
"date": "2026-12-01"
}
],
"passengers": {
"adults": 0,
"children": 0,
"infants": 0
},
"cabin": "ECONOMY"
}Responses
200Offers400Invalid search.401Missing, invalid, revoked or expired API key (`api_key_required` / `api_key_invalid`).403The key's owner may not do this.429Too many requests for this key — wait `Retry-After` seconds (`RATE_LIMITED`).
OrdersHold, travellers, pay, status
post/v1/ordersHold an offer
Locks the price for a short time (holdExpiresAt). Refused with 409 when the flight leaves too soon, the offer is gone or your travel policy blocks it (travel_policy).
Parameters
Idempotency-Keyheader · requiredA unique value per operation (8–128 characters). A retry with the same key and body returns the first answer.
Request body (example)
{
"offerId": "string",
"search": {
"slices": [
{
"origin": "ADD",
"destination": "NBO",
"date": "2026-12-01"
}
],
"passengers": {
"adults": 0,
"children": 0,
"infants": 0
},
"cabin": "ECONOMY"
}
}Responses
201The held order401Missing, invalid, revoked or expired API key (`api_key_required` / `api_key_invalid`).403The key's owner may not do this.409Cannot be held.429Too many requests for this key — wait `Retry-After` seconds (`RATE_LIMITED`).
get/v1/orders/{id}Get an order
Poll after paying until status is TICKETED (tickets in fulfilment.tickets).
Parameters
idpath · required
Responses
200The order401Missing, invalid, revoked or expired API key (`api_key_required` / `api_key_invalid`).403The key's owner may not do this.404Not found.429Too many requests for this key — wait `Retry-After` seconds (`RATE_LIMITED`).
put/v1/orders/{id}/passengersAdd the travellers
The airline's booking rules are checked here; a refused traveller answers 409 with the reasons. The booking contact must give a phone number (contact.phone); every traveller gives a middle name and every adult a mobile number (passengers.N.phone). A birth date is required for every traveller, except an adult on a domestic trip (every airport in Ethiopia). On a trip abroad the typed passport number and expiry date must match the uploaded passport image: otherwise 422 document_image_mismatch with the fields in details.fieldErrors (passengers.N.document.number / passengers.N.document.expiresOn).
Parameters
idpath · required
Request body (example)
{
"passengers": [
{
"type": "ADT",
"givenName": "string",
"middleName": "string",
"surname": "string",
"gender": "MALE",
"birthDate": "2026-12-01",
"email": "string",
"phone": "+251911000000",
"document": {
"type": "PASSPORT",
"number": "string",
"issuingCountry": "ET",
"nationality": "ET",
"expiresOn": "2026-12-01",
"imageFileId": "00000000-0000-4000-8000-000000000000"
},
"infantOfPosition": 0
}
],
"contact": {
"email": "string",
"phone": "+251911000000",
"refused": false
}
}Responses
200Saved400Invalid travellers: e.g. no contact phone, or a missing birth date (`details.fieldErrors`).401Missing, invalid, revoked or expired API key (`api_key_required` / `api_key_invalid`).403The key's owner may not do this.409Refused by the booking rules.422Passport image problems: `document_image_required`, `document_image_invalid`, `document_image_not_passport`, `document_image_mismatch` (`details.reason`, `details.fieldErrors`).429Too many requests for this key — wait `Retry-After` seconds (`RATE_LIMITED`).
post/v1/orders/{id}/passengers/document-imageUpload a traveller's passport image
A trip abroad needs an image of every traveller's passport (PDF, JPEG or PNG, 8 MB max). Send the answer's imageFileId as document.imageFileId when adding the travellers; without one, a trip abroad is refused (422 document_image_required). For a trip abroad the image is read on upload: only a passport data page is accepted (a national ID or any other picture answers 422 document_image_not_passport; an illegible page 422 document_image_unreadable — upload a clearer photo). The number and expiry date read from it must match what you send with the travellers.
Parameters
idpath · required
Responses
201Stored401Missing, invalid, revoked or expired API key (`api_key_required` / `api_key_invalid`).403The key's owner may not do this.404Not found.422No file, an unsupported type, or too large; on a trip abroad also `document_image_not_passport` or `document_image_unreadable` (`details.reason`).429Too many requests for this key — wait `Retry-After` seconds (`RATE_LIMITED`).
post/v1/orders/{id}/payPay from your organisation's wallet
Captures the amount due from the wallet in currency (409 insufficient_funds when short). Booking and ticketing then run in the background — poll the order.
Parameters
idpath · requiredIdempotency-Keyheader · requiredA unique value per operation (8–128 characters). A retry with the same key and body returns the first answer.
Request body (example)
{
"currency": "ETB"
}Responses
201The payment401Missing, invalid, revoked or expired API key (`api_key_required` / `api_key_invalid`).403The key's owner may not do this.409Cannot be paid.429Too many requests for this key — wait `Retry-After` seconds (`RATE_LIMITED`).
AccountBookings and wallet
get/v1/bookingsYour organisation's bookings
Parameters
pagequery
Responses
200A page of bookings401Missing, invalid, revoked or expired API key (`api_key_required` / `api_key_invalid`).403The key's owner may not do this.429Too many requests for this key — wait `Retry-After` seconds (`RATE_LIMITED`).
get/v1/walletYour organisation's wallet balances
Responses
200Wallets per currency401Missing, invalid, revoked or expired API key (`api_key_required` / `api_key_invalid`).403The key's owner may not do this.429Too many requests for this key — wait `Retry-After` seconds (`RATE_LIMITED`).