Skip to content

Checkout

  1. 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"
    Answer: 200 OK
    [
    {
    "kind": "pay_on_arrival",
    "deadline_hours": null,
    "currencies": [
    "USD",
    "AED"
    ]
    },
    {
    "kind": "payment_link",
    "deadline_hours": 72,
    "currencies": []
    }
    ]
  2. 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 from hold_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"
    }'
    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
    }
    }
  3. Check out with the hold’s ref, the lead traveller and the way to pay. Send locale so 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"
    }'
    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"
    }
  4. Show the booking. Its status is confirmed, or pending while the seller confirms or the payment is due. Keep booking_token and contact_token in the traveller’s session for the confirmation page; see managing a booking.

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.

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.

An on-request option: no hold, straight to pending
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 '{
"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"
}'
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"
}
  • On the day (pay_on_arrival): nothing to pay now; payment.on_arrival is the amount to bring, fixed in the chosen currency.
  • Bank transfer: the booking’s payment.bank has the account to pay, and payment.due_at the deadline. The traveller can send the transfer’s receipt with POST /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.

  • HoldExpired: the 15 minutes ran out. Hold again, quoting first if time has passed.
  • TravellerDetailsRequired or TravellerDetailsInvalid: show details next 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).