Errors, rate limits and retries
Error format
Errors use one envelope:
Branch on code, never on message. message is written for people and is often in Norwegian; for business rules (sold out, closed, outside the delivery zone) it is usually fine to show the customer as it is. details is only present for some codes.
One exception to the envelope: 409 ONLINE_BOOKING_CLOSED from POST /reservations uses a flat shape, { "error": "…", "code": "ONLINE_BOOKING_CLOSED" }.
Rate limits
Limits are counted per client IP, and for most endpoints per restaurant as well:
Rate-limited responses include these headers:
When you call the API from your server, every customer shares your server’s IP. POST /orders then allows 10 orders per minute per restaurant from that server. Calls from the browser on a verified domain are counted per customer instead. Talk to LettBestilt if you expect more traffic than the limits allow.
Read the headers rather than hard-coding the numbers; they may change.
Idempotency
POST /orders and POST /reservations accept an Idempotency-Key header: 16 to 128 URL-safe characters (a-z, A-Z, 0-9, _, -). A UUID works well. Keys are scoped per restaurant, and orders and reservations share the same key space.
Create one key per checkout attempt, store it with the attempt, and reuse it only to retry that attempt.

