Partner API / Documentation

Partner Flight API documentation

Everything you need to search, price and book flights from your own platform. Version 1.

Request sandbox keys

Audience: Travel agencies, tour operators, TMCs, banks, fintechs and travel apps integrating flights into their own platform
Version: Partner API v1
Base path: /api/v1/partner


1. Getting access

  1. Email support@getmytrip.com with the subject [PARTNER API] Access request. Tell us your company name, website, and what you want to build.
  2. Once approved, GetMyTrip sends you sandbox credentials and your base URL.
  3. Build and test against the sandbox. It uses live fares and simulated bookings, and is free for up to 60 days.
  4. When your integration passes the go-live checklist (section 9), GetMyTrip issues production credentials.

What you receive from GetMyTrip

ItemDescription
Base URLSent with your credentials, e.g. https://<base-url>/api/v1
client_idPublic partner identifier (e.g. gmt_sandbox_demo-bank_…)
client_secretSecret shown once at issuance. Store it in a vault
EnvironmentSANDBOX or PRODUCTION
ScopesUsually: locations.search, flights.search, flights.price, flights.book, flights.read

Sandbox note: With SANDBOX credentials, search and price-confirm return real fares from live airline/GDS inventory; they never reserve seats. Booking is simulated: your request is validated exactly as in production, then you receive a test PNR and orderId, but no airline reservation is made and no traveller email is sent. See section 4.7.


2. Authentication (OAuth 2.0 Client Credentials)

Step A: Get an access token

POST /api/v1/partner/oauth/token
Content-Type: application/json
{
  "grant_type": "client_credentials",
  "client_id": "YOUR_CLIENT_ID",
  "client_secret": "YOUR_CLIENT_SECRET"
}

Success (200):

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "flights.search flights.price flights.book flights.read locations.search",
  "partner": {
    "id": "...",
    "name": "Demo Bank",
    "slug": "demo-bank",
    "status": "SANDBOX",
    "environment": "SANDBOX"
  }
}

Step B: Call APIs with the token

Authorization: Bearer <access_token>

Tokens expire in about 1 hour. Cache and refresh by calling /oauth/token again. Never put client_secret in a browser or mobile app; call GetMyTrip from your backend only.


3. End-to-end booking flow

1. (Optional) Locations autocomplete
2. Search flights          → save offerToken from chosen offer
3. Price confirm           → new offerToken (use this for book)
4. Create order            → orderId + PNR/recordLocator
5. Retrieve order          → status / confirmation

Offers returned to partners are sanitized. Supplier internals are not exposed. You must pass offerToken into price-confirm and book (do not rebuild raw supplier payloads). Requests without offerToken are rejected.

Offers come from GDS and airline NDC content (source: GDS or NDC). The booking flow is the same for both.

offerToken is valid for about 30 minutes.


4. API reference

GET /api/v1/partner/locations/search?keyword=LOS
Authorization: Bearer <token>
GET /api/v1/partner/flights/search
  ?originLocationCode=LOS
  &destinationLocationCode=LHR
  &departureDate=2026-12-10
  &adults=1
  &cabinClass=ECONOMY
Authorization: Bearer <token>
QueryRequiredNotes
originLocationCodeYes*IATA, e.g. LOS
destinationLocationCodeYes*IATA, e.g. LHR
departureDateYes*YYYY-MM-DD
returnDateNoRound-trip
adultsNoDefault 1
children / infantsNo
cabinClassNoe.g. ECONOMY, BUSINESS
nonStopNotrue / false
currencyCodeNoDisplay preference when supported

* Multi-city uses leg query params (same as the GetMyTrip website search).

Success shape:

{
  "success": true,
  "message": "Flights retrieved successfully",
  "data": [
    {
      "id": "...",
      "source": "GDS",
      "price": { "currency": "NGN", "total": "902068.65", "base": "...", "grandTotal": "..." },
      "itineraries": [ /* segments */ ],
      "travelerPricings": [ /* ... */ ],
      "offerToken": "uuid-cache-id",
      "expiresAt": "2026-09-03T13:30:00.000Z"
    }
  ],
  "meta": { "totalOffers": 248, "currency": "NGN" }
}

Pick one offer and keep its offerToken.

4.3 Price confirm (mandatory before book)

POST /api/v1/partner/flights/price-confirm
Authorization: Bearer <token>
Content-Type: application/json
{
  "offerToken": "uuid-from-search"
}

Success shape:

{
  "success": true,
  "message": "Amadeus flight price confirmed successfully",
  "data": {
    "offer": { "price": { "currency": "NGN", "grandTotal": "..." }, "offerToken": "...", "expiresAt": "..." },
    "offerToken": "new-uuid-for-book",
    "expiresAt": "...",
    "priceChanged": false,
    "totalPrice": "...",
    "currency": "NGN"
  }
}

Always use the new data.offerToken from this response for booking.

4.4 Book (create order)

POST /api/v1/partner/flights/orders
Authorization: Bearer <token>
Content-Type: application/json
{
  "offerToken": "uuid-from-price-confirm",
  "travelers": [
    {
      "id": "1",
      "dateOfBirth": "1990-05-15",
      "gender": "MALE",
      "name": {
        "firstName": "ADE",
        "lastName": "OKAFOR"
      },
      "documents": [
        {
          "documentType": "PASSPORT",
          "number": "A12345678",
          "expiryDate": "2030-01-01",
          "issuanceCountry": "NG",
          "nationality": "NG",
          "holder": true
        }
      ]
    }
  ],
  "contacts": [
    {
      "addresseeName": {
        "firstName": "ADE",
        "lastName": "OKAFOR"
      },
      "emailAddress": "traveller@example.com",
      "phones": [
        {
          "deviceType": "MOBILE",
          "countryCallingCode": "234",
          "number": "8012345678"
        }
      ]
    }
  ]
}

Traveler count must match the offer (adults/children/infants from search).

Booking rules (all airlines):

Success (201):

{
  "success": true,
  "message": "Flight booked successfully",
  "data": {
    "orderId": "...",
    "recordLocator": "ABC123",
    "pnr": "ABC123",
    "status": "CONFIRMED",
    "totalPrice": 902068.65,
    "currency": "NGN",
    "autoCancelAt": "2026-11-02T10:15:00.000Z"
  }
}

Ticketing deadline (autoCancelAt): a booking is a reservation until GetMyTrip issues the ticket. If it is still unticketed at autoCancelAt, GetMyTrip cancels it with the airline and its status becomes EXPIRED. The deadline is the earlier of 24 hours after booking and 1 hour before the airline's own ticketing or payment deadline. autoCancelAt is null once the booking is ticketed, paid or closed.

4.5 Retrieve bookings

List:

GET /api/v1/partner/flights/orders
Authorization: Bearer <token>

One order (must belong to your partner account):

GET /api/v1/partner/flights/orders/{orderId}
Authorization: Bearer <token>

The single-order response includes autoCancelAt. This endpoint is the authoritative booking status; webhooks are sent once and are not retried.

StatusMeaning
CONFIRMEDReserved with the airline (PNR issued), not yet ticketed
PENDINGReserved but the supplier has not returned a PNR yet
TICKETEDTicket issued
EXPIREDCancelled automatically because it was not ticketed by autoCancelAt
CANCELLEDCancelled by GetMyTrip operations

4.6 Webhooks

Send GetMyTrip your webhook URL during onboarding. To test it:

POST /api/v1/partner/webhooks/test
Authorization: Bearer <token>

GetMyTrip may POST these events to your webhook:

EventWhenKey data fields
booking.confirmedBooking createdorderId, recordLocator, status, totalPrice, currency, autoCancelAt
booking.cancelledUnticketed booking cancelled at its deadlineorderId, recordLocator, status: "EXPIRED", reason: "TICKETING_DEADLINE_PASSED", autoCancelAt, cancelledAt
ticket.issuedThe deadline check found the airline had already ticketedorderId, recordLocator, status: "TICKETED", ticketNumbers

Every webhook carries the header:

X-GetMyTrip-Signature: sha256=<hmac-of-raw-body>

Verify this signature against the raw request body before trusting the payload.

4.7 Sandbox bookings

With SANDBOX credentials, POST /flights/orders does not contact the airline. It applies the same checks as production (offer token, traveller count and types, names, date of birth, gender, contact email and phone), then returns a simulated booking:

{
  "success": true,
  "message": "Flight booked successfully (sandbox simulation, no airline reservation was made)",
  "data": {
    "orderId": "…",
    "recordLocator": "K7PQ2M",
    "pnr": "K7PQ2M",
    "status": "CONFIRMED",
    "totalPrice": 902068.65,
    "currency": "NGN",
    "autoCancelAt": "2026-11-02T10:15:00.000Z",
    "sandbox": true
  }
}

Test failure paths by sending an optional header on the book request:

X-GetMyTrip-Sandbox-ScenarioResult
success (default)201, status CONFIRMED with a PNR
pending201, status PENDING, pnr: null (the airline accepted the booking but has not returned a PNR yet)
supplier_error502, the airline did not respond. Nothing is stored

