---
title: "Get the menu"
description: "Categories and products for an order type. A restaurant can run menu plans\nthat change prices or show some products only at certain times. The\nmenu, the product and the quote all follow the plan of the pickup or\ndelivery moment, exactly as the order is charged.\n\nCategories are in display order; hidden and empty categories are left\nout. Products not offered for `orderType` are left out.\n"
---

> Documentation Index
> Fetch the complete documentation index at: https://developer.unipage.be/llms.txt
> Use this file to discover all available pages before exploring further.

Path: Storefront API › Menu

`GET /menu`

Categories and products for an order type. A restaurant can run menu plans
that change prices or show some products only at certain times. The
menu, the product and the quote all follow the plan of the pickup or
delivery moment, exactly as the order is charged.

Categories are in display order; hidden and empty categories are left
out. Products not offered for `orderType` are left out.

## Authentication

Requires one of the following:

- `publicKey`, apiKey, in header, header `X-Unipage-Key`
- `secretKey`, http, header `Authorization`

## Query parameters

- `orderType` (`getMenu.query.orderType`; string, required) — The order type to read for.
  - one of `"TAKEOUT"`, `"DELIVERY"`
- `at` (`getMenu.query.at`; integer, optional) — Unix seconds of the chosen slot, default now. Prices and visibility follow the menu plan of that moment.

## Code samples

### cURL

```bash
curl --request GET \
  --url 'https://api.unipage.eu/storefront/v1/menu?orderType=TAKEOUT' \
  --header 'X-Unipage-Key: <X-Unipage-Key>'
```

### TypeScript

```typescript
const url = 'https://api.unipage.eu/storefront/v1/menu?orderType=TAKEOUT';
const options = {method: 'GET', headers: {'X-Unipage-Key': '<X-Unipage-Key>'}};

fetch(url, options)
  .then(res => res.json())
  .then(json => console.log(json))
  .catch(err => console.error(err));
```

### Python

```python
import requests

url = "https://api.unipage.eu/storefront/v1/menu?orderType=TAKEOUT"

headers = {"X-Unipage-Key": "<X-Unipage-Key>"}

response = requests.get(url, headers=headers)

print(response.text)
```

## Responses

### 200

The menu.

#### Example

```json
{
  "categories": [
    {
      "id": "c4n2w",
      "name": "Fries",
      "description": "string",
      "image": "string",
      "products": [
        {
          "id": "p7d2x",
          "name": "Medium fries",
          "description": "string",
          "price": 4,
          "priceType": "PER_UNIT",
          "image": "string",
          "available": true,
          "soldOut": true,
          "hasOptions": true,
          "maxPerOrder": 0,
          "allergens": [
            "gluten",
            "nuts"
          ],
          "allergenSources": {
            "gluten": [
              "wheat"
            ],
            "nuts": [
              "almonds"
            ]
          }
        }
      ]
    }
  ]
}
```

- `categories` (`getMenu.response.200.categories`; array<object>, optional) — In display order. Hidden and empty categories are left out.
  - `id` (`getMenu.response.200.categories.id`; string, optional)
  - `name` (`getMenu.response.200.categories.name`; string, optional)
  - `description` (`getMenu.response.200.categories.description`; string | null, optional)
  - `image` (`getMenu.response.200.categories.image`; string | null, optional)
  - `products` (`getMenu.response.200.categories.products`; array<object>, optional)
    - `id` (`getMenu.response.200.categories.products.id`; string, optional)
    - `name` (`getMenu.response.200.categories.products.name`; string, optional)
    - `description` (`getMenu.response.200.categories.products.description`; string | null, optional)
    - `price` (`getMenu.response.200.categories.products.price`; number, optional)
    - `priceType` (`getMenu.response.200.categories.products.priceType`; string, optional) — Products priced by weight are not supported.
      - one of `"PER_UNIT"`
    - `image` (`getMenu.response.200.categories.products.image`; string | null, optional) — Image URL.
    - `available` (`getMenu.response.200.categories.products.available`; boolean, optional) — `false` means not orderable right now: show it greyed out.
    - `soldOut` (`getMenu.response.200.categories.products.soldOut`; boolean, optional) — `true` means out of stock.
    - `hasOptions` (`getMenu.response.200.categories.products.hasOptions`; boolean, optional) — Get the product to read its option groups.
    - `maxPerOrder` (`getMenu.response.200.categories.products.maxPerOrder`; integer | null, optional)
    - `allergens` (`getMenu.response.200.categories.products.allergens`; array<string>, optional)
      - one of `"gluten"`, `"crustaceans"`, `"eggs"`, `"fish"`, `"peanuts"`, `"soybeans"`, `"milk"`, `"nuts"`, `"celery"`, `"mustard"`, `"sesame"`, `"sulphur_dioxide"`, `"lupine"`, `"molluscs"`
    - `allergenSources` (`getMenu.response.200.categories.products.allergenSources`; map<array<string>>, optional) — The specific cereal (`wheat`, `spelt`, `khorasan`, `rye`, `barley`, `oats`) or nut (`almonds`, `hazelnuts`, `walnuts`, `cashews`, `pecans`, `brazil_nuts`, `pistachios`, `macadamia`) per allergen, when the restaurant recorded it. EU food-information rules ask you to show it before the order is placed: "gluten (wheat)".

### 401

A missing, unknown or revoked key (`UNAUTHENTICATED`).

#### Example

```json
{
  "error": {
    "code": "UNAUTHENTICATED",
    "message": "No valid key."
  }
}
```

- `error` (`getMenu.response.401.error`; object, required)
  - `code` (`getMenu.response.401.error.code`; string, required)
    - one of `"UNAUTHENTICATED"`, `"FORBIDDEN"`, `"NOT_FOUND"`, `"METHOD_NOT_ALLOWED"`, `"VALIDATION"`, `"SLOT_UNAVAILABLE"`, `"DELIVERY_UNAVAILABLE"`, `"PRODUCT_UNAVAILABLE"`, `"COUPON_INVALID"`, `"MINIMUM_NOT_REACHED"`, `"RATE_LIMITED"`, `"INTERNAL"`
  - `message` (`getMenu.response.401.error.message`; string, required) — Human readable.
  - `fields` (`getMenu.response.401.error.fields`; map<string>, optional) — Only present when the error belongs to specific request fields.

### 403

A public key on a secret route, or used from an origin that is not
registered for it (`FORBIDDEN`).

#### Example

```json
{
  "error": {
    "code": "FORBIDDEN",
    "message": "Origin not registered for this key."
  }
}
```

- `error` (`getMenu.response.403.error`; object, required)
  - `code` (`getMenu.response.403.error.code`; string, required)
    - one of `"UNAUTHENTICATED"`, `"FORBIDDEN"`, `"NOT_FOUND"`, `"METHOD_NOT_ALLOWED"`, `"VALIDATION"`, `"SLOT_UNAVAILABLE"`, `"DELIVERY_UNAVAILABLE"`, `"PRODUCT_UNAVAILABLE"`, `"COUPON_INVALID"`, `"MINIMUM_NOT_REACHED"`, `"RATE_LIMITED"`, `"INTERNAL"`
  - `message` (`getMenu.response.403.error.message`; string, required) — Human readable.
  - `fields` (`getMenu.response.403.error.fields`; map<string>, optional) — Only present when the error belongs to specific request fields.

### 422

The request is not valid, see `fields` (`VALIDATION`).

#### Example

```json
{
  "error": {
    "code": "VALIDATION",
    "message": "The request is not valid.",
    "fields": {
      "products": "Unknown product."
    }
  }
}
```

- `error` (`getMenu.response.422.error`; object, required)
  - `code` (`getMenu.response.422.error.code`; string, required)
    - one of `"UNAUTHENTICATED"`, `"FORBIDDEN"`, `"NOT_FOUND"`, `"METHOD_NOT_ALLOWED"`, `"VALIDATION"`, `"SLOT_UNAVAILABLE"`, `"DELIVERY_UNAVAILABLE"`, `"PRODUCT_UNAVAILABLE"`, `"COUPON_INVALID"`, `"MINIMUM_NOT_REACHED"`, `"RATE_LIMITED"`, `"INTERNAL"`
  - `message` (`getMenu.response.422.error.message`; string, required) — Human readable.
  - `fields` (`getMenu.response.422.error.fields`; map<string>, optional) — Only present when the error belongs to specific request fields.

### 429

Too many requests (`RATE_LIMITED`). Wait `Retry-After` seconds.

#### Example

```json
{
  "error": {
    "code": "RATE_LIMITED",
    "message": "Too many requests."
  }
}
```

- `error` (`getMenu.response.429.error`; object, required)
  - `code` (`getMenu.response.429.error.code`; string, required)
    - one of `"UNAUTHENTICATED"`, `"FORBIDDEN"`, `"NOT_FOUND"`, `"METHOD_NOT_ALLOWED"`, `"VALIDATION"`, `"SLOT_UNAVAILABLE"`, `"DELIVERY_UNAVAILABLE"`, `"PRODUCT_UNAVAILABLE"`, `"COUPON_INVALID"`, `"MINIMUM_NOT_REACHED"`, `"RATE_LIMITED"`, `"INTERNAL"`
  - `message` (`getMenu.response.429.error.message`; string, required) — Human readable.
  - `fields` (`getMenu.response.429.error.fields`; map<string>, optional) — Only present when the error belongs to specific request fields.


Source: https://developer.unipage.be/storefront/api/menu/retrieve/index.md
