Skip to content

Modify a reservation

PATCH
/v1/reservations/{id}
curl --request PATCH \
--url https://api.useservice.app/v1/reservations/example \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "party_size": 4 }'

Moves a booking — its day, its time, its party size, the area it sits in, the note the restaurant reads — and re-checks it against the restaurant’s rules as it goes. Requires the reservations:write scope.

PATCH is partial. A field you do not send is left alone. A field you send as null is cleared, which is meaningful for section_id (drop the area preference) and guest_notes. Sending an empty body is a 400.

The response is the booking as GET /v1/reservations/{id} shows it to your key. On a booking your key did not make, a key without guests:read does not get guest_notes, contact_email or contact_phone back, even the guest_notes it just sent.

The booking does not block itself. Capacity, the covers caps and the table search all exclude this reservation, so moving a party of four from 19:00 to 19:30 gives the four covers back at 19:00 before charging them at 19:30, and growing a party from four to six is checked for the two extra covers, not for six.

The table is re-assigned. A modify detaches the booking’s table and picks one again for the new slot, so the party can end up somewhere else even when only the note changed. If no table fits, the whole modify rolls back and the booking is exactly as it was.

The status can move underneath you. A confirmed booking whose new slot or party size needs the restaurant’s approval comes back pending, and the guest is told their change has been requested rather than made. Read status from the response.

Approval gates demand from outside the restaurant, so it is the BOOKING’s origin that decides, not yours: a booking the restaurant made itself (booking_channel of back_office, walk_in or phone) is already granted and stays confirmed however you change it. Bookings that arrived through the widget, this API or another channel are re-checked against the slot.

Refusals are itemised, exactly as on the create. A modify the rules refuse is a 422 with code: "booking_rules_violated" and a violations array, each entry flagged overridable. Read violations, never the top-level code, which is the same sentence for one broken rule as for six. Re-send with override set to the codes you accept — the scope, the 403 with param: "override", the 400 on a code that can never be waived and the retry-at-most-once rule are all the same as on POST /v1/reservations. Overrides that actually waived something are recorded on this booking’s change event as overrides_accepted.

What cannot be changed here. The guest (guest, guest_id), who writes to the guest (guest_notifications), your metadata and hold_id. Sending any of them is a 400 naming the field rather than a quiet no-op. So is any field this operation does not accept at all — internal_notes, table_ids, status — even beside a field that would apply: nothing is changed. Fields go in the JSON body: one sent in the query string (?party_size=6) is a 400 naming it too. guest_notifications in particular is fixed for the life of the booking: a confirmation that has been sent cannot be unsent, and one that was suppressed cannot be sent late. Cancel and rebook if you need a different answer.

A change that would RAISE a card guarantee is refused, with 422 guarantee_consent_guest_only. Growing the party on a booking backed by a card imprint raises the amount the restaurant may later charge, and a higher ceiling needs the cardholder’s own agreement to the new figure — which is theirs to give and cannot be given on their behalf, by you or by the restaurant. Nothing is changed; the booking is exactly as it was. Three ways forward: make a change that does not raise the amount (moving the time, or shrinking the party, both work and re-price the imprint where relevant); ask the restaurant to make the change from its back office, which keeps the existing, lower ceiling; or send the guest to their own booking page, which is the one place a new amount can be agreed to. Bookings YOUR key created never hit this — their guarantee is a payment request with an amount the restaurant set, not a guest-consented imprint — so it is reached only on a booking taken through the restaurant’s own widget.

A change that would put a booking with no card onto a card guarantee is refused, with 422 guarantee_modify_requires_card — growing the party past the size at which the restaurant asks for a card, or moving onto a service that asks for one for every booking. A modify cannot collect a card, and nothing is changed. Cancel and rebook: the create takes the card, or, with the reservations:write:override scope, books without one on override: ["guarantee_required"]. This code is never overridable on the modify itself. A booking whose current slot and party already call for a guarantee it does not have is not refused by this rule, and neither is one at a restaurant that cannot take card payments right now.

excluded_from_shift_limits can be corrected here, and setting it to true requires the reservations:write:override scope exactly as it does on the create. Setting it to false — giving the exemption up — requires nothing.