Simulate what happens after booking (sandbox credentials only, scope flights.book):

POST /api/v1/partner/sandbox/orders/{orderId}/simulate
Authorization: Bearer <token>
Content-Type: application/json

{ "event": "ticket.issued" }
eventEffect
ticket.issuedOrder becomes TICKETED with test ticket numbers; ticket.issued webhook is sent
booking.cancelledOrder becomes EXPIRED, exactly as when a booking passes autoCancelAt; booking.cancelled webhook is sent

The response returns the updated order plus a webhook object (delivered, responseCode, error) so you can confirm your endpoint received it. Orders that are already TICKETED or EXPIRED return 409.


5. cURL walkthrough

Replace BASE, CLIENT_ID, and CLIENT_SECRET with the values GetMyTrip sent you.

BASE=https://<base-url>/api/v1
CLIENT_ID=YOUR_CLIENT_ID
CLIENT_SECRET=YOUR_CLIENT_SECRET

# 1) Token
TOKEN=$(curl -s -X POST "$BASE/partner/oauth/token" \
  -H "Content-Type: application/json" \
  -d "{\"grant_type\":\"client_credentials\",\"client_id\":\"$CLIENT_ID\",\"client_secret\":\"$CLIENT_SECRET\"}" \
  | jq -r .access_token)

# 2) Search
curl -s "$BASE/partner/flights/search?originLocationCode=LOS&destinationLocationCode=ACC&departureDate=2026-11-20&adults=1" \
  -H "Authorization: Bearer $TOKEN" | jq '.data[0] | {id, price, offerToken}'

# 3) Price confirm (set OFFER_TOKEN from search)
curl -s -X POST "$BASE/partner/flights/price-confirm" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"offerToken\":\"$OFFER_TOKEN\"}" | jq '.data | {offerToken, totalPrice, currency}'

# 4) Book (set BOOK_TOKEN from price-confirm). Simulated with SANDBOX keys, a real reservation with PRODUCTION keys
curl -s -X POST "$BASE/partner/flights/orders" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d "{
    \"offerToken\": \"$BOOK_TOKEN\",
    \"travelers\": [{
      \"id\": \"1\",
      \"dateOfBirth\": \"1990-05-15\",
      \"gender\": \"MALE\",
      \"name\": { \"firstName\": \"ADE\", \"lastName\": \"OKAFOR\" }
    }],
    \"contacts\": [{
      \"addresseeName\": { \"firstName\": \"ADE\", \"lastName\": \"OKAFOR\" },
      \"emailAddress\": \"partner-test@example.com\",
      \"phones\": [{ \"deviceType\": \"MOBILE\", \"countryCallingCode\": \"234\", \"number\": \"8012345678\" }]
    }]
  }" | jq .

  1. Store secrets on your server (environment variables or a secrets manager), never in a mobile app or frontend.
  2. Your backend calls GetMyTrip for the token and for search, price-confirm and book.
  3. Your UI only talks to your backend and renders the sanitized offers (price, itineraries, offerToken).
  4. When the user clicks "Continue", your backend price-confirms; on "Pay/Book" it creates the order and shows pnr / orderId.
  5. Optionally receive booking.confirmed webhooks to update your ledger.
[Your App / Website]
        │
        ▼
[Your Backend]  --OAuth + Flight APIs-->  [GetMyTrip Partner API]
                                                 │
                                                 ▼
                                         Airline / GDS inventory

7. Errors & limits

HTTPMeaning
401Missing/invalid token or bad client credentials
403Partner suspended, wrong scope, or production key before go-live
400Validation / expired offerToken / price failure
409The airline could not confirm the fare at price-confirm (search again), or a sandbox order is already closed
429Rate limit (default ~60 requests/min per partner; the token endpoint allows 30 requests per 15 minutes)
502The airline did not respond to a booking. Check GET /flights/orders before retrying

Expired offerToken: search (and price-confirm) again.

Service health: GET /api/v1/partner/health (no token needed) returns 200 when the Partner API is healthy and 503 when it is not. Limit: 60 requests per minute per IP.


8. Not in Partner API v1 (yet)

For these, contact GetMyTrip operations or request an API expansion.


9. Go-live checklist


10. Support

Email support@getmytrip.com with the subject [PARTNER API] followed by your company name. Include your client_id (never your client_secret), the endpoint, the time of the request and any orderId.

Partner Flight API Documentation | GetMyTrip