Create your first menu

Step-by-step guide with curl examples to go from zero to a saved menu — find your org, fetch a price band, create the menu, and add a category and item.

Create your first menu

This guide walks you through standing up a brand new menu in Flipdish from scratch using nothing but curl. You'll authenticate, find your org, fetch a price band, create an empty menu, and add a category and item.

This guide stops at "menu saved." It does not cover making the menu live for customers — for that, follow Publish your first menu once you've finished here.

If you already have menus and just want to read, edit, or publish an existing one, see Use v3 menus as an integrator.

🚧

Beta

The Menu Management API is currently in beta and may change without notice. Pin your integration to specific revisions and be defensive about unknown fields in responses.

🤖

Working with an AI assistant?

Each step below has a "💬 Ask an AI" block (collapsed by default — click the heading to expand) with a prompt you can paste into Claude, ChatGPT, Cursor, Copilot, or any other AI tool. Hover the code block to reveal the copy button. Every prompt uses placeholders like <MY_CLIENT_ID> instead of real values, so it's safe to copy as-is. Substitute your real values after the AI returns the command, not before. Never paste secrets (client secret, access token) into a chat window.

How everything fits together

Two things matter for creating a menu:

ConceptID prefixWhat it is
Orgorg123The top-level tenant. Every Menu Management path is scoped to an orgId.
MenumenuId (UUID)A document of categories, items, and modifiers that lives at the org level.

Menus are not attached to properties directly. A menu lives at the org level. Making it live at a particular property happens later, in the publish step, by linking a revision to one or more of that property's sales channels. That's covered in the publish guide; this guide just gets the menu document saved.

Prerequisites

  • A Flipdish OAuth App with access to the Org Management and Menu Management APIs. Create one in the Flipdish portal under My OAuth Apps. See Getting Started for the full walkthrough.
  • A working knowledge of the menu object. This guide uses a deliberately tiny example; for the full shape, see Menu Structure v3.0.
  • curl and jq (or any HTTP client and JSON parser).

All examples use:

Set up your session

This guide builds up a chain of values — access token, orgId, priceBandId, menuId, revisionId — that you'll reuse in every later step. Re-typing them gets old fast, and Claude Code's Bash tool runs each call in a fresh shell so anything exported in one tool call is gone by the next. The pattern below makes the values stick.

Create a file called .flipdish.env in your working directory with this content:

# --- Set these once ---
export FLIPDISH_BASE_URL=https://api.flipdish.co
export FLIPDISH_USER_AGENT='my-integration/1.0'
export FLIPDISH_CLIENT_ID=<your_client_id>
export FLIPDISH_CLIENT_SECRET=<your_client_secret>

# --- Captured by the steps below; do not edit by hand ---

<your_client_id> and <your_client_secret> are placeholders — you'll replace them with values from the Flipdish portal in the Fill in your credentials sub-section below.

Recommended flow

Do the credentials setup outside any AI chat, then come back to Claude Code (or stay in your terminal) for the rest of the guide. The steps below only need to source the file — your client_secret never has to cross the chat boundary.

The recommended sequence is:

  1. In a terminal outside Claude Code, create .flipdish.env with the heredoc below, fill in the real values from the Flipdish portal, and gitignore it.
  2. In Claude Code or your terminal, run steps 1–5 of this guide. Each step starts with source ./.flipdish.env and appends new captured values back to the file.

If you'd rather do everything in a terminal and skip Claude Code entirely, that works the same way — every snippet in this guide is plain curl + jq.

Create the file

In a terminal, paste this whole block in one go. The closing EOF must land flush-left with no leading whitespace — don't paste it indented (e.g. inside another quote block) and don't press Enter line-by-line:

cat > .flipdish.env <<'EOF'
# --- Set these once ---
export FLIPDISH_BASE_URL=https://api.flipdish.co
export FLIPDISH_USER_AGENT='my-integration/1.0'
export FLIPDISH_CLIENT_ID=<your_client_id>
export FLIPDISH_CLIENT_SECRET=<your_client_secret>

