> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.lettbestilt.no/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.lettbestilt.no/_mcp/server.

# Authentication

Every endpoint except order tracking needs one of two kinds of authentication: an API key, or a request from a trusted browser origin.

## API key (server to server)

Send the restaurant's API key as a bearer token:

```http
Authorization: Bearer lbs_...
```

* Keys are issued **per restaurant** by LettBestilt and start with `lbs_`.
* The full key is shown only once. LettBestilt stores only a hash and cannot show it again.
* When a key is rotated, the old one stops working immediately. Agree on a time with LettBestilt and deploy the new key right after.
* If a request has an `Authorization` header, the key is always checked. A wrong key fails with `401`, even from a trusted origin.

> **Warning**
>
> Use the key only from your server. Never put it in browser code, a mobile app or a public repository.

## Trusted browser origin

When your site calls the API directly from the browser, for example to validate a coupon as the customer types, the request is authenticated by its `Origin` header instead of a key. Browsers set `Origin` themselves; there is nothing to configure in your code.

An origin is trusted for a restaurant when it is:

* the restaurant's LettBestilt subdomain, `https://{slug}.lettbestilt.no`
* one of the restaurant's **verified domains**, for example `https://www.pizzaroma.no`

Ask LettBestilt to verify every hostname your site runs on. `pizzaroma.no` and `www.pizzaroma.no` are two different origins, so verify both if you use both. Only `https` origins are accepted.

A verified domain also:

* allows the domain through CORS (`Content-Type`, `Authorization` and `Idempotency-Key` are allowed request headers)
* allows it as `successUrl` and `cancelUrl` when you create orders

## Which endpoints need what

| Endpoint              | Authentication                             |
| --------------------- | ------------------------------------------ |
| `GET /orders/{token}` | None. The token is the secret              |
| `GET /site-gate`      | API key only. Browser origins are rejected |
| Everything else       | API key **or** trusted browser origin      |

## When authentication fails

The response is `401 UNAUTHORIZED`. `error.message` tells you why: a missing key, a wrong key, or an origin that is not trusted for this slug. See [Errors](/errors) for the envelope.