---
title: "Upsert menus for a store"
method: POST
path: "/v1/menus"
tags: ["menus_endpoints"]
---

# Upsert menus for a store

`POST /v1/menus`

## Request

- Base URL: `https://partners.tryotter.com`
- URL: `https://partners.tryotter.com/v1/menus`
- Auth: OAuth 2
  - Authorization code: `/v1/auth/oauth2/authorize`
  - Client credentials
  - Token URL: `/v1/auth/token` scopes: `menus.upsert`
- TypeScript: <https://skmtc.dev/cloudkitchens/apis/otter-api/docs/v1/menus/post.ts> (a function with typed inputs; its response is checked against the schema)

Replaces the store's complete menu snapshot. Include every customer-menu entity that should remain; omitted entities are deleted. An omitted station item can remain when an existing customer-item association prevents its deletion.
Repeating the same complete payload is safe and produces the same menu state.
Rate limit: 2 requests per minute.

## Headers

- `X-Store-Id` string, required: The unique identifier of the store in your app. This ID, along with the `Application ID`, will be used to match the correct store when performing operations. It cannot be longer than 255 characters and must only contain printable ASCII characters. During on-boarding, this ID will be similar to `onboarding:905bb725-b141-4a9b-832a-1f254f772c94` (where the UUID is the Internal Store ID). During off-boarding, this field will be filled with the last known Store ID, or with an empty string, in case none is found. In that case, please fall back to the provided `internalStoreId` (a.k.a. Sku-Sku ID).

## Request body

- MenusUpsertRequest: Complete menu snapshot for a store. This is replacement semantics, not a partial patch: customer-menu entities omitted from the request are deleted. Include every menu, category, item, modifier group, attachment, and external data record that should remain. An omitted station item can be retained when an existing customer-item association prevents its deletion.
  - `categories` object, required
  - `modifierGroups` object, required
  - `menus` object, required
  - `items` object

## Response `202`

The menu update will be processed.

- MenuAsynchronousJob: The job created to process the menu request.
  - `jobReference` JobReference: The job reference.
    - `id` string, uuid: Unique identifier of the job.
    - `status` 'PENDING' | 'FAILED' | 'SUCCESS' | 'UNKNOWN': The status of the job.
  - `jobType` 'UPSERT' | 'PUBLISH' | 'UPDATE_AVAILABILITY' | 'SYNC' | 'UNKNOWN': Type of job.
  - `publishJobState` MenuJobPublishState, nullable: Only present if the MenuJobType is PUBLISH. Contains a map of MenuPublishTarget services to their corresponding statuses.

## Other responses

- `400`: The request is malformed.
- `401`: Invalid authorization.
- `403`: Authorization not valid for the requested resource.
- `404`: Resource not found.
- `422`: The request body is not valid.

---

[API](https://skmtc.dev/cloudkitchens/apis/otter-api.md) - [All operations](https://skmtc.dev/cloudkitchens/apis/otter-api/llms.txt) - [OpenAPI document](https://skmtc.dev/cloudkitchens/apis/otter-api/revisions/4c868194a467?raw)
