Skip to content

Quote

A quote is the price of one choice: an option, a start, who is coming, and any extras or pickup. Ask for one each time the traveller changes a choice, and show it as it comes.

POST /v1/public/quotes with:

Field What it is
option_id The option chosen.
start The start, in the trip’s own time: 2026-11-14T15:00, or a date (2026-11-14) for an option open all day.
units Each unit chosen, with qty, and ages when the seller prices children by age.
extras Each extra chosen, with qty. Optional.
pickup Where to collect the travellers: a place_id, or lat and lng. Optional.
currency One of the site’s currencies. Optional: the site’s display currency by default.
What two adults and a child pay
Terminal window
curl -X POST "https://api.stg.vacationpackagesoman.com/v1/public/quotes" \
-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: 200 OK
{
"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
}
  • Each line: its label, qty and total. When original_unit_price is set, show it struck through: it is a special’s price before its discount.
  • totals.due_now: what is paid when booking.
  • totals.pay_locally: what is paid on the day, in its own currency. Show it apart, so nobody thinks it is charged now.
  • confirmation: instant books at once; manual waits for the seller, so say so before checkout.
  • policy: the cancellation policy this booking would have.

Show amounts with the currency’s own decimals (money). Don’t round, add or convert them yourself.

A selection that can’t be booked gets a 422 whose code says why, with the facts in details:

Too many travellers for the places left
Terminal window
curl -X POST "https://api.stg.vacationpackagesoman.com/v1/public/quotes" \
-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": 4
}
],
"currency": "USD"
}'
Answer: 422 Unprocessable Content
{
"type": "about:blank",
"title": "Unprocessable Content",
"status": 422,
"code": "NotEnoughCapacity",
"detail": "Not enough places are left then.",
"details": {
"remaining": 2
}
}

Turn each code into a message of your own, using details: “Only 2 places are left at 15:00” reads better than an error. The errors guide lists them all. A request that doesn’t fit the contract (a missing field, a wrong type) is 422 InvalidInput instead.

When the traveller goes on to book, hold the places with the same selection.