Use v3 menus as an integrator
End-to-end guide for reading, editing, publishing, exporting, and snoozing menus through the Flipdish Menu Management API.
Use v3 menus as an integrator
This guide walks you through working with menus through the Flipdish Menu Management API. It covers the lifecycle an integrator typically owns: discovering menus, reading the current version, editing, running publish checks, publishing a revision to sales channels, exporting for third-party channels, and snoozing items when something runs out.
BetaThe Menu Management API is currently in beta and may change without notice. We'll document any breaking change in release notes, but pin your integration to specific revisions and handle unknown fields defensively.
Menu v3 (within the v3.0 API suite)"v3" here refers to the menu version — menus have their own version number (v3 is current; v2 was the previous generation). That's distinct from the Flipdish API version: the Menu Management API documented in this guide is part of the Flipdish v3.0 API suite, alongside Sales Management, Org Management, and the rest. This guide covers the v3 menu lifecycle. If you're still integrating against v2 menus, the flow here doesn't apply.
Known issues (as of publication)Several endpoints currently have gaps that will affect integrations following this guide end-to-end. We're actively tracking fixes. In order of impact:
- Publishing a newly-created menu may not take effect.
POST /menuManagement/.../revisions/{revisionId}/publishcan fail with"No storefronts are associated with this menu"even after a successful save. There is no public endpoint today that bridges a menu created through this API to a sales channel. Please contact us before building on end-to-end publish for new menus — see Report an issue or give feedback.- Pricing is not persisted on
PUT /menus/{menuId}. The endpoint returns200and increments the revision, butpricingProfilescome back empty on the follow-upGET .../current. Structural edits (categories, items, names, allergens) do persist.GET .../revisions/{revisionId}/publishCheckreturns HTTP 500 with"Menu header not found". You can't programmatically validate a revision before publish today.GET /menuManagement/orgs/{orgId}/menus/{menuId}/revisionsreturns HTTP 500. UseGET .../menus/{menuId}/currentfor the current draft (and fetch an individual revision by id withGET .../revisions/{revisionId}if you've persisted one) until this is fixed.None of this blocks the read / save-draft path. If you hit any of the above, or see behaviour that contradicts this guide, please let us know via Report an issue or give feedback.
Prerequisites
Before you start, make sure you have:
- A Flipdish OAuth2 client with access to the Menu Management API. See Getting Started for how to create one and request an access token.
- Your
orgId; every Menu Management path is scoped to an org:/menuManagement/orgs/{orgId}/.... - A working understanding of the v3 menu shape. Read Menu Structure v3.0 first; this guide assumes you already know what a Category, Item, Modifier, ModifierMember, PricingProfile, CategoryGroup, and AvailabilityOverride are.
All examples use:
- Base URL:
https://api.flipdish.co - Auth header:
Authorization: Bearer <your access token>
How the API is shaped
The Menu Management API is coarse-grained. There are no per-category or per-item endpoints; you work on the whole menu document (the shape described in Menu Structure v3.0). Every write is a full replacement of the menu body.
Operations fall into three groups:
| Group | Purpose |
|---|---|
| Menu Management | List, create, read, update, and archive menus. |
| Menu Management - Revisions | List revisions, read a specific revision, validate it, publish it to sales channels, or export it. |
| Menu Management - Snooze | Temporarily hide items without editing the menu itself. |
Menus vs. revisions
In v3, a menu has a current (latest) version and a list of revisions. Every PUT /menus/{menuId} creates a new revision and bumps revisionId — there is no in-place draft that multiple saves write to. A revision becomes live only when it's published to one or more sales channels.
This means each save is its own immutable snapshot: you can iterate on a menu by PUTing it multiple times, then pick any resulting revisionId to validate and publish.
Complete endpoint reference
All paths are relative to https://api.flipdish.co and scoped by orgId.
Menus
| Method | Path | Purpose | Reference |
|---|---|---|---|
GET | /menuManagement/orgs/{orgId}/menus/headers | List menu headers (lightweight index). Supports includeArchived. | get menu headers |
GET | /menuManagement/orgs/{orgId}/menus/published | List every menu that currently has a published revision. | get published menus |
POST | /menuManagement/orgs/{orgId}/menus | Create a new menu (body: CreateMenuSchema). | create menu |
GET | /menuManagement/orgs/{orgId}/menus/{menuId}/current | Fetch the current (latest) version of a menu. | get current menu |
PUT | /menuManagement/orgs/{orgId}/menus/{menuId} | Replace the menu in place (body: UpdateMenuSchema). | update menu |
DELETE | /menuManagement/orgs/{orgId}/menus/{menuId} | Archive (soft-delete) the menu. | archive menu |
Revisions
| Method | Path | Purpose | Reference |
|---|---|---|---|
GET | /menuManagement/orgs/{orgId}/menus/{menuId}/revisions | List all revisions of the menu. | list revisions |
GET | /menuManagement/orgs/{orgId}/menus/{menuId}/revisions/{revisionId} | Fetch a specific revision. | get revision |
GET | /menuManagement/orgs/{orgId}/menus/{menuId}/revisions/{revisionId}/publishCheck | Validate whether the revision is publishable. | publish check |
POST | /menuManagement/orgs/{orgId}/menus/{menuId}/revisions/{revisionId}/publish | Publish the revision to the supplied selectedSalesChannelIds. | publish revision |
GET | /menuManagement/orgs/{orgId}/menus/{menuId}/revisions/{revisionId}/export/{channel} | Export the revision in a channel-specific format. Supports referencePriceDispatchType. | export revision |
Snooze
| Method | Path | Purpose | Reference |
|---|---|---|---|
GET | /menuManagement/orgs/{orgId}/menus/{menuId}/snoozes | List the current snooze state for items. Filter by propertyIds. | list snoozes |
POST | /menuManagement/orgs/{orgId}/menus/{menuId}/snoozes | Snooze one or more items (body: array of PublicSnoozeItemSchema). | snooze items |
POST | /menuManagement/orgs/{orgId}/menus/{menuId}/un-snoozes | Un-snooze items (body: array of PublicUnSnoozeItemSchema). | un-snooze items |
End-to-end integrator flow
A typical integration follows these steps. The sections below show a runnable curl example for each.
- Authenticate and obtain an access token.
- Discover the menus that belong to the org.
- Fetch the current menu.
- Edit the menu and
PUTit back; this creates a new revision. - Validate the revision with a publish check.
- Publish the revision to the chosen sales channels.
- Optionally export the revision for external channels, or snooze items.
1. Authenticate
curl --request POST \
--url https://api.flipdish.co/identity/connect/token \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data grant_type=client_credentials \
--data client_id=<your_client_id> \
--data client_secret=<your_client_secret> \
--data scope=apiThe response includes an access_token that you pass as Authorization: Bearer <token> on every subsequent call.
2. List menus
Start from the menu headers endpoint; it returns a lightweight index so you can pick the menu you want to work with without pulling the full document.
curl --request GET \
--url 'https://api.flipdish.co/menuManagement/orgs/<orgId>/menus/headers?includeArchived=false' \
--header 'Authorization: Bearer <access_token>'If you only care about what's currently live for the customer, call the published-menus endpoint instead:
curl --request GET \
--url 'https://api.flipdish.co/menuManagement/orgs/<orgId>/menus/published' \
--header 'Authorization: Bearer <access_token>'3. Fetch the current menu
Once you have a menuId, pull the current working version. This is the full menu document; see Menu Structure v3.0 for the shape.
curl --request GET \
--url 'https://api.flipdish.co/menuManagement/orgs/<orgId>/menus/<menuId>/current' \
--header 'Authorization: Bearer <access_token>'Hold onto the returned revisionId; you'll need it when you publish.
4. Edit and save
The update endpoint replaces the entire menu. Fetch the current menu, mutate the fields you care about (add a category, reprice an item, add a modifier member, etc.), then PUT the full document back. Every PUT creates a new revision and bumps revisionId — each save is a fresh, immutable snapshot, not an in-place edit of an existing draft. Re-fetch GET .../current after each save to pick up the new revisionId.
curl --request PUT \
--url 'https://api.flipdish.co/menuManagement/orgs/<orgId>/menus/<menuId>' \
--header 'Authorization: Bearer <access_token>' \
--header 'Content-Type: application/json' \
--data @updated-menu.json
Known issue — pricing is not persistedOn a
PUT /menus/{menuId}the response is200and structural edits (categories, items, names, allergens) persist, butpricingProfileson items are silently dropped — they come back empty on the follow-upGET .../currentregardless oftaxableor*TaxablePricevalues you send. We're tracking this; use the admin UI to set pricing in the meantime, and let us know if it's blocking you.
Guidelines for edits
- Preserve IDs you don't own. If an item already has an
id, keep it; changing or omitting it can create a new entity instead of updating the existing one. - Keep the top-level menu
idin the body.UpdateMenuSchemalists it as required; omitting it will fail validation. - Keep cross-references intact.
ModifierMember.parentModifierIdmust point at aModifier.idthat exists in the same menu, andCategoryGroup.categoryIdsmust reference validCategory.ids. - Every item needs a
PricingProfilefor each price band your property uses, with prices filled in for every dispatch type (collectionPrice,deliveryPrice,dineInPrice,takeawayPrice). (See the known issue above about pricing persistence.) AvailabilityOverriderules are the right place to express "weekday lunch only" or "Deliveroo-only" variants; do not duplicate items to model availability.
To create a fresh menu instead of updating, POST to /menuManagement/orgs/{orgId}/menus with a CreateMenuSchema body.
5. Run a publish check
Before publishing, validate the revision. The publish-check endpoint returns any structural or business-rule violations that would block a publish, so you can surface them to the user (or fail your CI job) without touching any customer-facing channel.
curl --request GET \
--url 'https://api.flipdish.co/menuManagement/orgs/<orgId>/menus/<menuId>/revisions/<revisionId>/publishCheck' \
--header 'Authorization: Bearer <access_token>'
Known issue — endpoint currently returns HTTP 500
publishCheckis currently returning500with{"error":{"message":"Menu header not found","code":"unknown_error"}}on every call, including against revisions that are visible inGET .../menus/headers. Skip this step until fixed, or rely on the errors returned by thepublishcall itself. Please report any occurrences so we can prioritise the fix.
6. Publish the revision
Publishing is atomic across the sales channels you pass. You choose the revision, you choose the channels; nothing else goes live until you call this.
curl --request POST \
--url 'https://api.flipdish.co/menuManagement/orgs/<orgId>/menus/<menuId>/revisions/<revisionId>/publish' \
--header 'Authorization: Bearer <access_token>' \
--header 'Content-Type: application/json' \
--data '{
"selectedSalesChannelIds": ["sc123", "sc456"]
}'selectedSalesChannelIds must contain at least one ID. To roll back, publish an earlier revisionId to the same channel list.
Known issue — new menus may not publishCalls can currently fail with
invalid_request: "No storefronts are associated with this menu. You cannot publish a menu without any storefronts"even when the menu was created and saved successfully through this API, and there is no public endpoint today that associates a new Menu-Management-API menu with a sales channel. Publishing updates to existing menus already associated with a sales channel works; publishing a brand-new menu end-to-end through the public API does not yet. (The error message still uses the legacy term "storefronts"; read it as "sales channels".) If your integration needs to stand up a new menu, contact us first — we'll confirm the supported path for your use case.
7. Export (optional)
If you need the revision in an external channel's format (for example, to ship to a marketplace), call the export endpoint with the channel identifier.
curl --request GET \
--url 'https://api.flipdish.co/menuManagement/orgs/<orgId>/menus/<menuId>/revisions/<revisionId>/export/<channel>?referencePriceDispatchType=Delivery' \
--header 'Authorization: Bearer <access_token>'referencePriceDispatchType controls which of the four PricingProfile prices (Collection, Delivery, DineIn, TakeAway) is used as the reference price when the target format only supports a single price per item.
Working with revisions
Revisions are immutable once created, and a new one is produced on every PUT /menus/{menuId}. Use them to:
- Audit what changed, when, and by whom;
GET .../revisions/{revisionId}returns the full body of a specific revision. - Roll back by publishing a known-good earlier revision.
- Coordinate multiple channels; you can publish the same revision to additional channels later without re-saving the menu.
Known issue — listing all revisions currently returns HTTP 500
GET /menuManagement/orgs/{orgId}/menus/{menuId}/revisionsis currently failing with a response-validation error on anarchivedfield. In the meantime, read the latestrevisionIdfromGET .../menus/{menuId}/currentafter each save, and store revision IDs yourself as you create them.GET .../revisions/{revisionId}(single revision) is unaffected.
Snoozing items
Snoozing temporarily removes items from the live menu without editing the menu body. This is the right tool for "we're out of fish today"; the edit is lightweight, doesn't require a publish, and is reversible in a single call.
List the current snooze state (optionally scoped to specific stores with propertyIds):
curl --request GET \
--url 'https://api.flipdish.co/menuManagement/orgs/<orgId>/menus/<menuId>/snoozes?propertyIds=prop123&propertyIds=prop456' \
--header 'Authorization: Bearer <access_token>'Snooze items by POSTing an array of snooze entries:
curl --request POST \
--url 'https://api.flipdish.co/menuManagement/orgs/<orgId>/menus/<menuId>/snoozes' \
--header 'Authorization: Bearer <access_token>' \
--header 'Content-Type: application/json' \
--data '[ { ... PublicSnoozeItemSchema ... } ]'Reverse a snooze with the un-snooze endpoint:
curl --request POST \
--url 'https://api.flipdish.co/menuManagement/orgs/<orgId>/menus/<menuId>/un-snoozes' \
--header 'Authorization: Bearer <access_token>' \
--header 'Content-Type: application/json' \
--data '[ { ... PublicUnSnoozeItemSchema ... } ]'Snooze vs. edit vs. availability override
| Scenario | Use |
|---|---|
| An item is temporarily unavailable (today, a few hours). | Snooze |
| An item is only available at certain times or on certain dispatch types. | AvailabilityOverride on the item |
| An item should be removed from the menu permanently, or its price/description is changing. | Edit + publish |
Archiving a menu
DELETE on a menu performs a soft delete; the menu is archived, not wiped. Archived menus stop appearing in the default GET .../menus/headers response; set includeArchived=true to see them.
curl --request DELETE \
--url 'https://api.flipdish.co/menuManagement/orgs/<orgId>/menus/<menuId>' \
--header 'Authorization: Bearer <access_token>'Error handling and best practices
- Send a User-Agent, required on every request. See User Agents.
- Handle errors consistently. The Flipdish API returns structured error responses; see Error Handling.
- Be defensive on reads. Since the API is in beta, unknown fields can appear in responses. Ignore what you don't understand rather than failing.
- Preserve round-trip fidelity. When you
GET .../current, edit, andPUTback, pass through fields you didn't intend to change (including IDs and cross-references) instead of regenerating the document. - Always publish-check before publish (once the known issue with
publishCheckis resolved). Errors caught inpublishCheckare cheaper than errors caught by a customer. - Treat a revisionId as a pointer to a frozen document. Every
PUTproduces a newrevisionId; after anyPUT, re-fetch.../currentto get the latest one before publishing or validating.
Report an issue or give feedback
This API is in beta and we're actively iterating. If you hit one of the known issues, see behaviour that contradicts this guide, or have feedback on the shape of the API, please get in touch:
- Email [email protected].
- Visit help.flipdish.com for support articles and to file a ticket.
To help us diagnose quickly, include:
- Your
orgId. - The
menuIdandrevisionIdinvolved. - The HTTP method and full path you called.
- Your request body (redact any secrets).
- The full response body and any
x-request-id/ correlation IDs from the response headers. - The approximate time (UTC) of the call.
That context lets us correlate your calls with server logs directly.
Related reading
- Menu Structure v3.0, the shape of the menu document
- Getting Started, OAuth2 setup
- Error Handling
- User Agents