# --- Captured by the steps below; do not edit by hand ---
EOF

If your shell sits at a > continuation prompt after the paste, the heredoc didn't close — usually because the EOF line ended up indented. Press Ctrl-C to abort, then redo with no leading whitespace. Or skip the heredoc entirely: run cat > .flipdish.env, paste the body lines, and press Ctrl-D on a new line to close the redirect.

Or use your editor: paste the same content into a new file named .flipdish.env in your working directory and save.

Then gitignore it:

grep -qxF .flipdish.env .gitignore 2>/dev/null || echo .flipdish.env >> .gitignore

Fill in your credentials

Open .flipdish.env in your terminal $EDITOR and replace <your_client_id> and <your_client_secret> with the values from the OAuth App you created in the Flipdish portal:

"${EDITOR:-nano}" .flipdish.env

That falls back to nano (save with Ctrl-O, then Enter, then Ctrl-X to exit). Swap for vim, vi, code, subl, etc. as you prefer. On macOS, open -t .flipdish.env opens your default text editor; on most Linux desktops, xdg-open .flipdish.env does the same.

The portal labels are different from the OAuth2 spec terms used in this guide:

In the Flipdish portal (My OAuth Apps)In .flipdish.envOAuth2 spec name
OAuth App IDFLIPDISH_CLIENT_IDclient_id
Secret KeyFLIPDISH_CLIENT_SECRETclient_secret

