
Airport Transfer API
OperationalBook airport and city transfers worldwide: private cars, vans and shuttles from hundreds of local providers.
Version v1 · 8 endpoints
Examples use the sandbox base URL https://sandbox.flightota.com/api/v1. Sandbox rides go to the provider network's test system; confirmations are not real rides. Cancel sandbox rides you do not need.
Partner API — Transfers
Book airport and city transfers worldwide: private cars, vans and shuttles from hundreds of local providers, paid from your FlightOTA deposit and confirmed in seconds. Every example below is a real sandbox call made on 22 Sep 2026.
Getting started
| Environment | Base URL | Key prefix |
|---|---|---|
| Sandbox | https://sandbox.flightota.com/api/v1 | ak_test_ |
| Production | https://api.flightota.com/api/v1 | ak_live_ |
- Issue a key in the agent portal under API access, enabled for transfers (ask your account manager to add transfers to your API plan).
- Whitelist your server's public IP on the key.
- Send
X-Api-KeyandX-Api-Secreton every request, withAccept: application/jsonandContent-Type: application/json. - Call
GET /pingfirst.
Conventions. Money is {"amount": <integer minor units>, "currency": "BDT"} in your billing currency. A key with Amounts switched on the API access page gets currency units instead (15161.94). Pickup times are local to the pickup place with their offset (2026-11-01T10:00:00+04:00); other times are UTC. Search ids look like trs_…, quote ids trq_…, bookings TFT-XXXXXXXX (rides booked before 28 Sep 2026 keep their TR- reference). Errors are {"error": {"code": "…", "message": "…"}}.
Booking flow
Search, pick a quote, book. Quotes arrive over a few seconds: the search answers with the first ones, and more_coming: true means reading the search again brings more.
| state | Meaning |
|---|---|
confirmed | The provider confirmed; confirmation and pickup instructions set |
pending | Paid; the provider is confirming. Read it again; a ride the provider refuses is refunded. One it has not answered within an hour stays pending while our team confirms it with the provider, then it is confirmed or refunded |
cancelled | Cancelled; what the cancellation policy gives back (refund) is in your deposit |
rejected | The provider refused; nothing charged |
Search rides
POST /transfers/search| Field | Required | Notes |
|---|---|---|
mode | Yes | one_way, round_trip or hourly |
start | Yes | { "iata": "DXB" } for an airport, { "address": "…" }, or { "lat": …, "lng": … } |
end | Unless hourly | Same forms as start |
pickup_at | Yes | Local time at the pickup, YYYY-MM-DD HH:MM |
return_pickup_at | For round_trip | Local time of the return pickup |
hours | For hourly | 1–24, a car at your disposal |
passengers | Yes | 1–50 |
flight_type | No | domestic or international, for airport pickups |
{
"mode": "one_way",
"start": {"iata": "DXB"},
"end": {"address": "Atlantis The Palm, Dubai"},
"pickup_at": "2026-11-01 10:00",
"passengers": 2,
"flight_type": "international"
}Return: "mode": "round_trip", "return_pickup_at": "2026-11-05 18:00". By the hour: "mode": "hourly", "hours": 6 and no end.
Response (sandbox: 33 quotes in 11 s; one shown):
{
"search_id": "trs_8vhdop9ilzvvjdpabo8r",
"expires_at": "2026-09-22T14:56:53+00:00",
"more_coming": false,
"start": {
"name": "Dubai International Airport",
"iata": "DXB",
"city": "Dubai",
"lat": 25.2528,
"lng": 55.364399,
"timezone": "Asia/Dubai"
},
"end": {
"name": "Atlantis The Palm, Dubai",
"address": "44J8+5V - Crescent Rd - The Palm Jumeirah - Dubai - United Arab Emirates",
"iata": null,
"city": "Dubai",
"lat": 25.130438,
"lng": 55.117188,
"timezone": "Asia/Dubai"
},
"quotes": [
{
"quote_id": "trq_991e55f4e7381325158b81ca",
"mode": "one_way",
"provider": {"name": "DidaGo", "logo": "https://…", "rating": 5, "rating_count": 1},
"vehicle": {
"type": "Sedan",
"class": "Standard",
"make": "Toyota",
"model": "Corolla",
"image": "https://…",
"max_passengers": 3,
"max_bags": 3,
"num_vehicles": 1
},
"pickup_at": "2026-11-01T10:00:00+04:00",
"arrival_at": "2026-11-01T10:42:46+04:00",
"duration_minutes": 45,
"return": null,
"cancellation": {"online": true, "policy": [{"notice_hours": 24, "refund_percent": 100}]},
"cancellation_deadline": "2026-10-31T10:00:00+04:00",
"amenities": [
{"key": "meet_and_greet", "name": "Meet & Greet", "included": false},
{
"key": "provider_driver_information",
"name": "Early driver details",
"included": true
}
],
"flight_info_required": true,
"extra_pax_required": false,
"wait_minutes": 33,
"tolls_included": true,
"gratuity_included": false,
"notes": [
"You can make changes or cancel your ride at any time up to 24 hours before your scheduled pickup"
],
"supports": {"tracking": false, "driver_details": true},
"price": {"amount": 565658, "currency": "BDT"}
}
]
}priceis the whole ride for all passengers, what your deposit pays.max_passengersandmax_bagsare per vehicle;num_vehiclesis how many the quote includes.cancellation_deadlineis the last moment to cancel for the refund inpolicy.online: falserides cannot be cancelled through the API.flight_info_required: true: the booking must carry the flight number.extra_pax_required: true: it must name every passenger.wait_minutesis the free waiting time at pickup.- Quotes are valid until
expires_at.GET /transfers/search/{search_id}returns all quotes so far (call it whilemore_comingis true); an expired search answers410 search_expired.GET /transfers/search/{search_id}/quotes/{quote_id}returns one quote.
Book a ride
POST /transfers/search/{search_id}/quotes/{quote_id}/book pays from your deposit and books with the provider at once. Send an Idempotency-Key header; the same request with the same key returns the ride already booked.
| Field | Required | Notes |
|---|---|---|
passenger.first_name, last_name | Yes | Lead passenger |
passenger.email | Yes | Confirmation and driver details go here |
passenger.phone | Yes | With country code, e.g. +8801711000000; the driver calls or texts it |
passenger.country | Yes | ISO code |
extra_passengers[] | When extra_pax_required | { "first_name", "last_name" } for each other passenger |
flight.airline, flight.number | When flight_info_required | e.g. EK and 585; the driver tracks the flight |
return_flight | Round trip with flight_info_required | Same shape |
instructions | No | Up to 300 characters for the driver |
client_reference | No | Your own reference |
POST /api/v1/transfers/search/trs_8vhdop9ilzvvjdpabo8r/quotes/trq_991e55f4e7381325158b81ca/book
Idempotency-Key: docs-ride-001{
"passenger": {
"first_name": "Arif",
"last_name": "Rahman",
"email": "ops@agency.example",
"phone": "+8801711000000",
"country": "BD"
},
"flight": {"airline": "EK", "number": "585"},
"instructions": "Two bags, one child seat not needed",
"client_reference": "DOCS-RIDE-001"
}Response 201 Created (3.6 s)
{
"status": "confirmed",
"booking": {
"booking_ref": "TFT-Y54HH32L",
"state": "confirmed",
"created_at": "2026-09-22T14:37:23Z",
"client_reference": "DOCS-RIDE-001",
"confirmation": "MOZ6f26aec",
"total": {"amount": 565658, "currency": "BDT"},
"trip": {
"mode": "one_way",
"start": {"name": "Dubai International Airport", "iata": "DXB", "…": "…"},
"end": {"name": "Atlantis The Palm, Dubai", "…": "…"},
"pickup_at": "2026-11-01T10:00:00+04:00",
"return_pickup_at": null,
"hours": null,
"passengers": 2
},
"ride": {
"provider": {"name": "DidaGo", "logo": "https://…", "rating": 5, "rating_count": 1},
"vehicle": {
"type": "Sedan",
"make": "Toyota",
"model": "Corolla",
"max_passengers": 3,
"max_bags": 3,
"…": "…"
},
"pickup_at": "2026-11-01T10:00:00+04:00",
"arrival_at": "2026-11-01T10:42:46+04:00",
"duration_minutes": 45,
"return": null,
"amenities": [
{
"key": "provider_driver_information",
"name": "Early driver details",
"included": true
}
]
},
"passenger": {
"first_name": "Arif",
"last_name": "Rahman",
"email": "ops@agency.example",
"phone": "+8801711000000",
"country": "BD"
},
"extra_passengers": [],
"flight": {"airline": "EK", "number": "585"},
"return_flight": null,
"instructions": "Two bags, one child seat not needed",
"pickup_instructions": "If you haven't paid for the Meet&Greet service, your driver will contact you via text message to confirm the meeting point…",
"driver_contact": {"name": "…", "phone": "…", "email": "…"},
"cancellation": {
"online": true,
"policy": [{"notice_hours": 24, "refund_percent": 100}],
"free_until": "2026-10-31T06:00:00Z",
"cancelled_at": null
}
}
}Show the traveller confirmation, pickup_instructions (may contain simple HTML) and driver_contact.
| HTTP | error.code | Meaning |
|---|---|---|
| 202 | (status: pending) | Paid; the provider is confirming. Read the booking |
| 400 | idempotency_key_required | Add the header |
| 422 | validation_failed | See errors (flight number, extra passengers…) |
| 410 | quote_expired | Search again |
| 402 | insufficient_funds | Deposit too low; nothing charged |
| 409 | supplier_refused | The provider declined; nothing charged; pick another quote |
| 409 | duplicate_request, request_in_progress | Key reused, or still running |
| 503 | supplier_unavailable | Nothing charged; retry |
Read, list and cancel
GET /transfers/bookings/{booking_ref} returns {"booking": {…}} as above. Another agency's reference answers 404 booking_not_found.
GET /transfers/bookings, newest first, 25 a page. Filters: state (pending, confirmed, cancelled, rejected), client_reference, created_from, created_to (YYYY-MM-DD), page, per_page (up to 100).
Cancel
POST /transfers/bookings/{booking_ref}/cancel, no body. The provider releases the ride and the share of the charge its policy gives at that notice returns to your deposit: all of it before cancellation.free_until, the tier's refund_percent after. refund says how much came back; it is zero when the provider reports it refunded nothing, and our team then follows it up. The sandbox cancellation of TFT-Y54HH32L (2 s):
{
"status": "cancelled",
"refund": {"amount": 565658, "currency": "BDT"},
"booking": {
"booking_ref": "TFT-Y54HH32L",
"state": "cancelled",
"cancellation": {
"online": true,
"policy": [{"notice_hours": 24, "refund_percent": 100}],
"free_until": "2026-10-31T06:00:00Z",
"cancelled_at": "2026-09-22T14:37:40+00:00"
},
"…": "…"
}
}| HTTP | error.code | Meaning |
|---|---|---|
| 409 | too_late | No tier of the policy gives money back any more |
| 409 | not_cancellable | This ride cannot be cancelled online (cancellation.online: false) |
| 503 | supplier_unavailable | The provider did not confirm; the ride is unchanged; retry |
Errors and go-live
Access errors
| HTTP | error.code | Fix |
|---|---|---|
| 401 | unauthenticated, credential_inactive | Check the key and secret |
| 403 | ip_whitelist_required, ip_not_whitelisted | Whitelist your server's IP |
| 403 | product_not_allowed | The key is not enabled for transfers |
| 403 | product_not_available | Transfers are not switched on for your agency |
| 403 | partner_inactive, subscription_*, environment_not_activated | Account or plan not active; live keys work after certification |
| 429 | rate_limited | Wait a minute |
Retries. 503, 429 and timeouts are safe to retry. Retry booking only with the same Idempotency-Key.
Go-live checklist
GET /pingfrom your whitelisted server- One-way search from an airport, a return search and an hourly search
- Quotes read again while
more_comingis true - Quotes shown with vehicle, capacity, waiting time and cancellation deadline
- Booking form asks for the flight number and extra passengers only when the quote requires them
- A ride booked with an
Idempotency-Key; the repeat returns the same booking - Confirmation, pickup instructions and driver contact shown to the traveller
- A ride cancelled before
free_until, and the refund shown 402 insufficient_funds,410 quote_expiredand409 too_lateshown in plain words
Sandbox notes. Sandbox rides go to the provider network's test system; confirmations are not real rides. Cancel sandbox rides you do not need.
Questions and certification: your account manager, or support from the agent portal.
Endpoint reference
Getting started
Ping
/pingCall GET /ping first.
Parameters
This endpoint takes no parameters.
Errors
- 401
unauthenticatedCheck the key and secret. - 401
credential_inactiveCheck the key and secret. - 403
ip_whitelist_requiredWhitelist your server's IP. - 403
ip_not_whitelistedWhitelist your server's IP. - 403
product_not_allowedThe key is not enabled for transfers. - 403
product_not_availableTransfers are not switched on for your agency. - 403
partner_inactiveAccount or plan not active; live keys work after certification. - 403
subscription_*Account or plan not active; live keys work after certification. - 403
environment_not_activatedAccount or plan not active; live keys work after certification. - 429
rate_limitedWait a minute.
curl -X GET "https://sandbox.flightota.com/api/v1/ping" \
-H "X-Api-Key: $FLIGHTOTA_API_KEY" \
-H "X-Api-Secret: $FLIGHTOTA_API_SECRET" \
-H "Accept: application/json"{
"ok": true,
"partner": "PTR-000020",
"key_id": "ak_test_your_key_id",
"environment": "test",
"from_ip": "203.0.113.10",
"server_time": "2026-09-22T13:25:02+00:00"
}{
"error": {
"code": "unauthenticated",
"message": "Check the key and secret."
}
}Search rides
Search rides
/transfers/searchQuotes arrive over a few seconds: the search answers with the first ones, and more_coming: true means reading the search again brings more. Return: "mode": "round_trip", "return_pickup_at": "2026-11-05 18:00". By the hour: "mode": "hourly", "hours": 6 and no end.
Parameters
| Parameter | In | Description |
|---|---|---|
modeone_way | round_trip | hourlyrequired | body | The trip type. |
startobjectrequired | body | { "iata": "DXB" } for an airport, { "address": "…" }, or { "lat": …, "lng": … }. |
endobjectoptional | body | Unless hourly. Same forms as start. |
pickup_atYYYY-MM-DD HH:MMrequired | body | Local time at the pickup. |
return_pickup_atYYYY-MM-DD HH:MMoptional | body | For round_trip. Local time of the return pickup. |
hoursinteger 1–24optional | body | For hourly. A car at your disposal. |
passengersinteger 1–50required | body | Passengers. |
flight_typedomestic | internationaloptional | body | For airport pickups. |
Errors
- 422
validation_failedSee errors. - 503
supplier_unavailableNothing charged; retry. - 401
unauthenticatedCheck the key and secret. - 401
credential_inactiveCheck the key and secret. - 403
ip_whitelist_requiredWhitelist your server's IP. - 403
ip_not_whitelistedWhitelist your server's IP. - 403
product_not_allowedThe key is not enabled for transfers. - 403
product_not_availableTransfers are not switched on for your agency. - 403
partner_inactiveAccount or plan not active; live keys work after certification. - 403
subscription_*Account or plan not active; live keys work after certification. - 403
environment_not_activatedAccount or plan not active; live keys work after certification. - 429
rate_limitedWait a minute.
curl -X POST "https://sandbox.flightota.com/api/v1/transfers/search" \
-H "X-Api-Key: $FLIGHTOTA_API_KEY" \
-H "X-Api-Secret: $FLIGHTOTA_API_SECRET" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"mode": "one_way",
"start": {
"iata": "DXB"
},
"end": {
"address": "Atlantis The Palm, Dubai"
},
"pickup_at": "2026-11-01 10:00",
"passengers": 2,
"flight_type": "international"
}'{
"search_id": "trs_8vhdop9ilzvvjdpabo8r",
"expires_at": "2026-09-22T14:56:53+00:00",
"more_coming": false,
"start": {
"name": "Dubai International Airport",
"iata": "DXB",
"city": "Dubai",
"lat": 25.2528,
"lng": 55.364399,
"timezone": "Asia/Dubai"
},
"end": {
"name": "Atlantis The Palm, Dubai",
"address": "44J8+5V - Crescent Rd - The Palm Jumeirah - Dubai - United Arab Emirates",
"iata": null,
"city": "Dubai",
"lat": 25.130438,
"lng": 55.117188,
"timezone": "Asia/Dubai"
},
"quotes": [
{
"quote_id": "trq_991e55f4e7381325158b81ca",
"mode": "one_way",
"provider": {
"name": "DidaGo",
"logo": "https://…",
"rating": 5,
"rating_count": 1
},
"vehicle": {
"type": "Sedan",
"class": "Standard",
"make": "Toyota",
"model": "Corolla",
"image": "https://…",
"max_passengers": 3,
"max_bags": 3,
"num_vehicles": 1
},
"pickup_at": "2026-11-01T10:00:00+04:00",
"arrival_at": "2026-11-01T10:42:46+04:00",
"duration_minutes": 45,
"return": null,
"cancellation": {
"online": true,
"policy": [
{
"notice_hours": 24,
"refund_percent": 100
}
]
},
"cancellation_deadline": "2026-10-31T10:00:00+04:00",
"amenities": [
{
"key": "meet_and_greet",
"name": "Meet & Greet",
"included": false
},
{
"key": "provider_driver_information",
"name": "Early driver details",
"included": true
}
],
"flight_info_required": true,
"extra_pax_required": false,
"wait_minutes": 33,
"tolls_included": true,
"gratuity_included": false,
"notes": [
"You can make changes or cancel your ride at any time up to 24 hours before your scheduled pickup"
],
"supports": {
"tracking": false,
"driver_details": true
},
"price": {
"amount": 565658,
"currency": "BDT"
}
}
]
}{
"error": {
"code": "validation_failed",
"message": "See errors."
}
}Search rides
Read all quotes so far
/transfers/search/{search_id}Returns all quotes so far (call it while more_coming is true); an expired search answers 410 search_expired.
Parameters
| Parameter | In | Description |
|---|---|---|
search_idstringrequired | path | The search id, trs_…. Example: trs_8vhdop9ilzvvjdpabo8r |
Errors
- 410
search_expiredAn expired search. - 401
unauthenticatedCheck the key and secret. - 401
credential_inactiveCheck the key and secret. - 403
ip_whitelist_requiredWhitelist your server's IP. - 403
ip_not_whitelistedWhitelist your server's IP. - 403
product_not_allowedThe key is not enabled for transfers. - 403
product_not_availableTransfers are not switched on for your agency. - 403
partner_inactiveAccount or plan not active; live keys work after certification. - 403
subscription_*Account or plan not active; live keys work after certification. - 403
environment_not_activatedAccount or plan not active; live keys work after certification. - 429
rate_limitedWait a minute.
curl -X GET "https://sandbox.flightota.com/api/v1/transfers/search/trs_8vhdop9ilzvvjdpabo8r" \
-H "X-Api-Key: $FLIGHTOTA_API_KEY" \
-H "X-Api-Secret: $FLIGHTOTA_API_SECRET" \
-H "Accept: application/json"{
"search_id": "trs_8vhdop9ilzvvjdpabo8r",
"expires_at": "2026-09-22T14:56:53+00:00",
"more_coming": false,
"start": {
"name": "Dubai International Airport",
"iata": "DXB",
"city": "Dubai",
"lat": 25.2528,
"lng": 55.364399,
"timezone": "Asia/Dubai"
},
"end": {
"name": "Atlantis The Palm, Dubai",
"address": "44J8+5V - Crescent Rd - The Palm Jumeirah - Dubai - United Arab Emirates",
"iata": null,
"city": "Dubai",
"lat": 25.130438,
"lng": 55.117188,
"timezone": "Asia/Dubai"
},
"quotes": [
{
"quote_id": "trq_991e55f4e7381325158b81ca",
"mode": "one_way",
"provider": {
"name": "DidaGo",
"logo": "https://…",
"rating": 5,
"rating_count": 1
},
"vehicle": {
"type": "Sedan",
"class": "Standard",
"make": "Toyota",
"model": "Corolla",
"image": "https://…",
"max_passengers": 3,
"max_bags": 3,
"num_vehicles": 1
},
"pickup_at": "2026-11-01T10:00:00+04:00",
"arrival_at": "2026-11-01T10:42:46+04:00",
"duration_minutes": 45,
"return": null,
"cancellation": {
"online": true,
"policy": [
{
"notice_hours": 24,
"refund_percent": 100
}
]
},
"cancellation_deadline": "2026-10-31T10:00:00+04:00",
"amenities": [
{
"key": "meet_and_greet",
"name": "Meet & Greet",
"included": false
},
{
"key": "provider_driver_information",
"name": "Early driver details",
"included": true
}
],
"flight_info_required": true,
"extra_pax_required": false,
"wait_minutes": 33,
"tolls_included": true,
"gratuity_included": false,
"notes": [
"You can make changes or cancel your ride at any time up to 24 hours before your scheduled pickup"
],
"supports": {
"tracking": false,
"driver_details": true
},
"price": {
"amount": 565658,
"currency": "BDT"
}
}
]
}{
"error": {
"code": "search_expired",
"message": "An expired search."
}
}Search rides
Read one quote
/transfers/search/{search_id}/quotes/{quote_id}Returns one quote. Quotes are valid until expires_at.
Parameters
| Parameter | In | Description |
|---|---|---|
search_idstringrequired | path | The search id, trs_…. Example: trs_8vhdop9ilzvvjdpabo8r |
quote_idstringrequired | path | The quote id, trq_…. Example: trq_991e55f4e7381325158b81ca |
Errors
- 410
search_expiredAn expired search. - 401
unauthenticatedCheck the key and secret. - 401
credential_inactiveCheck the key and secret. - 403
ip_whitelist_requiredWhitelist your server's IP. - 403
ip_not_whitelistedWhitelist your server's IP. - 403
product_not_allowedThe key is not enabled for transfers. - 403
product_not_availableTransfers are not switched on for your agency. - 403
partner_inactiveAccount or plan not active; live keys work after certification. - 403
subscription_*Account or plan not active; live keys work after certification. - 403
environment_not_activatedAccount or plan not active; live keys work after certification. - 429
rate_limitedWait a minute.
curl -X GET "https://sandbox.flightota.com/api/v1/transfers/search/trs_8vhdop9ilzvvjdpabo8r/quotes/trq_991e55f4e7381325158b81ca" \
-H "X-Api-Key: $FLIGHTOTA_API_KEY" \
-H "X-Api-Secret: $FLIGHTOTA_API_SECRET" \
-H "Accept: application/json"{
"quote_id": "trq_991e55f4e7381325158b81ca",
"mode": "one_way",
"provider": {
"name": "DidaGo",
"logo": "https://…",
"rating": 5,
"rating_count": 1
},
"vehicle": {
"type": "Sedan",
"class": "Standard",
"make": "Toyota",
"model": "Corolla",
"image": "https://…",
"max_passengers": 3,
"max_bags": 3,
"num_vehicles": 1
},
"pickup_at": "2026-11-01T10:00:00+04:00",
"arrival_at": "2026-11-01T10:42:46+04:00",
"duration_minutes": 45,
"return": null,
"cancellation": {
"online": true,
"policy": [
{
"notice_hours": 24,
"refund_percent": 100
}
]
},
"cancellation_deadline": "2026-10-31T10:00:00+04:00",
"amenities": [
{
"key": "meet_and_greet",
"name": "Meet & Greet",
"included": false
},
{
"key": "provider_driver_information",
"name": "Early driver details",
"included": true
}
],
"flight_info_required": true,
"extra_pax_required": false,
"wait_minutes": 33,
"tolls_included": true,
"gratuity_included": false,
"notes": [
"You can make changes or cancel your ride at any time up to 24 hours before your scheduled pickup"
],
"supports": {
"tracking": false,
"driver_details": true
},
"price": {
"amount": 565658,
"currency": "BDT"
}
}{
"error": {
"code": "search_expired",
"message": "An expired search."
}
}Book a ride
Book a ride
/transfers/search/{search_id}/quotes/{quote_id}/bookPays from your deposit and books with the provider at once. Show the traveller confirmation, pickup_instructions (may contain simple HTML) and driver_contact. A 202 (status: pending) means paid; the provider is confirming. Read the booking.
Send an Idempotency-Key header; the same request with the same key returns the ride already booked. This call pays from your deposit.
Parameters
| Parameter | In | Description |
|---|---|---|
search_idstringrequired | path | The search id, trs_…. Example: trs_8vhdop9ilzvvjdpabo8r |
quote_idstringrequired | path | The quote id, trq_…. Example: trq_991e55f4e7381325158b81ca |
Idempotency-Keystringrequired | header | The same request with the same key returns the ride already booked. Example: docs-ride-001 |
passenger.first_namestringrequired | body | Lead passenger. |
passenger.last_namestringrequired | body | Lead passenger. |
passenger.emailstringrequired | body | Confirmation and driver details go here. |
passenger.phonestringrequired | body | With country code, e.g. +8801711000000; the driver calls or texts it. |
passenger.countrystringrequired | body | ISO code. |
extra_passengers[]arrayoptional | body | When extra_pax_required. { "first_name", "last_name" } for each other passenger. |
flight.airlinestringoptional | body | When flight_info_required. e.g. EK; the driver tracks the flight. |
flight.numberstringoptional | body | When flight_info_required. e.g. 585; the driver tracks the flight. |
return_flightobjectoptional | body | Round trip with flight_info_required. Same shape. |
instructionsstringoptional | body | Up to 300 characters for the driver. |
client_referencestringoptional | body | Your own reference. |
Errors
- 400
idempotency_key_requiredAdd the header. - 422
validation_failedSee errors (flight number, extra passengers…). - 410
quote_expiredSearch again. - 402
insufficient_fundsDeposit too low; nothing charged. - 409
supplier_refusedThe provider declined; nothing charged; pick another quote. - 409
duplicate_requestKey reused. - 409
request_in_progressStill running. - 503
supplier_unavailableNothing charged; retry. - 401
unauthenticatedCheck the key and secret. - 401
credential_inactiveCheck the key and secret. - 403
ip_whitelist_requiredWhitelist your server's IP. - 403
ip_not_whitelistedWhitelist your server's IP. - 403
product_not_allowedThe key is not enabled for transfers. - 403
product_not_availableTransfers are not switched on for your agency. - 403
partner_inactiveAccount or plan not active; live keys work after certification. - 403
subscription_*Account or plan not active; live keys work after certification. - 403
environment_not_activatedAccount or plan not active; live keys work after certification. - 429
rate_limitedWait a minute.
curl -X POST "https://sandbox.flightota.com/api/v1/transfers/search/trs_8vhdop9ilzvvjdpabo8r/quotes/trq_991e55f4e7381325158b81ca/book" \
-H "X-Api-Key: $FLIGHTOTA_API_KEY" \
-H "X-Api-Secret: $FLIGHTOTA_API_SECRET" \
-H "Accept: application/json" \
-H "Idempotency-Key: docs-ride-001" \
-H "Content-Type: application/json" \
-d '{
"passenger": {
"first_name": "Arif",
"last_name": "Rahman",
"email": "ops@agency.example",
"phone": "+8801711000000",
"country": "BD"
},
"flight": {
"airline": "EK",
"number": "585"
},
"instructions": "Two bags, one child seat not needed",
"client_reference": "DOCS-RIDE-001"
}'{
"status": "confirmed",
"booking": {
"booking_ref": "TFT-Y54HH32L",
"state": "confirmed",
"created_at": "2026-09-22T14:37:23Z",
"client_reference": "DOCS-RIDE-001",
"confirmation": "MOZ6f26aec",
"total": {
"amount": 565658,
"currency": "BDT"
},
"trip": {
"mode": "one_way",
"start": {
"name": "Dubai International Airport",
"iata": "DXB",
"…": "…"
},
"end": {
"name": "Atlantis The Palm, Dubai",
"…": "…"
},
"pickup_at": "2026-11-01T10:00:00+04:00",
"return_pickup_at": null,
"hours": null,
"passengers": 2
},
"ride": {
"provider": {
"name": "DidaGo",
"logo": "https://…",
"rating": 5,
"rating_count": 1
},
"vehicle": {
"type": "Sedan",
"make": "Toyota",
"model": "Corolla",
"max_passengers": 3,
"max_bags": 3,
"…": "…"
},
"pickup_at": "2026-11-01T10:00:00+04:00",
"arrival_at": "2026-11-01T10:42:46+04:00",
"duration_minutes": 45,
"return": null,
"amenities": [
{
"key": "provider_driver_information",
"name": "Early driver details",
"included": true
}
]
},
"passenger": {
"first_name": "Arif",
"last_name": "Rahman",
"email": "ops@agency.example",
"phone": "+8801711000000",
"country": "BD"
},
"extra_passengers": [],
"flight": {
"airline": "EK",
"number": "585"
},
"return_flight": null,
"instructions": "Two bags, one child seat not needed",
"pickup_instructions": "If you haven't paid for the Meet&Greet service, your driver will contact you via text message to confirm the meeting point…",
"driver_contact": {
"name": "…",
"phone": "…",
"email": "…"
},
"cancellation": {
"online": true,
"policy": [
{
"notice_hours": 24,
"refund_percent": 100
}
],
"free_until": "2026-10-31T06:00:00Z",
"cancelled_at": null
}
}
}{
"error": {
"code": "idempotency_key_required",
"message": "Add the header."
}
}Read, list and cancel
Read a booking
/transfers/bookings/{booking_ref}Returns the booking as above. Another agency's reference answers 404 booking_not_found.
Parameters
| Parameter | In | Description |
|---|---|---|
booking_refstringrequired | path | The booking reference, TFT-XXXXXXXX. Example: TFT-Y54HH32L |
Errors
- 404
booking_not_foundAnother agency's reference. - 401
unauthenticatedCheck the key and secret. - 401
credential_inactiveCheck the key and secret. - 403
ip_whitelist_requiredWhitelist your server's IP. - 403
ip_not_whitelistedWhitelist your server's IP. - 403
product_not_allowedThe key is not enabled for transfers. - 403
product_not_availableTransfers are not switched on for your agency. - 403
partner_inactiveAccount or plan not active; live keys work after certification. - 403
subscription_*Account or plan not active; live keys work after certification. - 403
environment_not_activatedAccount or plan not active; live keys work after certification. - 429
rate_limitedWait a minute.
curl -X GET "https://sandbox.flightota.com/api/v1/transfers/bookings/TFT-Y54HH32L" \
-H "X-Api-Key: $FLIGHTOTA_API_KEY" \
-H "X-Api-Secret: $FLIGHTOTA_API_SECRET" \
-H "Accept: application/json"{
"booking": {
"booking_ref": "TFT-Y54HH32L",
"state": "confirmed",
"…": "as above"
}
}{
"error": {
"code": "booking_not_found",
"message": "Another agency's reference."
}
}Read, list and cancel
List bookings
/transfers/bookingsNewest first, 25 a page.
Parameters
| Parameter | In | Description |
|---|---|---|
statestringoptional | query | pending, confirmed, cancelled, rejected. |
client_referencestringoptional | query | Your own reference. |
created_fromYYYY-MM-DDoptional | query | Created on or after this date. |
created_toYYYY-MM-DDoptional | query | Created on or before this date. |
pageintegeroptional | query | The page. |
per_pageintegeroptional | query | Up to 100. |
Errors
- 401
unauthenticatedCheck the key and secret. - 401
credential_inactiveCheck the key and secret. - 403
ip_whitelist_requiredWhitelist your server's IP. - 403
ip_not_whitelistedWhitelist your server's IP. - 403
product_not_allowedThe key is not enabled for transfers. - 403
product_not_availableTransfers are not switched on for your agency. - 403
partner_inactiveAccount or plan not active; live keys work after certification. - 403
subscription_*Account or plan not active; live keys work after certification. - 403
environment_not_activatedAccount or plan not active; live keys work after certification. - 429
rate_limitedWait a minute.
curl -X GET "https://sandbox.flightota.com/api/v1/transfers/bookings" \
-H "X-Api-Key: $FLIGHTOTA_API_KEY" \
-H "X-Api-Secret: $FLIGHTOTA_API_SECRET" \
-H "Accept: application/json"{
"bookings": [
{
"booking_ref": "TFT-Y54HH32L",
"state": "confirmed",
"…": "…"
}
],
"page": 1,
"per_page": 25,
"total": 1,
"last_page": 1
}{
"error": {
"code": "unauthenticated",
"message": "Check the key and secret."
}
}Read, list and cancel
Cancel
/transfers/bookings/{booking_ref}/cancelNo body. The provider releases the ride and the share of the charge its policy gives at that notice returns to your deposit: all of it before cancellation.free_until, the tier's refund_percent after. refund says how much came back; it is zero when the provider reports it refunded nothing, and our team then follows it up.
The provider releases the ride. What its policy gives back returns to your deposit.
Parameters
| Parameter | In | Description |
|---|---|---|
booking_refstringrequired | path | The booking reference, TFT-XXXXXXXX. Example: TFT-Y54HH32L |
Errors
- 409
too_lateNo tier of the policy gives money back any more. - 409
not_cancellableThis ride cannot be cancelled online (cancellation.online: false). - 503
supplier_unavailableThe provider did not confirm; the ride is unchanged; retry. - 401
unauthenticatedCheck the key and secret. - 401
credential_inactiveCheck the key and secret. - 403
ip_whitelist_requiredWhitelist your server's IP. - 403
ip_not_whitelistedWhitelist your server's IP. - 403
product_not_allowedThe key is not enabled for transfers. - 403
product_not_availableTransfers are not switched on for your agency. - 403
partner_inactiveAccount or plan not active; live keys work after certification. - 403
subscription_*Account or plan not active; live keys work after certification. - 403
environment_not_activatedAccount or plan not active; live keys work after certification. - 429
rate_limitedWait a minute.
curl -X POST "https://sandbox.flightota.com/api/v1/transfers/bookings/TFT-Y54HH32L/cancel" \
-H "X-Api-Key: $FLIGHTOTA_API_KEY" \
-H "X-Api-Secret: $FLIGHTOTA_API_SECRET" \
-H "Accept: application/json"{
"status": "cancelled",
"refund": {
"amount": 565658,
"currency": "BDT"
},
"booking": {
"booking_ref": "TFT-Y54HH32L",
"state": "cancelled",
"cancellation": {
"online": true,
"policy": [
{
"notice_hours": 24,
"refund_percent": 100
}
],
"free_until": "2026-10-31T06:00:00Z",
"cancelled_at": "2026-09-22T14:37:40+00:00"
},
"…": "…"
}
}{
"error": {
"code": "too_late",
"message": "No tier of the policy gives money back any more."
}
}