Availability for one service date
const url = 'https://api.useservice.app/v1/availability?service_date=example&party_size=1';const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url 'https://api.useservice.app/v1/availability?service_date=example&party_size=1' \ --header 'Authorization: Bearer <token>'Per-shift slots for one date and one party size. A projection of what was sellable at read time, NOT a promise: the create path re-validates every cap and table fit under an advisory lock. Requires the reservations:read scope. Note that slots[].available_covers is null when the restaurant sets no covers cap — meaning unlimited, not zero.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Header Parameters
Section titled “Header Parameters”Pin this request to a dated version of the contract, e.g. 2026-09-01. Omit it and the version pinned on the API key applies. A version we do not publish is a 400 bad_request with param: "Service-Version". The version that was applied comes back on the Service-Version response header, always.
Query Parameters
Section titled “Query Parameters”YYYY-MM-DD, in the restaurant timezone
Slots, caps and the guarantee quote are all resolved for this party size
Restrict to one seating area (sec_…). Resolves to the whole section group.
Answer as if this hold or booking did not exist (hold_… or resv_…).
A live hold occupies its table for the whole booking duration and its covers count against the shift cap, so a funnel that holds a slot and then offers the guest other times is reading availability reduced by its own hold — up to and including the held time itself. Pass the hold back here and that stops happening.
Only an id this key could already fetch is accepted: a hold_… that resolves on
GET /v1/holds/{id}, or a resv_… that resolves on GET /v1/reservations/{id}.
Anything else is a 404, and a value that is neither shape is a 400 with
param: "excluding".
Varies the ETag, so revalidation is safe.
Language for the restaurant-authored text in this response — shift name,
guest_message, day_message and closure. Defaults to the restaurant’s
primary_language.
Only the languages listed in guest_languages on GET /v1/configuration are
accepted; anything else is a 400 with param: "locale", because a language the
restaurant holds no text for would silently answer in the primary one. Varies the
ETag, so revalidation is safe.
Responses
Section titled “Responses”Availability returned
A projection of what was sellable at read time, never a promise: the create path re-validates under a lock.
object
The object type: always availability.
The service day asked about, YYYY-MM-DD in the restaurant’s timezone.
The party size asked about. Every slot, flag and guarantee below answers for it.
The sec_… filter applied, if any.
A day-level note from the restaurant, shown as a banner. Independent of the shifts below — it can exist on a day where every service was removed.
Nothing is bookable today and what remains to show is a display-only service’s message. Day-level: NOT the per-shift flag of the same name.
No service runs today, but day_message carries the reason. Distinct from a closure.
The closure covering this date, or null. When set the day takes no bookings and shifts is empty.
object
The object type: always availability_closure.
The restaurant’s name for the closure, e.g. a holiday. null when it gave none.
The restaurant’s own words for this closure. Show them.
First day of the closure, YYYY-MM-DD in the restaurant’s timezone.
Last day of the closure, inclusive, in the same form.
The services that run on this date. [] on a closed day or a day with no service.
object
The object type: always availability_shift.
Opaque shf_… id, or null for a service that exists only as a date-scoped override.
The service’s name, e.g. Dîner. A date override’s name wins over the service’s own. null when neither has one.
The restaurant’s own note for this service. Show it.
HH:MM, restaurant timezone.
HH:MM, restaurant timezone.
How many minutes before start_time online booking closes FOR THIS service on THIS
date — the value actually enforced, resolved through the restaurant’s rule cascade
(a date override beats this service’s own rule, which beats the house default). This
is the authoritative one: configuration.default_cutoff_minutes is only the house
default and a service may set its own.
0 means bookable right up to the start time, -1 means bookable during the
service, and null means the restaurant has no booking rule at all and booking
never closes.
Once it passes, this service lists no slots and a create is refused with
cutoff_passed — so treat it as the countdown to show a guest, never as permission
to book.
The service is open and worth showing but takes NO online booking. Render its message, never a booking control.
Online booking for this service on this date is over: effective_cutoff_minutes
has passed, or its last seating time is behind the clock. slots is then []
because booking for it has ended, not because it filled, so do not show it as full.
The widget leaves such a service out of the list entirely.
Computed in the restaurant’s timezone at the moment of the request, so it is only
ever true on today’s date — and on yesterday’s, which this API still serves while
an overnight service is seating past midnight: there the overnight service reads
false until its last seating has passed, and every other service true.
A booking here is a REQUEST: it lands as pending and staff decide. Never tell the guest they are booked.
A guest of this party size may join the queue for this service. Always false while the restaurant has its booking widget switched off, because that is what the join endpoint itself enforces.
The card guarantee a booking of the requested party size in this service will be asked for. null means no card will be asked for.
object
The object type: always availability_guarantee.
Only card imprints are disclosed today.
ISO 4217 currency code of both amounts, e.g. EUR.
Minor units per guest.
Minor units for the requested party size.
Hours before the seating after which a cancellation may be charged. Null means cancellation is always free and only a no-show is charged.
The smallest party this service asks for a card imprint on this date, whatever
party_size you queried with.
null is a promise: no booking on this service on this date is asked for a card, at
any party size. A number is exact: a party of that size or larger is asked, a
smaller one is not. So on a bookable service guarantee is non-null exactly when
party_size is at least this, and you can tell a guest at which size the card step
starts without querying every size. guarantee still carries the amounts.
Set on a display_only or marked-full service too, where guarantee is always
null: it is what a booking placed there with an override would be asked.
It follows the same rule as the create: an imprint the restaurant cannot currently
charge is not asked, and reads null.
configuration.card_guarantee_from_party_size summarises it across every service
and date.
The seating times still bookable for the requested party size. [] when none is — read the flags above for why.
object
The object type: always availability_slot.
Seating time as HH:MM in the restaurant timezone.
Covers still sellable at this time, or null when no covers cap is configured — meaning unlimited, NOT zero. Do not treat null as falsy.
The per-slot pacing cap in force, or null when none is set.
Times this service SELLS that this party cannot take right now — rejected by a covers cap or because no table fits. Render them greyed out and offer the queue; hiding them is what makes a booking UI feel broken at peak. Times staff never offered, and times that have simply elapsed, are not listed here.
The rooms this service can be booked WHOLE in on this date: the group_id of every
section group with a row drawn on the floor plan this service uses on this date (a
date override may swap the plan). Pass one as entire_section_id.
Absence is a promise: a group not listed here is refused with
no_table_available_in_section for this service on this date. Presence is only a
maybe: a listed room can still be taken, and is then refused with section_occupied
and its conflicts.
It does not depend on party_size or section_id, and it ignores
bookable_online, which a whole-room booking does not read. Empty when the plan in
use has no sections.
Example
{ "object": "availability", "closure": { "object": "availability_closure" }, "shifts": [ { "object": "availability_shift", "guarantee": { "object": "availability_guarantee", "mode": "imprint" }, "slots": [ { "object": "availability_slot" } ] } ]}Headers
Section titled “Headers”Dated API version applied to this response
Pass back as If-None-Match to revalidate cheaply
Invalid request parameter
The envelope every public-API error answers with, whatever the status.
object
Every error response carries this one object.
object
The broad class of the error, from the HTTP status.
invalid_request_error: a400,403,404,409or422— something about the request to change.authentication_error: a401— the key is missing, invalid, revoked or expired.rate_limit_error: a429— slow down and retry.api_error: any other status, a fault on our side.
The specific error, stable and machine-readable, e.g. not_found. Branch on this, not on message.
A human-readable explanation for the developer. Its wording can change.
The request parameter the error is about, when there is one — e.g. expand or limit. Absent — not null — when the error names no field.
A link to this code in the errors reference. Always present.
Example
{ "error": { "type": "invalid_request_error" }}Missing or invalid API key
The envelope every public-API error answers with, whatever the status.
object
Every error response carries this one object.
object
The broad class of the error, from the HTTP status.
invalid_request_error: a400,403,404,409or422— something about the request to change.authentication_error: a401— the key is missing, invalid, revoked or expired.rate_limit_error: a429— slow down and retry.api_error: any other status, a fault on our side.
The specific error, stable and machine-readable, e.g. not_found. Branch on this, not on message.
A human-readable explanation for the developer. Its wording can change.
The request parameter the error is about, when there is one — e.g. expand or limit. Absent — not null — when the error names no field.
A link to this code in the errors reference. Always present.
Example
{ "error": { "type": "invalid_request_error" }}API key lacks the reservations:read scope
The envelope every public-API error answers with, whatever the status.
object
Every error response carries this one object.
object
The broad class of the error, from the HTTP status.
invalid_request_error: a400,403,404,409or422— something about the request to change.authentication_error: a401— the key is missing, invalid, revoked or expired.rate_limit_error: a429— slow down and retry.api_error: any other status, a fault on our side.
The specific error, stable and machine-readable, e.g. not_found. Branch on this, not on message.
A human-readable explanation for the developer. Its wording can change.
The request parameter the error is about, when there is one — e.g. expand or limit. Absent — not null — when the error names no field.
A link to this code in the errors reference. Always present.
Example
{ "error": { "type": "invalid_request_error" }}The section_id or excluding id does not resolve for this key
The envelope every public-API error answers with, whatever the status.
object
Every error response carries this one object.
object
The broad class of the error, from the HTTP status.
invalid_request_error: a400,403,404,409or422— something about the request to change.authentication_error: a401— the key is missing, invalid, revoked or expired.rate_limit_error: a429— slow down and retry.api_error: any other status, a fault on our side.
The specific error, stable and machine-readable, e.g. not_found. Branch on this, not on message.
A human-readable explanation for the developer. Its wording can change.
The request parameter the error is about, when there is one — e.g. expand or limit. Absent — not null — when the error names no field.
A link to this code in the errors reference. Always present.
Example
{ "error": { "type": "invalid_request_error" }}The date or party size is outside what the restaurant accepts (date_in_past, party_size_too_small, party_size_too_large, advance_window_exceeded)
The envelope every public-API error answers with, whatever the status.
object
Every error response carries this one object.
object
The broad class of the error, from the HTTP status.
invalid_request_error: a400,403,404,409or422— something about the request to change.authentication_error: a401— the key is missing, invalid, revoked or expired.rate_limit_error: a429— slow down and retry.api_error: any other status, a fault on our side.
The specific error, stable and machine-readable, e.g. not_found. Branch on this, not on message.
A human-readable explanation for the developer. Its wording can change.
The request parameter the error is about, when there is one — e.g. expand or limit. Absent — not null — when the error names no field.
A link to this code in the errors reference. Always present.
Example
{ "error": { "type": "invalid_request_error" }}Too many requests on the read budget
The envelope every public-API error answers with, whatever the status.
object
Every error response carries this one object.
object
The broad class of the error, from the HTTP status.
invalid_request_error: a400,403,404,409or422— something about the request to change.authentication_error: a401— the key is missing, invalid, revoked or expired.rate_limit_error: a429— slow down and retry.api_error: any other status, a fault on our side.
The specific error, stable and machine-readable, e.g. not_found. Branch on this, not on message.
A human-readable explanation for the developer. Its wording can change.
The request parameter the error is about, when there is one — e.g. expand or limit. Absent — not null — when the error names no field.
A link to this code in the errors reference. Always present.
Example
{ "error": { "type": "invalid_request_error" }}Headers
Section titled “Headers”Requests permitted in the read burst
Requests remaining in the read burst
Seconds until the read bucket refills
Which budget the numbers describe. read here.
Seconds to wait before retrying
Unique id for this request. Quote it to support: it is how a specific call is found in our logs. Generated per request, or echoed from the X-Request-Id you sent.