A booking that is completed, no_show or cancelled is a 409 reservation_finalized.

Holds are not reachable here. A hold_… id is not a reservation id, and a held slot is not served by this collection at all — release it with DELETE /v1/holds/{id} and take another.

Idempotency-Key is OPTIONAL on this endpoint, unlike on POST /v1/reservations and POST /v1/holds. Applying the same change twice is ordinarily harmless — the second pass finds nothing to change and writes nothing. The one thing a key buys you is the table: because every modify re-runs the table search, a blind retry can seat the party somewhere else and email the guest about a change they did not make. Send a key if you retry automatically. When you do, the original response is replayed verbatim, so it shows the booking as it was at the first attempt.

Writes have their own rate budget, lower than the read one, shared with every other write on this restaurant. See POST /v1/reservations.

id
required
string

Reservation id (resv_…)

Idempotency-Key
string
<= 255 characters

Optional. Re-send the same value to retry a modify safely. At most 255 characters, and no control characters: a longer or unprintable key is a 400 idempotency_key_invalid``, not a silently truncated one. Keys are scoped to your restaurant — another restaurant’s key of the same value is a different key — and are remembered for 72 hours, after which the same value starts a new request.

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.

Media typeapplication/json
object
service_date

The service day the booking belongs to, YYYY-MM-DD in the restaurant’s timezone. A seating after midnight in a service that began the evening before keeps that evening’s date, so it can differ from the date in starts_at.

string format: date
start_time

HH:MM on the restaurant’s clock: a slot time GET /v1/availability offered for this service_date.

string
party_size

How many guests the booking is for.

integer
section_id

Seat in one area (sec_…). null clears the preference.

string
nullable
guest_notes

What the guest asked for, in their own words. The restaurant sees it on the booking. Reading it back follows the response’s guest_notes.

string
nullable
internal_notes

The restaurant’s own note about this booking, as its staff would type it into the reservation form. Never shown to the guest. Reading it back follows the response’s internal_notes, which needs guests:read — on this booking as on any other.

string
nullable
company_id

File the booking under one of the restaurant’s companies (cmp_…), as its own staff would — the id is the one company.id carries on a booking already filed under it. null files it under no company. An id this restaurant does not know is a 404 naming company_id.

string
nullable
override

Booking rules you accept breaking, for this change only. Requires the reservations:write:override scope. Each value names a rule, and sending it waives that rule whether or not the refusal reported it — so you can send one ahead of the round trip.

guarantee_required is the rule “this slot asks the guest for a card”. You are only REFUSED with it when the card cannot be asked for — no address the pay-link can reach — but waiving it always means the same thing: the booking is made with no card guarantee at all, and the guest is never asked for one.

Array<string>
Allowed values: slot_no_longer_available cutoff_passed advance_window_exceeded party_size_too_small party_size_too_large slot_blocked shift_not_online_bookable duplicate_booking guarantee_required
excluded_from_shift_limits

Correct whether this booking is charged to the shift’s covers caps. Setting it to true requires the reservations:write:override scope; setting it to false requires none.

boolean
guarantee

Ask the guest for a card now. The booking goes back to awaiting_guarantee and is confirmed again when the card is saved. Only on a confirmed, upcoming booking that carries no guarantee yet — anything else is a 422 guarantee_request_not_allowed.

We e-mail the guest a payment link. Send {} to ask on the restaurant’s own terms, or set any of the three below. Needs no scope beyond reservations:write, and needs a guest e-mail address — without one the request is a 422 email_required_for_guarantee.

Not the same thing as the slot’s own guarantee, which applies whether or not you send this and is described by guarantee on GET /v1/availability. Sending this on such a slot replaces the amount and deadline it would have used.

A restaurant that cannot take card payments refuses the request with 422 payments_suspended, unlike a booking on a guaranteed slot, which is simply confirmed without a card.

object
amount_cents

How much to guarantee, in the restaurant’s currency’s smallest unit, for the whole party. Omit it for the amount the slot’s own guarantee policy would have used. Must be greater than zero; a slot with no policy and no amount here is a 422 guarantee_amount_invalid.

integer
nullable
deadline_hours

