The restaurant's booking policy
const url = 'https://api.useservice.app/v1/configuration';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/configuration \ --header 'Authorization: Bearer <token>'What a booking funnel reads once before it can show its first screen: the restaurant’s
party-size policy, the advance window, the timezone every date and time on this API is
expressed in, the currency every amount is denominated in, and the languages the restaurant
serves guests in. Requires the reservations:read scope. Read it once at start-up and hold
it; it is cheap to revalidate with If-None-Match.
Party size is policy. min_party_size and max_party_size are the range the
restaurant accepts online, enforced by POST /v1/reservations and GET /v1/availability
as party_size_too_small and party_size_too_large. They do not say a party of that size
can be seated: the table inventory decides that, and a size inside the range that no table
fits is refused with no_table_available. The sizes that can actually be seated are
party_sizes on each day of GET /v1/availability/months; offer those.
The advance window. max_advance_days, last_service_date and current_date let a
funnel avoid advance_window_exceeded and date_in_past rather than discover them.
Those policy refusals are defaults, not walls:
party_size_too_small,party_size_too_largeandadvance_window_exceededare overridable by a key carryingreservations:write:override.date_in_pastis not, and neither isno_table_available— no override adds a table.
Per-service facts are on GET /v1/availability. Whether a card guarantee applies,
whether a booking is a request, and when online booking closes vary by service, and are
disclosed per shift there. card_guarantee_from_party_size and default_cutoff_minutes
here are venue-wide summaries, not those answers.
Authorizations
Section intitulée « Authorizations »Parameters
Section intitulée « Parameters »Header Parameters
Section intitulée « 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.
Responses
Section intitulée « Responses »Configuration returned
The restaurant’s booking policy: the limits a request can break, plus the locale and currency every other payload is expressed in. Read it once at start-up and re-read it on a 200; it is cheap to revalidate and it changes whenever a manager changes a setting.
object
The object type: always configuration.
The restaurant this API key resolves to. There is no other way to confirm it.
The restaurant’s hosted booking page on our side, absolute and per-environment.
Two uses, and the second is the one that matters: it is a booking page for this
restaurant you can send a guest straight to, and it is the BASE of the guest
self-service page — append /{modification_token} (from
POST /v1/reservations?expand=modification_token) and the guest can view, modify or
cancel that booking with no credential of yours.
⚠️ Absolute on purpose: a relative path would resolve against whatever origin your funnel is served from and 404. Read it from here rather than hard-coding a host — it differs between environments, and it moves if the restaurant’s slug is changed.
ISO-3166 alpha-2. Phone numbers sent without a country code are normalised against this country.
IANA zone. Every service_date and every HH:MM on this API is wall-clock in this zone — never UTC, never the caller’s.
ISO-4217. The currency every minor-unit amount on this API is denominated in, guarantee quotes included.
The language restaurant-authored text — shift names, guest messages, closure messages — is rendered in when you send no ?locale=. It is also the language a guest created without guest.language is given.
The languages this restaurant maintains guest-facing content in, primary first. This
is the exact set ?locale= accepts on GET /v1/availability and
GET /v1/availability/months; anything else is a 400 with param: "locale",
because a locale the restaurant holds no strings for would silently answer in the
primary language instead.
⚠️ It also bounds what a guest can actually be WRITTEN to in: guest.language on a
create accepts any language the platform supports and records it on the profile, but
the message goes out in the first of that language and primary_language that
appears in this list. Sending one outside it is not refused and changes nothing
today.
Smallest party the restaurant accepts online — policy, not a promise of a table (party_sizes on GET /v1/availability/months is what can be seated). A smaller one is refused with party_size_too_small — overridable, so a key carrying reservations:write:override can still place it. Null means the restaurant sets no floor and the rule never fires.
Largest party the restaurant accepts online — policy, not a promise of a table (party_sizes on GET /v1/availability/months is what can be seated). A larger one is refused with party_size_too_large — overridable, so a key carrying reservations:write:override can still place it, which is how a partner books the large party the restaurant agreed to by phone. Null means no ceiling.
The restaurant’s own suggested party size: preselect it. Always between min_party_size and max_party_size.
Today, in timezone — the date date_in_past is measured against, not the caller’s. An earlier service_date is refused and, unlike the party and window limits, date_in_past can NOT be overridden: a service that has happened cannot be sold. One exception, and it is not an override — a service that started yesterday and is still seating past midnight remains bookable on yesterday’s date.
How many days ahead of current_date the restaurant sells. Beyond it, both availability and create answer advance_window_exceeded, which is overridable on the create. Null means the restaurant has no booking rule and the window is not enforced.
current_date + max_advance_days — the last date worth offering, pre-computed so a calendar can be bounded with a string comparison. Null whenever max_advance_days is.
The house default for how many minutes before a service starts online booking
closes; 0 means bookable until the start time, -1 means bookable during the
service, and null means the restaurant has no booking rule at all.
⚠️ A DEFAULT, not the enforced value: an individual service, or one date of it, may
set its own, and cutoff_passed is decided on that. Read the ENFORCED value from
effective_cutoff_minutes on each shift of GET /v1/availability, which resolves
the same cascade the create path checks. Use this one only where no shift is in hand
— a settings screen, a default in copy.
Availability remains the authoritative answer either way: a slot past its cutoff is simply not listed.
Whether the restaurant wants guests asked to choose a seating area. Render the
seating step from GET /v1/sections when true; skip it and send no section_id
when false.
⚠️ ADVISORY, not a rule: section_id is accepted on availability and on a create
either way, and nothing is refused for sending one. It is the restaurant’s
preference about its own booking flow, and it is the only place that preference is
stated.
Whether the restaurant asks for a guest e-mail address on its own booking form.
⚠️ ADVISORY, not a rule: this API does NOT enforce it, and a create with no e-mail
is accepted whatever it says — see required_guest_fields for what is actually
demanded. Use it to mark the same field required in your funnel rather than
contradict the restaurant in either direction.
One refusal does involve the address and it is not this flag: a slot carrying a card
guarantee always needs one, however this reads, or the create is refused with
email_required_for_guarantee — the guest is sent a pay-link by e-mail and cannot
complete the booking without it.
Whether the restaurant asks for a guest phone number on its own booking form.
⚠️ ADVISORY, not a rule, exactly like require_guest_email: this API does not
enforce it.
⚠️ Sending NEITHER an e-mail nor a phone number is accepted and costs the restaurant
two things worth knowing: nobody can reach that guest when a service is cancelled,
and the booking can never be matched to an existing guest profile, so it creates a
new one every time. Send whichever you hold, or identify the guest with guest_id.
Whether this venue asks guests for a card imprint at all, and from which party size.
null is a promise: no booking made now, on any service or date, is asked for a
card — skip the card step entirely for this venue. Either the restaurant uses no
card guarantee, or it cannot currently take one.
A number N is only a maybe: some service, on some date, may ask a party of N or
more, and no service asks a smaller party. Build the card step, then read
guarantee_from_party_size and guarantee on the service in GET /v1/availability
for the date the guest picks — that is the exact answer.
It can go from null to a number whenever the restaurant turns guarantees on, with
no change on your side: if you keep it for longer than a session, revalidate with
the ETag. No amounts or cancel window here; those are per service.
Guest fields a create must carry, or it is refused with guest_fields_required. Not required when the create identifies an existing profile by guest_id. This is the ENFORCED list, and it is not the widget’s form policy: require_guest_email / require_guest_phone above are published as advice about the restaurant’s own form and do not bind this API. Only what appears in this array is refused.
Example
{ "object": "configuration", "primary_language": "fr", "guest_languages": [ "fr" ], "required_guest_fields": [ "first_name", "last_name" ]}Dated API version applied to this response
Pass back as If-None-Match to revalidate cheaply
The Service-Version header names a version we do not publish
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" }}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.
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" }}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" }}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.