Skip to content

Availability for one service date

GET
/v1/availability
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.

Service-Version
string

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.

service_date
required
string

YYYY-MM-DD, in the restaurant timezone

party_size
required
integer

Slots, caps and the guarantee quote are all resolved for this party size

section_id
string

Restrict to one seating area (sec_…). Resolves to the whole section group.

excluding
string

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.

locale
string

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.

Availability returned

Media typeapplication/json

A projection of what was sellable at read time, never a promise: the create path re-validates under a lock.

object
object
required

The object type: always availability.

string
Allowed values: availability
service_date
required

The service day asked about, YYYY-MM-DD in the restaurant’s timezone.

string format: date
party_size
required

The party size asked about. Every slot, flag and guarantee below answers for it.

integer
section_id
required

The sec_… filter applied, if any.

string
nullable
day_message
required

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.

string
nullable
display_only
required

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.

boolean
message_only
required

No service runs today, but day_message carries the reason. Distinct from a closure.

boolean
closure
required

The closure covering this date, or null. When set the day takes no bookings and shifts is empty.

object
object
required

The object type: always availability_closure.

string
Allowed values: availability_closure
name
required

The restaurant’s name for the closure, e.g. a holiday. null when it gave none.

string
nullable
guest_message
required

The restaurant’s own words for this closure. Show them.

string
nullable
start_date
required

First day of the closure, YYYY-MM-DD in the restaurant’s timezone.

string format: date
end_date
required

Last day of the closure, inclusive, in the same form.

string format: date
shifts
required

The services that run on this date. [] on a closed day or a day with no service.

Array<object>
object
object
required

The object type: always availability_shift.

string
Allowed values: availability_shift
id
required

Opaque shf_… id, or null for a service that exists only as a date-scoped override.

string
nullable
name
required

The service’s name, e.g. Dîner. A date override’s name wins over the service’s own. null when neither has one.

string
nullable
guest_message
required

The restaurant’s own note for this service. Show it.

string
nullable
start_time
required

HH:MM, restaurant timezone.

string
nullable
end_time
required

HH:MM, restaurant timezone.

string
nullable
effective_cutoff_minutes
required

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.

integer
nullable
display_only
required

The service is open and worth showing but takes NO online booking. Render its message, never a booking control.

boolean
booking_closed
required

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.

boolean
requires_approval
required

A booking here is a REQUEST: it lands as pending and staff decide. Never tell the guest they are booked.

boolean
waitlist_open
required

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.

boolean
guarantee
required

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
object
required

The object type: always availability_guarantee.

string
Allowed values: availability_guarantee
mode
required

Only card imprints are disclosed today.

string
Allowed values: imprint
currency
required

ISO 4217 currency code of both amounts, e.g. EUR.

string
per_guest_amount
required

Minor units per guest.

integer
amount
required

Minor units for the requested party size.

integer
cancel_hours
required

Hours before the seating after which a cancellation may be charged. Null means cancellation is always free and only a no-show is charged.

integer
nullable
guarantee_from_party_size
required

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.

integer
nullable
slots
required

The seating times still bookable for the requested party size. [] when none is — read the flags above for why.

Array<object>
object
object
required

The object type: always availability_slot.

string
Allowed values: availability_slot
time
required

Seating time as HH:MM in the restaurant timezone.

string
available_covers
required

Covers still sellable at this time, or null when no covers cap is configured — meaning unlimited, NOT zero. Do not treat null as falsy.

integer
nullable
max_covers_per_slot
required

The per-slot pacing cap in force, or null when none is set.

integer
nullable
unavailable_slots
required

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.

Array<string>
section_ids
required

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.

Array<string>
Example
{
"object": "availability",
"closure": {
"object": "availability_closure"
},
"shifts": [
{
"object": "availability_shift",
"guarantee": {
"object": "availability_guarantee",
"mode": "imprint"
},
"slots": [
{
"object": "availability_slot"
}
]
}
]
}
Service-Version
string

Dated API version applied to this response

ETag
string

Pass back as If-None-Match to revalidate cheaply

Invalid request parameter

Media typeapplication/json

The envelope every public-API error answers with, whatever the status.

object
error
required

Every error response carries this one object.

object
type
required

The broad class of the error, from the HTTP status.

  • invalid_request_error: a 400, 403, 404, 409 or 422 — something about the request to change.
  • authentication_error: a 401 — the key is missing, invalid, revoked or expired.
  • rate_limit_error: a 429 — slow down and retry.
  • api_error: any other status, a fault on our side.
string
Allowed values: invalid_request_error authentication_error rate_limit_error api_error
code
required

The specific error, stable and machine-readable, e.g. not_found. Branch on this, not on message.

string
message
required

A human-readable explanation for the developer. Its wording can change.

string
param

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.

string
doc_url
required

A link to this code in the errors reference. Always present.

string
Example
{
"error": {
"type": "invalid_request_error"
}
}

Missing or invalid API key

Media typeapplication/json

The envelope every public-API error answers with, whatever the status.

object
error
required

Every error response carries this one object.

object
type
required

The broad class of the error, from the HTTP status.

  • invalid_request_error: a 400, 403, 404, 409 or 422 — something about the request to change.
  • authentication_error: a 401 — the key is missing, invalid, revoked or expired.
  • rate_limit_error: a 429 — slow down and retry.
  • api_error: any other status, a fault on our side.
string
Allowed values: invalid_request_error authentication_error rate_limit_error api_error
code
required

The specific error, stable and machine-readable, e.g. not_found. Branch on this, not on message.

string
message
required

A human-readable explanation for the developer. Its wording can change.

string
param

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.

string
doc_url
required

A link to this code in the errors reference. Always present.

string
Example
{
"error": {
"type": "invalid_request_error"
}
}

API key lacks the reservations:read scope

Media typeapplication/json

The envelope every public-API error answers with, whatever the status.

object
error
required

Every error response carries this one object.

object
type
required

The broad class of the error, from the HTTP status.

  • invalid_request_error: a 400, 403, 404, 409 or 422 — something about the request to change.
  • authentication_error: a 401 — the key is missing, invalid, revoked or expired.
  • rate_limit_error: a 429 — slow down and retry.
  • api_error: any other status, a fault on our side.
string
Allowed values: invalid_request_error authentication_error rate_limit_error api_error
code
required

The specific error, stable and machine-readable, e.g. not_found. Branch on this, not on message.

string
message
required

A human-readable explanation for the developer. Its wording can change.

string
param

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.

string
doc_url
required

A link to this code in the errors reference. Always present.

string
Example
{
"error": {
"type": "invalid_request_error"
}
}

The section_id or excluding id does not resolve for this key

Media typeapplication/json

The envelope every public-API error answers with, whatever the status.

object
error
required

Every error response carries this one object.

object
type
required

The broad class of the error, from the HTTP status.

  • invalid_request_error: a 400, 403, 404, 409 or 422 — something about the request to change.
  • authentication_error: a 401 — the key is missing, invalid, revoked or expired.
  • rate_limit_error: a 429 — slow down and retry.
  • api_error: any other status, a fault on our side.
string
Allowed values: invalid_request_error authentication_error rate_limit_error api_error
code
required

The specific error, stable and machine-readable, e.g. not_found. Branch on this, not on message.

string
message
required

A human-readable explanation for the developer. Its wording can change.

string
param

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.

string
doc_url
required

A link to this code in the errors reference. Always present.

string
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)

Media typeapplication/json

The envelope every public-API error answers with, whatever the status.

object
error
required

Every error response carries this one object.

object
type
required

The broad class of the error, from the HTTP status.

  • invalid_request_error: a 400, 403, 404, 409 or 422 — something about the request to change.
  • authentication_error: a 401 — the key is missing, invalid, revoked or expired.
  • rate_limit_error: a 429 — slow down and retry.
  • api_error: any other status, a fault on our side.
string
Allowed values: invalid_request_error authentication_error rate_limit_error api_error
code
required

The specific error, stable and machine-readable, e.g. not_found. Branch on this, not on message.

string
message
required

A human-readable explanation for the developer. Its wording can change.

string
param

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.

string
doc_url
required

A link to this code in the errors reference. Always present.

string
Example
{
"error": {
"type": "invalid_request_error"
}
}

Too many requests on the read budget

Media typeapplication/json

The envelope every public-API error answers with, whatever the status.

object
error
required

Every error response carries this one object.

object
type
required

The broad class of the error, from the HTTP status.

  • invalid_request_error: a 400, 403, 404, 409 or 422 — something about the request to change.
  • authentication_error: a 401 — the key is missing, invalid, revoked or expired.
  • rate_limit_error: a 429 — slow down and retry.
  • api_error: any other status, a fault on our side.
string
Allowed values: invalid_request_error authentication_error rate_limit_error api_error
code
required

The specific error, stable and machine-readable, e.g. not_found. Branch on this, not on message.

string
message
required

A human-readable explanation for the developer. Its wording can change.

string
param

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.

string
doc_url
required

A link to this code in the errors reference. Always present.

string
Example
{
"error": {
"type": "invalid_request_error"
}
}
RateLimit-Limit
integer

Requests permitted in the read burst

RateLimit-Remaining
integer

Requests remaining in the read burst

RateLimit-Reset
integer

Seconds until the read bucket refills

RateLimit-Resource
string

Which budget the numbers describe. read here.

Retry-After
integer

Seconds to wait before retrying

X-Request-Id
string

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.