Open your OAuth app in the portal, copy the OAuth App ID into FLIPDISH_CLIENT_ID, click the eye icon next to Secret Key to reveal it, and copy that into FLIPDISH_CLIENT_SECRET. (The "Owner User ID" shown alongside is informational — you don't need it for this guide.)

🔒

Don't put your client_secret in any AI chat

Anything you type into Claude Code's prompt (or any AI assistant) is sent to the model provider's API and stored on disk in your local conversation transcript. From there it can leak via screenshots, /resumed sessions, transcript exports, hooks, MCP servers, or subagents. Editing .flipdish.env in a terminal editor keeps the secret on your machine only.

If .flipdish.env ever leaks (or you suspect it has), rotate the Secret Key in the Flipdish portal under your OAuth App.

Use it from every step

Source it at the top of every shell command in this guide:

source ./.flipdish.env

As each step captures a new value (TOKEN, ORG_ID, PRICE_BAND_ID, MENU_ID, REVISION_ID), the example shows how to append it back into .flipdish.env. Repeated export lines in a sourced file are fine — the last one wins on the next source, so re-running a step (e.g. to refresh the token) just works.

🤖

Why this matters in Claude Code

Each Bash invocation in Claude Code is a fresh shell — export FOO=bar in one tool call is not visible to the next. Sourcing .flipdish.env at the top of every command and appending captured values back to the file is what makes variables persist across tool calls so neither you nor your AI assistant has to re-paste them.

When you ask an AI for help, include this rule in the prompt: "Always start commands with source ./.flipdish.env, and after capturing any new value, append it back via echo \"export VAR='$value'\" >> .flipdish.env."

💡

If you keep .flipdish.env open while running steps, reload it

Each step below appends new export ... lines to .flipdish.env as it captures values. If you've got the file open somewhere, that view is a snapshot from when you opened it — it won't refresh on its own.

  • Terminal editor — reload from disk. vim: :e!. nano: Ctrl-X to quit (answer N to discard the stale buffer), then re-open with nano .flipdish.env. GUI editors (VS Code, Cursor, etc.): close the tab and reopen, or run "Revert File" from the command palette.
  • Claude Code — every Read tool call hits disk fresh, so just ask Claude to re-read the file. File contents Claude saw earlier in the conversation are a snapshot from that prior Read, not a live view; treat them as stale once a step has run.

To check from any shell whether a value landed, without exposing the value itself:

grep -c '^export TOKEN=' .flipdish.env   # count of TOKEN lines (>= 1 means it's there)
tail -1 .flipdish.env | cut -c1-15       # first 15 chars of the last line

One-time scaffold via Claude Code (only if you haven't created the file yet)

If you're already inside Claude Code with no .flipdish.env on disk and no terminal handy, you can ask Claude to scaffold an empty template — then fill in the real values yourself in your editor.

⚠️

One-time only — do not re-run this prompt

The prompt below tells Claude to write .flipdish.env from scratch with placeholder credentials. If .flipdish.env already exists with real values, this would overwrite them. Claude Code will normally refuse to clobber a file with real-looking secrets, but don't rely on that — only run this prompt when the file doesn't exist yet, and never as a "reset" later.

💬 Scaffold .flipdish.env with placeholders — click to expand. Safe to copy: no secrets in this prompt. Hover the code block to copy.
Create a file called `.flipdish.env` in my current working directory
with exactly this content. Write the file directly using your
file-write tool — do NOT paste it back into chat, do NOT run it
through a shell heredoc, and do NOT ask me for any of the placeholder
values. If `.flipdish.env` already exists, STOP and tell me — do not
overwrite it.

# --- Set these once ---
export FLIPDISH_BASE_URL=https://api.flipdish.co
export FLIPDISH_USER_AGENT='my-integration/1.0'
export FLIPDISH_CLIENT_ID=<your_client_id>
export FLIPDISH_CLIENT_SECRET=<your_client_secret>

# --- Captured by the steps below; do not edit by hand ---

Then ensure `.flipdish.env` is listed in .gitignore (create .gitignore
if it doesn't exist; only append the line if it isn't already present).

Leave `<your_client_id>` and `<your_client_secret>` as literal
placeholders. I will fill in the real values myself in my editor — do
not ask me to paste them into the chat.

After Claude writes the file, follow the Fill in your credentials section above to substitute the real values in your editor.

Step 1 — Get an access token

Exchange your client credentials for a bearer token, capture the access_token into $TOKEN, and persist it back to .flipdish.env so subsequent steps (and future Claude Code Bash calls) pick it up automatically.

source ./.flipdish.env

TOKEN=$(curl --silent --request POST \
  --url "$FLIPDISH_BASE_URL/identity/connect/token" \
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --data grant_type=client_credentials \
  --data "client_id=$FLIPDISH_CLIENT_ID" \
  --data "client_secret=$FLIPDISH_CLIENT_SECRET" \
  --data scope=api \
  | jq -r .access_token)

echo "export TOKEN='$TOKEN'" >> .flipdish.env

Tokens expire — re-run this step to refresh. The new export TOKEN= line appended at the bottom of .flipdish.env will override the old one on the next source.

💬 Ask an AI to fetch and persist a token — click to expand. Safe to copy: no secrets in the prompt. Hover the code block to copy.
I have a `.flipdish.env` file in my cwd that already exports
FLIPDISH_BASE_URL, FLIPDISH_USER_AGENT, FLIPDISH_CLIENT_ID, and
FLIPDISH_CLIENT_SECRET (the last two are placeholders <your_client_id>
and <your_client_secret> until I fill them in — do not ask me to paste
them into chat).

Show me a bash snippet that:
  1. Sources ./.flipdish.env.
  2. Exchanges the client credentials for an access token via curl
     against $FLIPDISH_BASE_URL/identity/connect/token
     (Content-Type: application/x-www-form-urlencoded;
      grant_type=client_credentials, client_id=$FLIPDISH_CLIENT_ID,
      client_secret=$FLIPDISH_CLIENT_SECRET, scope=api).
  3. Extracts .access_token with jq into a shell variable named TOKEN.
  4. Appends `export TOKEN='$TOKEN'` to .flipdish.env so it persists.

Don't inline my real credentials anywhere. Reference them only via the
$FLIPDISH_CLIENT_ID and $FLIPDISH_CLIENT_SECRET shell variables.

Step 2 — Find your orgId

Every Menu Management and Org Management path is scoped by orgId. List the orgs your client has access to so you can pick one. Two paths — pick whichever fits your setup:

In a terminal, run this and read the table that comes back:

source ./.flipdish.env

curl --silent --request GET \
  --url "$FLIPDISH_BASE_URL/orgManagement/orgs" \
  --header "Authorization: Bearer $TOKEN" \
  --header "User-Agent: $FLIPDISH_USER_AGENT" \
  | jq -r '.data[] | "\(.orgId)\t\(.name)\t\(.countryCode)"'

You'll see one row per org as orgId<TAB>name<TAB>countryCode. Pick the id (shape: org123) of the org you want.

In Claude Code, paste the prompt below into chat. Claude will run the call via its Bash tool and print the table directly — no copy/paste or jq install required:

💬 Ask Claude to list my orgs and let me pick — click to expand. Safe to copy: no secrets in the prompt. Hover the code block to copy.
I have a .flipdish.env file in my cwd that already exports
FLIPDISH_BASE_URL, FLIPDISH_USER_AGENT, and TOKEN. Don't ask me for any
of those.

Run this and print the output to me as a readable table:
  source ./.flipdish.env
  curl --silent --request GET \
    --url "$FLIPDISH_BASE_URL/orgManagement/orgs" \
    --header "Authorization: Bearer $TOKEN" \
    --header "User-Agent: $FLIPDISH_USER_AGENT" \
    | jq -r '.data[] | "\(.orgId)\t\(.name)\t\(.countryCode)"'

Then wait for me to tell you which orgId I want. After I pick, USE YOUR
BASH TOOL to run this exact command yourself — do NOT print the command
for me to run, ACTUALLY execute it:
  echo "export ORG_ID='<my-pick>'" >> ./.flipdish.env
Then verify by running:
  grep -c '^export ORG_ID=' .flipdish.env
and confirm the count is 1 or higher. Only after that's confirmed,
tell me we're ready for the next step.

After picking, persist your choice (skip this if you used the Claude Code prompt — it does the append for you):

echo "export ORG_ID=org123" >> .flipdish.env
💡

First time using jq?

The Flipdish API returns single-line JSON, which is hard to scan with dozens of records. The pipe to jq above flattens the response to one org per line. Install it with brew install jq (macOS) or apt install jq (Debian/Ubuntu). The same trick works for every step below. (Claude Code's environment already has jq available.)

Reference: get all orgs.

Step 3 — Get the org's price bands

Every item on a menu needs a PricingProfile tied to a priceBandId. Price bands are defined at the org level — list them so you can pick one.

In a terminal:

source ./.flipdish.env

curl --silent --request GET \
  --url "$FLIPDISH_BASE_URL/orgManagement/orgs/$ORG_ID/priceBands" \
  --header "Authorization: Bearer $TOKEN" \
  --header "User-Agent: $FLIPDISH_USER_AGENT" \
  | jq -r '.data[] | "\(.id)\t\(.name // .displayName // "")"'

You'll see one row per band as id<TAB>name. Pick the UUID of the band you want to price against.

In Claude Code, ask Claude to list and let you pick:

💬 Ask Claude to list my price bands and let me pick — click to expand. Safe to copy: no secrets in the prompt. Hover the code block to copy.
I have a .flipdish.env file in my cwd that already exports
FLIPDISH_BASE_URL, FLIPDISH_USER_AGENT, TOKEN, and ORG_ID. Don't ask me
for any of those.

Run this and print the output to me as a readable table:
  source ./.flipdish.env
  curl --silent --request GET \
    --url "$FLIPDISH_BASE_URL/orgManagement/orgs/$ORG_ID/priceBands" \
    --header "Authorization: Bearer $TOKEN" \
    --header "User-Agent: $FLIPDISH_USER_AGENT" \
    | jq -r '.data[] | "\(.id)\t\(.name // .displayName // "")"'

Then wait for me to tell you which priceBandId I want. After I pick,
USE YOUR BASH TOOL to run this exact command yourself — do NOT print
the command for me to run, ACTUALLY execute it:
  echo "export PRICE_BAND_ID='<my-pick>'" >> ./.flipdish.env
Then verify by running:
  grep -c '^export PRICE_BAND_ID=' .flipdish.env
and confirm the count is 1 or higher. Only after that's confirmed,
tell me we're ready for the next step.

After picking, persist the chosen UUID (skip this if Claude already appended it):

echo "export PRICE_BAND_ID=<chosen-priceband-uuid>" >> .flipdish.env

You'll plug $PRICE_BAND_ID into pricingProfiles[].priceBandId on every item in the next step.

Step 4 — Create the menu with a category and an item

Create the menu in a single POST, including at least one category and one item. The body must include categories, modifiers, and categoryGroups (the last two can be empty arrays). Valid type values are Store, Primary, Reward, and Kiosk.

🆔

Don't send id fields when creating

On create there are no IDs to send — the server generates a UUID for the menu and for every category and item, and returns them in the response. Capture those IDs. You'll send each one back unchanged on every future update so the entity keeps its identity (see step 5). Optionally you can also set externalId (a free-form string) on a category or item to correlate it with your own system's identifier, but it's not required and isn't what Flipdish uses to track the entity — the server-generated id is.

Write the request body to a file (the heredoc is unquoted, so $PRICE_BAND_ID is interpolated by the shell), then POST it. Capture MENU_ID and REVISION_ID from the response and append them to .flipdish.env.

source ./.flipdish.env

cat > new-menu.json <<JSON
{
  "name": "Main Menu",
  "type": "Store",
  "description": "Our first menu",
  "categories": [
    {
      "caption": "Burgers",
      "enabled": true,
      "availabilityOverrides": [],
      "items": [
        {
          "caption": "Classic Burger",
          "enabled": true,
          "alcohol": false,
          "allergens": ["Gluten", "Milk"],
          "disableVouchers": false,
          "excludeFromVoucherDiscounting": false,
          "modifierMembers": [],
          "charges": [],
          "pricingProfiles": [
            {
              "priceBandId": "$PRICE_BAND_ID",
              "collectionPrice": 9.99,
              "collectionTax": 0,
              "collectionTaxable": false,
              "deliveryPrice": 9.99,
              "deliveryTax": 0,
              "deliveryTaxable": false,
              "dineInPrice": 9.99,
              "dineInTax": 0,
              "dineInTaxable": false,
              "takeawayPrice": 9.99,
              "takeawayTax": 0,
              "takeawayTaxable": false
            }
          ]
        }
      ]
    }
  ],
  "modifiers": [],
  "categoryGroups": []
}
JSON

RESPONSE=$(curl --silent --request POST \
  --url "$FLIPDISH_BASE_URL/menuManagement/orgs/$ORG_ID/menus" \
  --header "Authorization: Bearer $TOKEN" \
  --header 'Content-Type: application/json' \
  --header "User-Agent: $FLIPDISH_USER_AGENT" \
  --data @new-menu.json)

MENU_ID=$(echo "$RESPONSE" | jq -r .data.id)
REVISION_ID=$(echo "$RESPONSE" | jq -r .data.revisionId)

echo "export MENU_ID='$MENU_ID'" >> .flipdish.env
echo "export REVISION_ID='$REVISION_ID'" >> .flipdish.env
📦

The response is wrapped in a data envelope

Menu Management responses (create, update, get current) put the menu payload under a top-level data key — e.g. {"data": {"id": "...", "revisionId": 1, ...}}. The jq paths above use .data.id and .data.revisionId accordingly; .id at the top level returns null. The same pattern applies to PUT and GET .../current responses below.

The response contains the new menu, including:

  • data.id — captured into $MENU_ID.
  • data.revisionId — captured into $REVISION_ID. Bumped when a draft is created. In v3 menus this revision behaviour is different from v2; see Use v3 menus as an integrator.
  • Server-generated id UUIDs on the category and the item (inside data.categories[].items[]). Keep these — you send them back unchanged on every update so the entities keep their identity (see step 5).

Guidelines for the create body

  • Don't send id on anything in the create body — there's nothing to send yet. The server generates the IDs and returns them; from then on you reuse them.
  • Every item needs a pricingProfiles entry for every price band you intend to use, with all four dispatch-type prices filled in (collectionPrice, deliveryPrice, dineInPrice, takeawayPrice).
  • Use availabilityOverrides rules (not duplicated items) to model "lunch only" or "Deliveroo only" behaviour.

Reference: create menu, Menu Structure v3.0.

💬 Ask an AI to create the menu and persist menuId / revisionId — click to expand. Safe to copy: no secrets in the prompt. Hover the code block to copy.
I have a `.flipdish.env` file that exports FLIPDISH_BASE_URL,
FLIPDISH_USER_AGENT, TOKEN, ORG_ID, and PRICE_BAND_ID. Don't ask me for
any of those.

Show me a bash snippet that:
  1. Sources ./.flipdish.env.
  2. Writes new-menu.json with name "Main Menu", type "Store", empty
     modifiers and categoryGroups, and one category caption "Burgers"
     containing one item caption "Classic Burger" priced at 9.99 across
     collection/delivery/dine-in/takeaway with tax 0, priceBandId
     interpolated from $PRICE_BAND_ID. Use a heredoc whose delimiter is
     unquoted so $PRICE_BAND_ID expands.
  3. POSTs the file to
     $FLIPDISH_BASE_URL/menuManagement/orgs/$ORG_ID/menus
     with Authorization: Bearer $TOKEN, Content-Type: application/json,
     and User-Agent: $FLIPDISH_USER_AGENT.
  4. Extracts .data.id and .data.revisionId from the response with jq
     into MENU_ID and REVISION_ID. The response is wrapped in a `data`
     envelope — `.id` and `.revisionId` at the top level are null.
  5. Appends `export MENU_ID='$MENU_ID'` and
     `export REVISION_ID='$REVISION_ID'` to .flipdish.env so they
     persist across Claude Code Bash calls.

Important: on create there are no "id" fields to include — the server
generates them and returns them. Capture the returned menuId plus the
id of the category and item, because later updates must send those same
ids back so the entities keep their identity.

Step 5 — Update the menu

The Menu Management API is coarse-grained: there are no per-category or per-item endpoints. To change anything you fetch the current menu, mutate the document, and PUT it back.

First, fetch the current menu:

source ./.flipdish.env

curl --silent --request GET \
  --url "$FLIPDISH_BASE_URL/menuManagement/orgs/$ORG_ID/menus/$MENU_ID/current" \
  --header "Authorization: Bearer $TOKEN" \
  --header "User-Agent: $FLIPDISH_USER_AGENT" \
  > menu.json

Existing items keep their id across updates — send it back

When you PUT a menu, send each existing category and item back with the id the server gave you — i.e. round-trip the IDs that came in the GET .../current response. Existing entities keep their identity across the update; an id only changes if you drop it. Add a new item or category by leaving its id off — the server mints one and returns it, and you reuse that on subsequent updates.

externalId is an optional free-form string you can set to correlate an entity with your own system, but it isn't required and isn't the identity Flipdish tracks — the server-generated id is. (Earlier guidance said to strip ids and rely on externalId; that was for a one-off migration and no longer applies — don't strip IDs.)

The robust pattern is: take the document you just fetched, mutate it in place, and PUT the whole thing back with every existing id intact. New entities go in without an id. The example below uses jq to unwrap the data envelope from menu.json, raise the price of the existing "Classic Burger", and append a brand-new "Cheeseburger" (no id) — leaving every existing id untouched:

source ./.flipdish.env

# Mutate the fetched menu.json (it still holds the `data` envelope from the GET above):
#   - unwrap `.data`
#   - raise "Classic Burger" to 10.99 across all dispatch types
#   - append a new "Cheeseburger" with NO id (the server generates one)
jq --arg pb "$PRICE_BAND_ID" '
  .data
  | ( .categories[].items[] | select(.caption == "Classic Burger") | .pricingProfiles[] )
      |= ( .collectionPrice = 10.99 | .deliveryPrice = 10.99 | .dineInPrice = 10.99 | .takeawayPrice = 10.99 )
  | ( .categories[] | select(.caption == "Burgers") | .items ) += [
      {
        "caption": "Cheeseburger",
        "enabled": true,
        "alcohol": false,
        "allergens": ["Gluten", "Milk"],
        "disableVouchers": false,
        "excludeFromVoucherDiscounting": false,
        "modifierMembers": [],
        "charges": [],
        "pricingProfiles": [
          {
            "priceBandId": $pb,
            "collectionPrice": 11.99, "collectionTax": 0, "collectionTaxable": false,
            "deliveryPrice": 11.99, "deliveryTax": 0, "deliveryTaxable": false,
            "dineInPrice": 11.99, "dineInTax": 0, "dineInTaxable": false,
            "takeawayPrice": 11.99, "takeawayTax": 0, "takeawayTaxable": false
          }
        ]
      }
    ]
' menu.json > updated-menu.json

RESPONSE=$(curl --silent --request PUT \
  --url "$FLIPDISH_BASE_URL/menuManagement/orgs/$ORG_ID/menus/$MENU_ID" \
  --header "Authorization: Bearer $TOKEN" \
  --header 'Content-Type: application/json' \
  --header "User-Agent: $FLIPDISH_USER_AGENT" \
  --data @updated-menu.json)

REVISION_ID=$(echo "$RESPONSE" | jq -r .data.revisionId)
echo "export REVISION_ID='$REVISION_ID'" >> .flipdish.env

The PUT response is wrapped in the same data envelope as POST, hence .data.revisionId. The existing category and "Classic Burger" come back with the same ids they had before; only the newly added "Cheeseburger" gets a fresh server-generated id — capture it from the response if you'll reference that item later. The new REVISION_ID is what you'll publish in the next guide.

Guidelines when editing

  • Round-trip the document you fetched from .../current and send every existing category and item back with its id intact. Omit id only on genuinely new entities — the server generates one and returns it.
  • Every item needs a pricingProfiles entry for every price band the property uses, with all four dispatch-type prices filled in.
  • Use availabilityOverrides rules (not duplicated items) to model "lunch only" or "Deliveroo only" behaviour.

Reference: get current menu, update menu, Menu Structure v3.0.

💬 Ask an AI to update the menu and persist the new revisionId — click to expand. Safe to copy: no secrets in the prompt. Hover the code block to copy.
I have a `.flipdish.env` file that exports FLIPDISH_BASE_URL,
FLIPDISH_USER_AGENT, TOKEN, ORG_ID, PRICE_BAND_ID, MENU_ID, and
REVISION_ID. Don't ask me for any of those.

I want to update my Flipdish menu by raising the price of the existing
item with caption "Classic Burger" to 10.99 and adding a new item with
caption "Cheeseburger" at 11.99, both inside the existing category with
caption "Burgers". All prices apply across collection, delivery,
dine-in, and takeaway, tax 0, using priceBandId $PRICE_BAND_ID.

Show me a bash snippet that:
  1. Sources ./.flipdish.env.
  2. GETs $FLIPDISH_BASE_URL/menuManagement/orgs/$ORG_ID/menus/$MENU_ID/current
     with Authorization: Bearer $TOKEN and User-Agent: $FLIPDISH_USER_AGENT,
     saving to menu.json.
  3. Uses jq to produce updated-menu.json by:
       - unwrapping the `data` envelope on the GET response (the menu
         document lives at `.data`, not the top level),
       - KEEPING every existing "id" on categories and items intact,
       - raising the existing item's pricing,
       - appending the new "Cheeseburger" item with NO "id" (the server
         generates one),
     without stripping or inventing any UUIDs.
  4. PUTs $FLIPDISH_BASE_URL/menuManagement/orgs/$ORG_ID/menus/$MENU_ID
     with --data @updated-menu.json.
  5. Captures the new .data.revisionId into REVISION_ID (the PUT
     response is also wrapped in a `data` envelope) and appends
     `export REVISION_ID='$REVISION_ID'` to .flipdish.env so subsequent
     Claude Code Bash calls and the publish guide pick it up.

Where to go next