How long the guest has to save the card. Defaults to 48. Clamped, never refused: a deadline past the booked time — or past free cancellation, when that comes sooner — is brought forward, and the guarantee.expires_at on the response is the one that applies.

integer
nullable
auto_cancel_on_expiry

Cancel the booking when the deadline passes with no card saved. Defaults to true. Set it to false to keep the booking and let the restaurant decide.

boolean
nullable
Example
{
"party_size": 4
}

Reservation modified

Media typeapplication/json
object
object
required

The object type: always reservation.

string
Allowed values: reservation
id
required

The booking’s id, resv_…. Opaque and permanent. A booking converted from a hold keeps that hold’s suffix: hold_AbC becomes resv_AbC.

string
status
required

Where the booking is in its lifecycle.

⚠️ held and awaiting_guest never appear on a reservation this API serves — a hold is its own object (GET /v1/holds) and a waitlist promotion awaiting its guest is not yet a booking — so no endpoint, and no reservation.* webhook, can carry either value. They are listed because the enum is the platform’s own and codegen reads it verbatim. awaiting_guarantee DOES appear: it is a booking waiting for the guest to save a card.

There is no late. The restaurant’s screens show a party as late from its start time, but that is worked out on the spot and never stored, so a late party keeps the status it had, usually confirmed.

string
Allowed values: awaiting_guarantee awaiting_guest held pending confirmed partially_seated seated completed cancelled no_show
source
required

The mechanism that created the booking. See booking_channel for the channel the demand arrived through — a waitlist booking promoted by staff still has the channel the guest joined through.

  • manual: entered by the restaurant’s staff.
  • widget: made by the guest in the restaurant’s booking widget, including a widget embedded on a partner’s page.
  • walk_in: a party seated without a booking.
  • import: brought over from the restaurant’s previous reservation system.
  • waitlist: came out of the waitlist.
  • api: created through this API (POST /v1/reservations).
string
Allowed values: manual widget walk_in import waitlist api
booking_channel
required

The channel the demand arrived through, as opposed to source, the mechanism.

  • back_office: taken by the restaurant’s staff.
  • website_widget: the restaurant’s own booking widget.
  • phone: taken by telephone.
  • walk_in: a party that walked in.
  • google_reserve: booked through Google.
  • partner_platform: taken in the booking widget embedded on a partner’s own page.
  • api: created through this API (POST /v1/reservations), including a hold converted into a booking.
string
Allowed values: back_office website_widget phone walk_in google_reserve partner_platform api
party_size
required

How many guests the booking is for.

integer
service_date
required

The service day the booking belongs to, YYYY-MM-DD in the restaurant’s timezone. A seating after midnight in a service that began the evening before keeps that evening’s date, so it can differ from the date in starts_at.

string format: date
starts_at
required

When the party is due to sit down: ISO 8601 with the restaurant’s UTC offset, e.g. 2026-07-01T20:00:00+02:00.

string format: date-time
ends_at

When the table is expected back, in the same format as starts_at. null when no seating duration applies to the booking.

string format: date-time
nullable
guest_notes

What the guest asked for, in their own words. Guest data: present only when your key carries guests:read — on every booking alike, including the ones your key made. Otherwise the field is absent, not null. Every webhook delivery carries it.

string
nullable
guest_notifications
required

Who writes to the guest about this booking. partner_managed means we send none of the discretionary guest messages for it. Treat the list as open.

string
Allowed values: service_managed partner_managed
excluded_from_shift_limits
required

True when this booking does not count against the shift’s covers caps — a private event seated apart from the room those caps describe.

Those caps do not refuse it either, so a party larger than the covers left is booked rather than turned away. It still holds its table, and it still appears in every count of guests.

Setting it requires the reservations:write:override scope, except on a whole-section booking (entire_section_id), where it is the default.

boolean
contact_email

The e-mail address this booking’s messages go to, as given when it was made. null means the booking uses the guest profile’s address. Guest data: present only when your key carries guests:read — on every booking alike, including the ones your key made. Otherwise the field is absent, not null. Every webhook delivery carries it.

string
nullable
contact_phone

The phone number this booking’s messages go to, as given when it was made. null means the booking uses the guest profile’s number. Present on the same terms as contact_email.

