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

# Quickstart

This page gets you from an API key to a working menu. The [ordering flow guide](/build-an-ordering-flow) takes it from there to a paid order.

### Get an API key

LettBestilt issues one API key per restaurant. It starts with `lbs_` and is shown only once, so store it right away as a server-side environment variable, for example `LETTBESTILT_API_KEY`.

> **Warning**
>
> Never put the API key in browser code. Anything in a client bundle is public.

### Fetch the restaurant

Check that the key works and see what the restaurant offers:

**`cURL`**

```bash title="cURL"
curl "https://www.lettbestilt.no/api/v1/restaurant?slug=pizzaroma" \
  -H "Authorization: Bearer $LETTBESTILT_API_KEY"
```

**`TypeScript`**

```typescript title="TypeScript"
const API = "https://www.lettbestilt.no/api/v1";
const headers = { Authorization: `Bearer ${process.env.LETTBESTILT_API_KEY}` };

const res = await fetch(`${API}/restaurant?slug=pizzaroma`, { headers });
const { restaurant } = await res.json();

console.log(restaurant.name, restaurant.capabilities);
```

`restaurant.capabilities` tells you which flows to offer:

```json
{
  "pickup": true,
  "delivery": false,
  "reservations": true,
  "payment": { "online": true, "cash": true }
}
```

Build your UI from this object. If `delivery` is `false`, do not offer delivery.

### Fetch the menu

**`cURL`**

```bash title="cURL"
curl "https://www.lettbestilt.no/api/v1/menu?slug=pizzaroma" \
  -H "Authorization: Bearer $LETTBESTILT_API_KEY"
```

**`TypeScript`**

```typescript title="TypeScript"
const menu = await fetch(`${API}/menu?slug=pizzaroma`, { headers }).then((r) => r.json());

for (const category of menu.categories) {
  console.log(category.name);
  for (const product of category.products) {
    console.log(`  ${product.name}: kr ${product.basePrice / 100}`);
  }
}
```

Prices are integers in øre, so `12900` is kr 129,00. The response also has the restaurant's opening hours, delivery zones, coupons, promotions and allergens. It is cached for about 30 seconds and supports `ETag` / `If-None-Match`.

### Show the preparation time

The kitchen can turn on rush mode, which adds minutes to the preparation time. Show the live number from `/prep-time` instead of the cached one in the menu:

**`cURL`**

```bash title="cURL"
curl "https://www.lettbestilt.no/api/v1/prep-time?slug=pizzaroma" \
  -H "Authorization: Bearer $LETTBESTILT_API_KEY"
```

**`TypeScript`**

```typescript title="TypeScript"
const { prepTime } = await fetch(`${API}/prep-time?slug=pizzaroma`, { headers }).then((r) => r.json());

console.log(`Ready in about ${prepTime.pickupMinutes} minutes`);
```

> **Note**
>
> If you get `404 RESTAURANT_NOT_FOUND` for a slug you know exists, the restaurant has not been set live in LettBestilt yet. The API only answers for live restaurants.

## Next steps

#### [Build an ordering flow](/build-an-ordering-flow)

Cart, discounts, order creation, payment and tracking.

#### [Core concepts](/concepts)

Money, time, caching and order statuses.