Checkout
-
Ask how the traveller can pay. With the option and the start, the API lists only the methods whose time to pay ends in time. Bank details never come here: they come with the booking.
How the traveller can pay for this start Terminal window curl "https://api.stg.vacationpackagesoman.com/v1/public/payment-methods?option_id=9e4c2a71-3b5d-4e8f-a1c6-7d20f5b93e48&start=2026-11-14T15:00" \-H "Tp-Publishable-Key: $TP_KEY"const res = await fetch("https://api.stg.vacationpackagesoman.com/v1/public/payment-methods?option_id=9e4c2a71-3b5d-4e8f-a1c6-7d20f5b93e48&start=2026-11-14T15:00", {headers: {"Tp-Publishable-Key": process.env.TP_KEY!,},})const answer = await res.json()Answer: 200 OK
[{"kind": "pay_on_arrival","deadline_hours": null,"currencies": ["USD","AED"]},{"kind": "payment_link","deadline_hours": 72,"currencies": []}] -
Hold the places with the quote’s selection. The API prices it again and holds the places for 15 minutes. Keep the
ref, and show the time left fromhold_expires_at.Hold the places for 15 minutes Terminal window curl -X POST "https://api.stg.vacationpackagesoman.com/v1/public/holds" \-H "Tp-Publishable-Key: $TP_KEY" \-H "Content-Type: application/json" \-d '{"option_id": "9e4c2a71-3b5d-4e8f-a1c6-7d20f5b93e48","start": "2026-11-14T15:00","units": [{"unit_id": "1c7e9b42-6a3f-4d85-b0e2-58f4a1c9d736","qty": 2},{"unit_id": "2d8fac53-7b40-4e96-81f3-69a5b2dae847","qty": 1,"ages": [8]}],"currency": "USD"}'const res = await fetch("https://api.stg.vacationpackagesoman.com/v1/public/holds", {method: "POST",headers: {"Tp-Publishable-Key": process.env.TP_KEY!,"Content-Type": "application/json",},body: JSON.stringify({"option_id": "9e4c2a71-3b5d-4e8f-a1c6-7d20f5b93e48","start": "2026-11-14T15:00","units": [{"unit_id": "1c7e9b42-6a3f-4d85-b0e2-58f4a1c9d736","qty": 2},{"unit_id": "2d8fac53-7b40-4e96-81f3-69a5b2dae847","qty": 1,"ages": [8]}],"currency": "USD"}),})const answer = await res.json()Answer: 201 Created
{"ref": "TP-4HZQ-8MNE","status": "on_hold","hold_expires_at": "2026-10-02T09:15:00.000Z","start": "2026-11-14T15:00","quote": {"option_id": "9e4c2a71-3b5d-4e8f-a1c6-7d20f5b93e48","lines": [{"kind": "unit","ref": "1c7e9b42-6a3f-4d85-b0e2-58f4a1c9d736","label": "Adult","qty": 2,"unit_price": {"amount": 6500,"currency": "USD"},"original_unit_price": null,"total": {"amount": 13000,"currency": "USD"},"pay_at": "upfront","included": false,"vehicle": null},{"kind": "unit","ref": "2d8fac53-7b40-4e96-81f3-69a5b2dae847","label": "Child (3-11)","qty": 1,"unit_price": {"amount": 5000,"currency": "USD"},"original_unit_price": null,"total": {"amount": 5000,"currency": "USD"},"pay_at": "upfront","included": false,"vehicle": null}],"totals": {"due_now": {"amount": 18000,"currency": "USD"},"pay_locally": [],"grand_total": {"amount": 18000,"currency": "USD"}},"confirmation": "instant","pending_expires_at": null,"remaining": 14,"pax": 3,"pairing": false,"vehicles": [],"fx": {"base": "USD","quote": "USD","rate": "1","rate_id": "0f6d2b8e-4c1a-4e5f-9b3d-7a8c6e2f1d90","as_of": "2026-10-01T00:00:00.000Z"},"policy": {"name": "Flexible","tiers": [{"from_days": 1,"to_days": null,"refund_pct": 100},{"from_days": 0,"to_days": 0,"refund_pct": 0}],"preset": "flexible"},"pickup": null}} -
Check out with the hold’s
ref, the lead traveller and the way to pay. Sendlocaleso the emails are in the traveller’s language.Check the hold out with the lead traveller Terminal window curl -X POST "https://api.stg.vacationpackagesoman.com/v1/public/checkout" \-H "Tp-Publishable-Key: $TP_KEY" \-H "Content-Type: application/json" \-d '{"ref": "TP-4HZQ-8MNE","lead": {"name": "Amina Yusuf","email": "amina@example.com","phone": "+971501234567"},"payment_method": "pay_on_arrival","locale": "en"}'const res = await fetch("https://api.stg.vacationpackagesoman.com/v1/public/checkout", {method: "POST",headers: {"Tp-Publishable-Key": process.env.TP_KEY!,"Content-Type": "application/json",},body: JSON.stringify({"ref": "TP-4HZQ-8MNE","lead": {"name": "Amina Yusuf","email": "amina@example.com","phone": "+971501234567"},"payment_method": "pay_on_arrival","locale": "en"}),})const answer = await res.json()Answer: 200 OK
{"ref": "TP-4HZQ-8MNE","status": "confirmed","start": "2026-11-14T15:00","pax": 3,"hold_expires_at": null,"pending_expires_at": null,"trip": {"title": "Desert safari with BBQ dinner","option": "Shared 4WD, afternoon","product_id": "5b1f0c3e-8d2a-4f6b-9c41-2e7a9d0b6f13"},"payment": {"method": "pay_on_arrival","status": "pay_on_arrival","due_at": null,"on_arrival": {"amount": 18000,"currency": "USD"},"bank": null,"receipt": null,"link": null},"details": {"status": "not_needed","due_at": null,"needed": 0,"complete": 0,"overdue": false},"cancellation": null,"rejection_reason": null,"quote": {"option_id": "9e4c2a71-3b5d-4e8f-a1c6-7d20f5b93e48","lines": [{"kind": "unit","ref": "1c7e9b42-6a3f-4d85-b0e2-58f4a1c9d736","label": "Adult","qty": 2,"unit_price": {"amount": 6500,"currency": "USD"},"original_unit_price": null,"total": {"amount": 13000,"currency": "USD"},"pay_at": "upfront","included": false,"vehicle": null},{"kind": "unit","ref": "2d8fac53-7b40-4e96-81f3-69a5b2dae847","label": "Child (3-11)","qty": 1,"unit_price": {"amount": 5000,"currency": "USD"},"original_unit_price": null,"total": {"amount": 5000,"currency": "USD"},"pay_at": "upfront","included": false,"vehicle": null}],"totals": {"due_now": {"amount": 18000,"currency": "USD"},"pay_locally": [],"grand_total": {"amount": 18000,"currency": "USD"}},"confirmation": "instant","pending_expires_at": null,"remaining": 14,"pax": 3,"pairing": false,"vehicles": [],"fx": {"base": "USD","quote": "USD","rate": "1","rate_id": "0f6d2b8e-4c1a-4e5f-9b3d-7a8c6e2f1d90","as_of": "2026-10-01T00:00:00.000Z"},"policy": {"name": "Flexible","tiers": [{"from_days": 1,"to_days": null,"refund_pct": 100},{"from_days": 0,"to_days": 0,"refund_pct": 0}],"preset": "flexible"},"pickup": null},"booking_token": "TOKEN_FROM_THE_LINK","contact_token": "CONTACT_TOKEN_FROM_CHECKOUT"} -
Show the booking. Its
statusisconfirmed, orpendingwhile the seller confirms or the payment is due. Keepbooking_tokenandcontact_tokenin the traveller’s session for the confirmation page; see managing a booking.
What checkout takes
Section titled “What checkout takes”| Field | When |
|---|---|
ref |
Always, for an option with holds: the hold’s reference. |
lead |
Always: name, email and phone (with the country code, e.g. +971501234567). |
payment_method |
When the site has ways to pay: one listed in step 1. |
traveller_details |
When the option’s traveller_details collects them at checkout: every traveller, the lead first. |
pickup_details |
When the pickup asks for a flight, a ship or a room. |
special_requests |
Optional, the traveller’s own words. |
locale |
Optional: the language of the traveller’s emails. |
Options booked on request
Section titled “Options booked on request”An option with capacity_mode on_request takes no hold. Check it out
directly with the quote’s selection in place of ref; the booking is
pending until the seller finds a place, and pending_expires_at says
when the request lapses.
curl -X POST "https://api.stg.vacationpackagesoman.com/v1/public/checkout" \ -H "Tp-Publishable-Key: $TP_KEY" \ -H "Content-Type: application/json" \ -d '{ "option_id": "4a5b6c7d-8e9f-4a0b-9c1d-2e3f4a5b6c7d", "start": "2026-11-14T09:00", "units": [ { "unit_id": "5b6c7d8e-9f0a-4b1c-8d2e-3f4a5b6c7d8e", "qty": 2 } ], "currency": "USD", "lead": { "name": "Amina Yusuf", "email": "amina@example.com", "phone": "+971501234567" }, "payment_method": "pay_on_arrival"}'const res = await fetch("https://api.stg.vacationpackagesoman.com/v1/public/checkout", { method: "POST", headers: { "Tp-Publishable-Key": process.env.TP_KEY!, "Content-Type": "application/json", }, body: JSON.stringify({ "option_id": "4a5b6c7d-8e9f-4a0b-9c1d-2e3f4a5b6c7d", "start": "2026-11-14T09:00", "units": [ { "unit_id": "5b6c7d8e-9f0a-4b1c-8d2e-3f4a5b6c7d8e", "qty": 2 } ], "currency": "USD", "lead": { "name": "Amina Yusuf", "email": "amina@example.com", "phone": "+971501234567" }, "payment_method": "pay_on_arrival" }),})const answer = await res.json()Answer: 200 OK (shortened)
{ "ref": "TP-7KQM-2XWD", "status": "pending", "pending_expires_at": "2026-10-04T09:00:00.000Z", "booking_token": "TOKEN_FROM_THE_LINK"}Paying
Section titled “Paying”- On the day (
pay_on_arrival): nothing to pay now;payment.on_arrivalis the amount to bring, fixed in the chosen currency. - Bank transfer: the booking’s
payment.bankhas the account to pay, andpayment.due_atthe deadline. The traveller can send the transfer’s receipt withPOST /v1/public/bookings/{ref}/receipt, a PDF or an image. - Payment link: the seller sends the traveller a link to pay, by the deadline.
Card payments come later.
If something goes wrong
Section titled “If something goes wrong”HoldExpired: the 15 minutes ran out. Hold again, quoting first if time has passed.TravellerDetailsRequiredorTravellerDetailsInvalid: showdetailsnext to the fields concerned.PaymentMethodNotOffered: ask for the payment methods again.- A network error after you sent checkout: send the same checkout again. The same hold with the same lead email books once, and the second answer is the same booking without its tokens (retries).