Publish menu

http
POST /v1/publish

Creates a publication snapshot of the current menu and makes it live: all products with menuVisible: true (and their categories, compositions and modifiers) are frozen into a new publication that guests see on the public menu.

No request body is required.

Sync vs publish#

POST /v1/sync writes to the draft menu — guests don't see those changes yet. POST /v1/publish takes what the draft looks like right now and snapshots it as the live menu. The typical flow:

  1. One or more sync calls (and/or cleanup).
  2. One publish call at the end.

Publish once per batch

Publishing after every small sync creates needless snapshots. Batch your changes, then publish once — it also keeps you well inside the rate limits.

Products with menuVisible: false (including those deactivated by cleanup) are excluded from the snapshot.

Publish is immediate

The new snapshot goes live for guests the moment the call returns — there is no review step. Verify the draft first (e.g. GET /v1/menu, and dry-run your sync/cleanup calls). If a publish does go wrong, roll back below.

Publication history & rollback#

The last 5 publications are retained per venue as a rollback buffer:

http
GET  /v1/publications
POST /v1/publish/rollback

GET /v1/publications lists them newest-first with a compact summary (current: true marks the live one):

json
{
  "items": [
    {
      "id": "cml9x2f4a0001abcd1234efgh",
      "publishedAt": "2026-07-05T12:00:00.000Z",
      "current": true,
      "summary": { "format": "full", "categories": 8, "products": 64, "banners": 2 }
    }
  ],
  "total": 1, "page": 1, "limit": 5, "totalPages": 1
}

POST /v1/publish/rollback re-publishes a retained snapshot verbatim as the new live menu (an empty body targets the previous publication; send { "publicationId": "..." } to pick one):

json
{
  "success": true,
  "publicationId": "cml9...new",
  "restoredFrom": "cml9...old",
  "restoredFromPublishedAt": "2026-07-04T18:20:00.000Z"
}

Rollback restores what GUESTS saw — it does not change your draft menu; the next regular publish publishes the draft again. Errors: 404 PUBLICATION_NOT_FOUND (not in the retained 5), 400 NO_PREVIOUS_PUBLICATION, 400 PUBLICATION_ALREADY_CURRENT, 400 PUBLICATION_INCOMPATIBLE (a legacy-format snapshot that predates this feature — publish fresh instead).

Example#

bash
curl -X POST https://api.duck-hub.com/v1/publish \
  -H "Authorization: Bearer dk_live_your_api_key"

Response#

201 Created:

json
{
  "success": true,
  "publicationId": "cml9x2f4a0001abcd1234efgh"
}
FieldMeaning
successAlways true on success
publicationIdId of the created publication snapshot

Errors#