Skip to content

Quotes

POST /v1/quotes prices a stay or a time slot. It doesn’t hold anything — it’s a read, just a priced one. A quote is valid for 15 minutes; hold it before expiresAt or ask for a new one.

For an hourly space, send the exact start and end of a slot from GET /v1/resources/{id}/slots, and leave out ratePlanId. See Hourly spaces and services.

FieldRequiredNotes
resourceIdyes
ratePlanIdif the resource has a room typeGet it from GET /v1/resources/{id} — see Resources, room types, rate plans. Leave it out for an hourly space.
from, toyesISO 8601 datetimes; from must be strictly before to. At most 366 nights apart. For an hourly space, the exact startsAt and endsAt of a slot.
partySizeyespositive integer
currencynoDisplay currency, an uppercase ISO 4217 code such as IDR; defaults to the rate plan’s own currency (no conversion)
Terminal window
curl -X POST https://api.<domain>/v1/quotes \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-d '{
"resourceId": "<RESOURCE_ID>",
"ratePlanId": "<RATE_PLAN_ID>",
"from": "2026-08-01T00:00:00Z",
"to": "2026-08-04T00:00:00Z",
"partySize": 2
}'
{
"quoteId": "...",
"priceBreakdown": {
"unit": "night",
"lines": [
{
"startsAt": "2026-08-01T00:00:00.000Z",
"endsAt": "2026-08-02T00:00:00.000Z",
"unit": "night",
"durationMinutes": 1440,
"unitAmountMinorUnits": "1500000",
"baseAmountMinorUnits": "1500000",
"seasonalMultiplierBps": 10000,
"dayOfWeekMultiplierBps": 10000,
"amountMinorUnits": "1500000"
}
],
"nights": [
{
"date": "2026-08-01",
"baseAmountMinorUnits": "1500000",
"amountMinorUnits": "1500000",
"seasonalMultiplierBps": 10000,
"dayOfWeekMultiplierBps": 10000
}
],
"subtotalMinorUnits": "4500000",
"lengthOfStayAdjustment": null,
"leadTimeAdjustment": null,
"totalMinorUnits": "4500000",
"currency": "IDR"
},
"fx": null,
"displayTotal": { "currency": "IDR", "amountMinorUnits": "4500000" },
"signedQuoteToken": "eyJhbGciOi...",
"expiresAt": "2026-07-16T03:15:00.000Z"
}

priceBreakdown.lines[] is the price, one line per priced unit. Read it in new code.

  • unit is night for a hotel stay (one line per night), hour for an hourly space priced per hour, and slot for an hourly space with a fixed price for that length. priceBreakdown.unit repeats it.
  • A multiplier of 10000 means no change (100%). 12000 means 20% more.
  • nights[] is the older shape. It stays for hotel stays and is empty for hourly spaces. It is removed only in a new API version.
  • lengthOfStayAdjustment and leadTimeAdjustment are null when no rule applied. They never apply to an hourly space.

null when no currency conversion happened — you didn’t ask for one, or it already matched the rate plan’s own currency. When it’s present, displayTotal is the converted amount the guest actually sees; priceBreakdown.totalMinorUnits/.currency always stays in the rate plan’s native currency either way.

Hand this to hold creation unchanged (see Quickstart) — whoever confirms the hold trusts this token’s price, never a re-typed number.

StatuscodeMeaning
400invalid_windowfrom isn’t strictly before to
400validation_failedA field is wrong, or the window is longer than 366 nights
400rate_plan_requiredThe resource has a room type; you omitted ratePlanId
400invalid_durationHourly space: the window length is not one of the space’s durations
404resource_not_found / rate_plan_not_foundCheck the ID, and check you’re using the right tenant’s key
409unavailableSee reasons — same vocabulary as Availability. For an hourly space, the window is not one of the bookable slots.
422no_pricing_ruleNo price configured for one or more nights (missingDates) — an operator-side gap, not something your integration can fix
422fx_rate_unavailableNo FX rate for the currency you asked for

Both sk_ and pk_ keys can call this endpoint — it’s the widget’s pricing surface too. Both need the quote:read scope.