Skip to main content

Make a test booking (JSON)

This walkthrough hand-holds you through creating a real booking in the test environment using the JSON API, end to end:

  1. Get an access token
  2. Search availabilityPOST /json/v2/offers
  3. Price the offerPOST /json/v2/offers/price
  4. Create the orderPOST /json/v2/orders
  5. Retrieve the orderGET /json/v2/orders/{orderId}

Every request and response below was captured live against the test environment. Only the API key and bearer token are redacted. Each endpoint also has a reference page covering the full schema: create offers, price offer, create order, order retrieve.

Before you start

Test base URLhttps://api-staging.flybreeze.com/breeze-offer-order
Production base URLhttps://api.flybreeze.com/breeze-offer-order
Route usedPVU → SNA (Provo → Orange County) — operates daily, so any date works
Passenger1 adult, paying with the sandbox Visa test card 4111 1111 1111 1111

All requests except the token call need two headers:

Authorization: Bearer <access token from step 0>
Content-Type: application/json

Successful responses arrive in a { "data": …, "error": null } envelope; failures put null in data and the problem in error.

Step 0 — Get an access token

Exchange your API key for a JWT. The token is valid for 30 minutes (expires_in: 1800); when a request starts returning 401, fetch a new one.

curl -X POST "https://api-staging.flybreeze.com/breeze-offer-order/auth/token" \
-H "x-api-key: <your-api-key>"
Response — 200 OK
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9…",
"token_type": "Bearer",
"expires_in": 1800
}

Send the token on every following request as Authorization: Bearer <access_token>.

Step 1 — Search availability

POST /json/v2/offers

One origin/destination, one adult:

Request
{
"originDestinations": [
{
"origin": "PVU",
"destination": "SNA",
"departureDate": "2026-09-15"
}
],
"passengers": [
{ "type": "ADT" }
]
}

The response returns 201 with one offer per fare product per flight (this search returned 8: four fare tiers on each of two flights). From the offer you want, capture two values for the next step:

  • offerIdOF-e6481f8d-74ed-46af-9ccb-7e47c6be3875
  • offerItemIdOFI-e6481f8d-74ed-46af-9ccb-7e47c6be3875-0

Offers expire at expiresAt (about 30 minutes). If you take longer, just search again.

Response — 201 Created (one offer shown, 7 elided)
{
"data": {
"offers": [
{
"offerId": "OF-e6481f8d-74ed-46af-9ccb-7e47c6be3875",
"ownerCode": "MX",
"expiresAt": "2026-08-17T15:23:40.625Z",
"totalPrice": {
"total": { "amount": 59, "currency": "USD" },
"base": { "amount": 13.58, "currency": "USD" },
"taxes": [
{ "code": "", "amount": { "amount": 45.42, "currency": "USD" } }
],
"fees": []
},
"offerItems": [
{
"offerItemId": "OFI-e6481f8d-74ed-46af-9ccb-7e47c6be3875-0",
"legIndex": 0,
"totalPrice": {
"total": { "amount": 59, "currency": "USD" },
"base": { "amount": 13.58, "currency": "USD" },
"taxes": [
{ "code": "", "amount": { "amount": 45.42, "currency": "USD" } }
],
"fees": []
},
"flight": {
"journeyId": "JOU-UFZVU05BfDIwMjYwOTE1fE1YMTY0NA",
"origin": "PVU",
"destination": "SNA",
"departureDateTime": "2026-09-15T19:31:00",
"arrivalDateTime": "2026-09-15T20:30:00",
"duration": "PT1H59M",
"stops": 0,
"segments": [
{
"segmentId": "SEG-UFZVU05BfDIwMjYwOTE1fE1YMTY0NA",
"marketingCarrier": "MX",
"marketingFlightNumber": "1644",
"operatingCarrier": "MX",
"operatingFlightNumber": "1644",
"origin": "PVU",
"destination": "SNA",
"departureDateTime": "2026-09-15T19:31:00",
"arrivalDateTime": "2026-09-15T20:30:00",
"cabinTypeCode": "Y",
"cabinName": "Economy",
"rbd": "C",
"duration": "PT1H59M"
}
],
"flightNumbers": ["MX1644"]
},
"fare": {
"fareBasisCode": "CNO00",
"cabinTypeCode": "Y",
"cabinName": "Economy",
"rbd": "C",
"paxRefIds": ["ADT-1"],
"bundleName": "No Flex",
"description": "Basic economy fare. Not combinable with Nice, Nicer, and Nicest add-on bundles.",
"benefits": [
{ "label": "Personal item", "included": true, "status": "included", "quantity": 1 },
{ "label": "Seat assignment", "included": false, "status": "upgrade" }
// … 7 more benefit rows elided …
],
"baggageDisclosures": [
{ "code": "PERSONAL_ITEM", "description": "17 in H x 13 in W x 8 in D", "ruleTypeCode": "D" }
// … CARRY_ON and CHECKED_BAG elided …
],
"penalties": [
// … change/cancel penalty ladders elided …
]
},
"passengerPrices": [
{
"ptc": "ADT",
"count": 1,
"paxRefIds": ["ADT-1"],
"price": {
"total": { "amount": 59, "currency": "USD" },
"base": { "amount": 13.58, "currency": "USD" },
"taxes": [
{ "code": "", "amount": { "amount": 45.42, "currency": "USD" } }
],
"fees": []
}
}
],
"seatsRemaining": 9
}
]
}
// … 7 more offers elided …
],
"pax": [
{ "paxId": "ADT-1", "ptc": "ADT" }
],
"paymentFunctions": [
{ "paymentTypeCode": "CC", "paymentBrandCode": "AX" },
{ "paymentTypeCode": "CC", "paymentBrandCode": "DS" },
{ "paymentTypeCode": "CC", "paymentBrandCode": "CA" },
{ "paymentTypeCode": "CC", "paymentBrandCode": "VI" }
],
"view": "flat"
},
"error": null
}