string
nullable
internal_notes

The restaurant’s own note about this booking — what its staff would type into the reservation form. Not shown to the guest anywhere.

Guest data, and gated exactly like guest_notes: present only when your key carries guests:read — on every booking alike, including the ones your key made. Otherwise the field is absent, not null. Every webhook delivery carries it.

string
nullable
guest
required
Any of:

The guest’s id, gst_… — the unexpanded form.

string
company
required

The company the booking is made for, when it was filed under one — by the restaurant’s staff, or by company_id on your own create or PATCH. null otherwise, which is the common case; the key is always present. Readable by every key with reservations:read, unlike the guest’s own details.

object
object
required

The object type: always company.

string
Allowed values: company
id
required

The company’s id, cmp_….

string
name
required

The company’s name, as the restaurant recorded it.

string
tables
required

The tables the booking is seated at, each with its seating area. [] while no table is assigned.

Array<object>
object
object
required

The object type: always table.

string
Allowed values: table
id
required

The table’s id, tbl_…. Opaque and stable.

string
name
required

The table’s name on the restaurant’s floor plan.

string
min_capacity
required

The smallest party the table is meant for. Always a number, never null.

integer
max_capacity
required

The largest party the table seats on its own — a larger party needs tables joined together. Always a number, never null, and never below min_capacity.

integer
section
required

The seating area the table is in.

object
object
required

The object type: always section.

string
Allowed values: section
id
required

Pass this as section_id to GET /v1/availability or to a create — any member of a group resolves to the whole group, so a sec_… read off a reservation’s table works without knowing which row it is.

string
name
required

The area’s name, in the restaurant’s primary_language.

string
area_type
required

The kind of space, as the restaurant classified it: indoor, outdoor, terrace, bar, lounge, private_room (a room of its own), patio or rooftop. For a group, take it from the row where group_id == id.

string
Allowed values: indoor outdoor terrace bar lounge private_room patio rooftop
bookable_online
required

Whether THIS row is offered for online booking. Per row, never per group: it is deliberately not cascaded between group members, so a group is worth offering when ANY of its rows is true.

boolean
group_id
required

The sec_… id that identifies the conceptual seating area this row belongs to.

Rows sharing a group_id are ONE choice to a guest — the same area drawn on more than one floor plan — so group by it before rendering a picker, or the same area is offered twice.

Exactly one row per group has group_id == id: take that row’s name and area_type as the group’s. The others are kept in step by the product and are normally identical, but that is a behaviour of its editing paths rather than a constraint, so the naming row is the answer that cannot go stale.

string
guarantee

The card guarantee attached to the booking. null when it has none. Always included; no scope or expand needed.

object
object
required

The object type: always guarantee.

string
Allowed values: guarantee
kind
required

What the guest is guaranteeing with.

  • imprint: a saved card, charged only on a no-show or a late cancellation.
  • prepayment: payment up front. Reserved: no guarantee is issued with it today.
string
Allowed values: imprint prepayment
state
required

Where the guarantee is in its own lifecycle, which is separate from the booking’s status.

  • awaiting_card: waiting for the guest to save a card, until expires_at.
  • active: a card is saved and can be charged under the terms the guest accepted.
  • expired: the guest did not save a card in time.
  • withdrawn: the restaurant withdrew the request before a card was saved.
  • released: the card was let go and nothing will be charged.
  • charged: the full amount was charged.
  • partially_charged: less than amount was charged.
  • charge_failed: a charge was attempted and declined; it may be retried.
  • refunded: money charged was refunded in full.
  • disputed: the guest disputed the charge with their bank.
string
Allowed values: awaiting_card active expired released charged partially_charged charge_failed refunded disputed withdrawn
origin
required

How the card was asked for.

  • online_booking: the guest saved it while booking in the restaurant’s widget.
  • staff_request: the guest was sent a link to save it — by the restaurant, or because the booking was created through this API.
  • waitlist_offer: the guest saves it to claim a place offered from the waitlist.
string
Allowed values: online_booking staff_request waitlist_offer
amount
required

The most that can be charged, as the guest accepted it: in the minor unit of currency (cents), so 4000 is €40.00. Covers the whole party.

integer
currency
required

ISO 4217 currency code of every amount on this object, e.g. EUR.

string
charged_amount
required

How much has been charged so far, in minor units of currency. 0 when nothing has.

integer
refunded_amount
required

How much of charged_amount has been refunded, in minor units of currency. 0 when nothing has.

integer
card
required

null until the guest saves a card, and on a guarantee that never had one. Once a card is saved, its brand and the last four digits of its number; last4 can be null when the card network does not report it.

object
brand
required

The card network, as the payment processor reports it, e.g. visa.

string
last4
required

The last four digits of the card number.

string
nullable
cancel_deadline_at
required

Until when the guest can cancel without being charged: ISO 8601 with the restaurant’s UTC offset. A cancellation after it may be charged. null means cancelling is always free and only a no-show is charged.

string format: date-time
nullable
expires_at
required

While state is awaiting_card, the deadline for the guest to save a card, in the same format. null in every other state.

string format: date-time
nullable
consented_at

When the terms the guest accepts were recorded, in the same format: when the card was saved in the booking widget, or when the request was sent for a card asked for by link. null on a widget booking whose card is not saved yet.

string format: date-time
nullable
created_at
required

When the guarantee was created, in the same format.

string format: date-time
updated_at
required

When the guarantee last changed, in the same format.

string format: date-time
metadata

Your own reconciliation data, echoed verbatim on every read and webhook; {} when there is none.

Set once, when the booking is made, and never changed afterwards — PATCH refuses it. It comes from metadata on POST /v1/reservations, or from the hold the booking was converted from. A booking made in the restaurant’s own widget carries metadata only when the widget was embedded by a partner platform that signed it into its identity assertion; an unsigned widget booking never has any.

⚠️ Readable by every integration this restaurant has authorised, not only by the one that wrote it. Put reconciliation ids here, not commercial terms.

object
key
additional properties
any
events

The booking’s lifecycle events, oldest first — the same list GET /v1/reservations/{id}/events returns. Present only when you pass ?expand=events on a read, which needs no scope beyond reservations:read; absent otherwise, never an empty stand-in.

Array<object>
object
object
required

The object type: always reservation_event.

string
Allowed values: reservation_event
id
required

The event’s id, evt_…. Opaque and permanent. Not the id of the webhook event that announced the same change: the two are numbered separately.

string
type
required

What happened, named like the webhook event for the same change.

  • reservation.created: the booking was made.
  • reservation.pending: it became a request awaiting the restaurant’s decision.
  • reservation.confirmed: the restaurant accepted it.
  • reservation.declined: the restaurant turned the request down.
  • reservation.updated: its details or its tables changed.
  • reservation.partially_seated: part of the party was seated.
  • reservation.seated: the party was seated.
  • reservation.completed: the party left.
  • reservation.cancelled: it was cancelled — data.cancellation_reason says how.
  • reservation.no_show: the party did not come.
string
Allowed values: reservation.created reservation.confirmed reservation.declined reservation.updated reservation.pending reservation.partially_seated reservation.seated reservation.completed reservation.cancelled reservation.no_show
created_at
required

When it happened: ISO 8601 with the restaurant’s UTC offset.

string format: date-time
data
required

What changed, keyed per event type — statuses as from_status/to_status, field edits under changes. Internal ids, staff identity and the staff’s own notes are stripped. Treat the key set as open.

Six keys carry the guest’s own data and appear only when your key could read that field on the booking — that is, when it carries guests:read:

  • contact_email, contact_phone, guest_notes — the booking’s own contact details and the note the guest left, inside changes when one of them is edited.
  • submitted_guest_name, submitted_email, submitted_phone — on the reservation.created event, what the booker actually typed, recorded when it differs from the guest profile the booking was matched to.

On reservation.cancelled, cancellation_reason says who ended the booking and how:

  • partner_api is a cancel YOU made through POST /v1/reservations/{id}/cancel.
  • guest_self_service is the guest cancelling from their own manage link.
  • guarantee_expired is a card request that lapsed unpaid.

Anything else was typed by the restaurant; match on the three named values and pass the rest through.

object
key
additional properties
any
modification_token

The guest’s own credential for their booking page. That page is on the booking host that public_booking_url in GET /v1/configuration names, not on this API, and the link is {public_booking_url}/{modification_token}, the same link the confirmation e-mail sends the guest.

Whoever holds it can do on that page everything the guest can: read, change or cancel the booking and, while it is awaiting_guarantee, complete the card step. Pass it only to the guest, as the link to their own page; never log it, display it or keep it longer than you need it. The endpoints behind that page are the booking widget’s, not part of this API.

⚠️ Present ONLY on the POST /v1/reservations response, and only when you ask with ?expand=modification_token and your key carries guests:read (it reads the guest’s contact details, so it is gated like the guest book). Reads, lists and webhooks never carry it — capture it at create time. Never null when present.

How long it lasts. It is minted once, when the booking is created, and never rotates: the value you capture is the value that booking keeps. It carries no expiry of its own and stays usable for as long as the booking is live, which in practice means until the party has been and gone. Cancelling — by you, by the guest or by a card request lapsing — retires it, and so does the restaurant marking the booking a no-show: the page answers 404 from then on, exactly as it does for a token that was never issued. There is no way to revoke it while the booking stands, which is the other half of “never log it”: if it leaks, the remedy is to cancel and rebook.

string
created_at
required

When the booking was recorded: ISO 8601 with the restaurant’s UTC offset.

string format: date-time
updated_at
required

When anything on the booking last changed, in the same format. The value updated_since compares against.

string format: date-time
Example
{
"object": "reservation",
"status": "awaiting_guarantee",
"source": "manual",
"booking_channel": "back_office",
"guest_notifications": "service_managed",
"guest": {
"object": "guest",
"language": "fr",
"source": "manual"
},
"company": {
"object": "company"
},
"tables": [
{
"object": "table",
"section": {
"object": "section",
"area_type": "indoor"
}
}
],
"guarantee": {
"object": "guarantee",
"kind": "imprint",
"state": "awaiting_card",
"origin": "online_booking"
},
"events": [
{
"object": "reservation_event",
"type": "reservation.created"
}
]
}
Service-Version
string

Dated API version applied

Idempotent-Replayed
string
Allowed values: true

Present, as true, only when this response replays an earlier request with the same Idempotency-Key; the body is that original response, verbatim. Absent on a first write.

Nothing to modify, or a field that cannot be changed

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"
}
}

No API key, or not a live one

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"
}
}
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.

The API key does not carry the reservations:write 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"
}
}
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.

No such reservation

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"
}
}
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.

The booking is finalized

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 change breaks the restaurant’s booking rules

Media typeapplication/json
Any of:

The 422 a write answers with when it broke the restaurant’s booking rules: the envelope above plus the itemised violations. No other status carries that array.

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

Every booking rule this request broke, itemised. The whole array is the refusal: the top-level code is the fixed umbrella booking_rules_violated and the top-level message one fixed sentence, for one broken rule as for six. Only a 422 carries it.

Array<object>
object
code
required

The rule that was broken, e.g. cutoff_passed.

string
message
required

A human-readable explanation of this violation.

string
param

The request field to change to satisfy the rule, when there is one. Absent — not null — otherwise.

string
overridable
required

Whether a key carrying reservations:write:override may re-submit with this code in override and have the rule waived.

boolean
conflicts

Only on section_occupied: what already holds part of the room during the window — one entry per occupied table, with the time it is held from and to. Never who holds it. Absent on every other code.

Array<object>
object
table
required

The occupied table (tbl_…). Null when the room has no tables and another whole-room booking holds it.

string
nullable
start_time
required

When the table is held from: HH:MM on the service_date the request named, in the restaurant’s timezone. Read on the service’s own axis, which runs past midnight — a 00:30 against a 23:30 is half an hour later the same night, not 23 hours earlier.

string
end_time
required

When the table is held until, on the same clock and the same axis as start_time. null for a booking stored without an end time.

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

Too many requests on the write 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 write burst

RateLimit-Remaining
integer

Requests remaining in the write burst

RateLimit-Reset
integer

Seconds until the write bucket refills

RateLimit-Resource
string

Which budget the numbers describe. write 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.