Skip to navigation

Request a table reservation

Creates a table reservation request. The restaurant approves or rejects it from its dashboard, and the guest gets an email when that happens (if you sent guestEmail). A new request always has status: "PENDING_APPROVAL" and tableId: null; the table is assigned on approval.

Follow the status with GET /orders/{token} using publicToken, or listen for the RESERVATION_APPROVED and RESERVATION_REJECTED webhooks. reservationId is the ID that webhooks call orderId.

The server checks the party size, the minimum notice and whether online booking is open. It does not check the time against opening hours or existing bookings, so only offer times from GET /dine-in/availability.

Idempotency-Key is supported. A replay with the same key and the same body returns the existing request with status 200 and idempotent: true; the same key with a different body returns 409 IDEMPOTENCY_CONFLICT.

Rate limit: 20 requests per 60 seconds per slug and IP. Walkthrough: Table reservations.

Authentication

AuthorizationBearer

Either this or a trusted browser origin. The restaurant’s API key, sent as Authorization: Bearer lbs_…. Use it from your server only, never in browser code. Keys are issued per restaurant by LettBestilt.

OR
Originstring

Either this or an API key. No key is needed when the request’s Origin header is trusted for this restaurant: https://{slug}.lettbestilt.no, a verified domain of the restaurant, or a partner origin LettBestilt has bound to the restaurant. Browsers set Origin themselves; it is not something you configure. Not accepted by GET /site-gate, which requires an API key.

Headers

Idempotency-KeystringOptionalformat: "^[A-Za-z0-9_-]+$"16-128 characters

Optional. 16–128 URL-safe characters (a-z, A-Z, 0-9, _, -).

Query parameters

slugstringRequired
The restaurant's slug.

Request

This endpoint expects an object.
dineInAtdatetimeRequired

Start time in UTC (ISO 8601). Use iso from GET /dine-in/availability.

partySizeintegerRequired1-50
Number of guests.
guestNamestringRequired<=120 characters
The guest's name.
guestEmailstringOptionalformat: "email"
Strongly recommended. Without it, the guest cannot be told when the request is approved or rejected.
guestPhonestringOptional<=40 characters
The guest's phone number.
notestringOptional<=500 characters
A note to the restaurant, for example about allergies or a high chair.
marketingOptInbooleanOptional

The guest’s consent to marketing. Requires guestEmail; the consent is stored in the restaurant’s subscriber list.

consentGivenAtdatetimeOptional

Optional. When the guest gave consent. Only allowed with marketingOptIn: true. If you leave it out, the server uses the time it received the request.

localeenumOptionalDefaults to nb
Language of the emails to the guest.
Allowed values:
attributedCampaignIdstringOptional<=64 characters

Campaign attribution: the value of ?lb_campaign=<id> from a LettBestilt campaign link. The reservation counts as a conversion for that campaign. Optional metadata: an invalid or unknown ID is dropped silently and never blocks the reservation. Note that orders call this field attributionCampaignId.

Response

The request was created.
reservationIdstringOptional

The reservation’s ID. Webhooks call it orderId.

publicTokenstringOptional

Use it with GET /orders/{token} to follow the status.

orderNumberintegerOptional
The number the restaurant sees in its dashboard.
statusenumOptional
Allowed values:
dineInAtdatetimeOptional
partySizeintegerOptional
tableIdstring or nullOptional

Always null when the request is created. Assigned when the restaurant approves it.

Errors

400
Bad Request Error
401
Unauthorized Error
404
Not Found Error
409
Conflict Error
422
Unprocessable Entity Error
429
Too Many Requests Error