Step 2 — Price the offer

POST /json/v2/offers/price

Reference the shopping offer and repeat the passenger list:

Request
{
"selections": [
{
"offerId": "OF-e6481f8d-74ed-46af-9ccb-7e47c6be3875",
"offerItemIds": ["OFI-e6481f8d-74ed-46af-9ccb-7e47c6be3875-0"]
}
],
"passengers": [
{ "type": "ADT" }
]
}
The priced offer has a NEW ID

Pricing returns a new offerId/offerItemId — here OF-5cee97a8-…, not the OF-e6481f8d-… you sent. Create order only accepts the priced IDs.

The priced offer carries the guaranteed total with the full tax breakdown (the shopping response only shows a lump sum):

Response — 201 Created (trimmed)
{
"data": {
"pax": [
{ "paxId": "ADT-1", "ptc": "ADT" }
],
"paymentFunctions": [
{ "paymentTypeCode": "CC", "paymentBrandCode": "AX" },
{ "paymentTypeCode": "CC", "paymentBrandCode": "DS" },
{ "paymentTypeCode": "CC", "paymentBrandCode": "CA" },
{ "paymentTypeCode": "CC", "paymentBrandCode": "VI" }
],
"offer": {
"offerId": "OF-5cee97a8-d446-461b-91c6-4c9c5565ba04",
"ownerCode": "MX",
"expiresAt": "2026-08-17T15:23:40.625Z",
"totalPrice": {
"total": { "amount": 59, "currency": "USD" },
"base": { "amount": 13.58, "currency": "USD" },
"taxes": [
{ "code": "AY", "description": "PVU-SNA", "amount": { "amount": 5.6, "currency": "USD" } },
{ "code": "XF", "description": "PVU-SNA", "amount": { "amount": 4.5, "currency": "USD" } },
{ "code": "ZP", "description": "PVU-SNA", "amount": { "amount": 5.3, "currency": "USD" } },
{ "code": "US", "description": "PVU-SNA", "amount": { "amount": 1.02, "currency": "USD" } },
{ "code": "TDC", "description": "PVU-SNA", "amount": { "amount": 29, "currency": "USD" } }
],
"fees": []
},
"items": [
{
"offerItemId": "OFI-5cee97a8-d446-461b-91c6-4c9c5565ba04-0",
"totalPrice": {
// … same amounts and tax breakdown as above …
}
// … fare details, per-passenger prices elided …
}
]
},
"journeys": [
{
"journeyId": "JOU-UFZVU05BfDIwMjYwOTE1fE1YMTY0NA",
"origin": "PVU",
"destination": "SNA",
"departureDateTime": "2026-09-15T19:31:00",
"arrivalDateTime": "2026-09-15T20:30:00",
"duration": "PT1H59M",
"stops": 0,
"segments": [
// … same segment as step 1 …
]
}
]
},
"error": null
}

Step 3 — Create the order

POST /json/v2/orders

Three parts:

  • Offer selection — the priced IDs from step 2, and which passengers take which offer item.
  • Passengers & contacts — real passenger details. passengerId values are yours (PX1); gender must be Male or Female. The booking contact goes in contact and needs at least an email address; see contacts.
  • Payment — a card. In the test environment use the Visa test card below; no real charge is made. See payments.
Request
{
"offerId": "OF-5cee97a8-d446-461b-91c6-4c9c5565ba04",
"offerItemIds": ["OFI-5cee97a8-d446-461b-91c6-4c9c5565ba04-0"],
"offerItemSelections": [
{
"offerItemId": "OFI-5cee97a8-d446-461b-91c6-4c9c5565ba04-0",
"passengerIds": ["PX1"]
}
],
"passengers": [
{
"passengerId": "PX1",
"type": "ADT",
"name": { "givenName": "Jane", "surname": "Doe" },
"dateOfBirth": "1980-01-01",
"gender": "Female"
}
],
"contact": {
"emailAddress": "[email protected]",
"phoneNumber": "8015551212"
},
"payment": {
"type": "CreditCard",
"cardType": "VI",
"cardNumber": "4111111111111111",
"expiryDate": "1227",
"securityCode": "123",
"payer": {
"name": { "givenName": "Jane", "surname": "Doe" },
"postalAddress": {
"line1": "123 Main St",
"city": "Los Angeles",
"stateProvince": "California",
"postalCode": "90210",
"countryCode": "US"
}
}
}
}

Success returns 201 with the full order view. The key fields:

  • orderIdMX7NDN465E71, the order's identity for every later call.
  • recordLocatorE2BL5F, the underlying reservation-system record locator.
  • statusCodeCONFIRMED, with balanceDue of 0 since payment succeeded.
Response — 201 Created
{
"data": {
"order": {
"orderId": "MX7NDN465E71",
"recordLocator": "E2BL5F",
"ownerCode": "MX",
"statusCode": "CONFIRMED",
"creationDateTime": "2026-08-17T14:55:04.097Z",
"lastModifiedDateTime": "2026-08-17T14:55:04.097Z",
"balanceDue": { "amount": 0, "currency": "USD" },
"totalPrice": {
"total": { "amount": 59, "currency": "USD" },
"base": { "amount": 13.58, "currency": "USD" },
"taxes": [
{ "code": "AY", "amount": { "amount": 5.6, "currency": "USD" } },
{ "code": "XF", "amount": { "amount": 4.5, "currency": "USD" } },
{ "code": "ZP", "amount": { "amount": 5.3, "currency": "USD" } },
{ "code": "US", "amount": { "amount": 1.02, "currency": "USD" } },
{ "code": "TDC", "amount": { "amount": 29, "currency": "USD" } }
],
"fees": []
},
"items": [
{
"itemId": "OOI-FL-UHxQQVgtUVVSVUxURXxTfFBWVVNOQXwyMDI2MDkxNXxNWDE2NDQ",
"statusCode": "CONFIRMED",
"totalPrice": {
// … same amounts and tax breakdown as the order total …
},
"paxRefIds": ["ADT-1"],
"segmentRefIds": ["SEG-UFZVU05BfDIwMjYwOTE1fE1YMTY0NA"],
"fare": {
"fareBasisCode": "CNO00",
"cabinTypeCode": "Y",
"cabinName": "Economy",
"rbd": "C",
"paxRefIds": ["ADT-1"]
}
}
]
},
"services": [],
"pax": [
{
"paxId": "ADT-1",
"ptc": "ADT",
"name": { "givenName": "Jane", "surname": "Doe" },
"dateOfBirth": "1980-01-01",
"genderCode": "F",
"contactRefId": "CTC-UA"
}
],
"contacts": [
{
"contactId": "CTC-UA",
"contactTypeCode": "P",
"contactTypeName": "Primary",
"emailAddress": "[email protected]",
"phoneNumbers": [
{ "number": "+18015551212", "type": "Other" }
],
"name": { "givenName": "Jane", "surname": "Doe" }
}
],
"journeys": [
{
"journeyId": "JOU-UFZVU05BfDIwMjYwOTE1fE1YMTY0NA",
"origin": "PVU",
"destination": "SNA",
"departureDateTime": "2026-09-15T19:31:00",
"arrivalDateTime": "2026-09-15T20:30:00",
"duration": "PT1H59M",
"stops": 0,
"segments": [
{
"segmentId": "SEG-UFZVU05BfDIwMjYwOTE1fE1YMTY0NA",
"marketingCarrier": "MX",
"marketingFlightNumber": "1644",
"operatingCarrier": "MX",
"operatingFlightNumber": "1644",
"origin": "PVU",
"destination": "SNA",
"departureDateTime": "2026-09-15T19:31:00",
"arrivalDateTime": "2026-09-15T20:30:00",
"cabinTypeCode": "Y",
"cabinName": "Economy",
"rbd": "C",
"duration": "PT1H59M",
"legs": [
{
"legId": "LEG-UFZVU05BfDIwMjYwOTE1fE1YMTY0NA",
"origin": "PVU",
"destination": "SNA",
"departureDateTime": "2026-09-15T19:31:00",
"arrivalDateTime": "2026-09-15T20:30:00",
"aircraftTypeCode": "223",
"carrierAircraftTypeCode": "223-137"
}
]
}
]
}
],
"payments": [
{
"paymentId": "PAY-MQ",
"amount": { "amount": 59, "currency": "USD" },
"statusCode": "SUCCESSFUL",
"processedAt": "2026-08-17T14:55:05.947Z",
"method": {
"type": "CreditCard",
"cardBrandCode": "VI",
"maskedCardId": "x1111"
}
}
],
"tickets": []
},
"error": null
}

Step 4 — Retrieve the order

GET /json/v2/orders/MX7NDN465E71?ownerCode=MX

No body — just the Authorization header. Returns 200 with exactly the same order view as the create response above.

That's it — you have a paid, confirmed test booking.

Troubleshooting

SymptomCause & fix
401 on any callToken expired (30-minute lifetime). Re-run step 0.
ERR-1005 422 on createA field failed validation — the error.fields map names it (e.g. gender must be Male/Female).
ERR-3000 / ERR-3001The referenced offer was not found or has expired. Start again from step 1.
ERR-4001 400 on createMost common in testing: a passenger with the same name already holds a booking on the same flight — the reservation system rejects duplicate passenger names. Change the passenger name or the travel date between test bookings.

Next steps

Keep going with the same order: