Skip to content
innovorder
⌘K

Product graph

Menus

A menu is the root container of the catalog. It belongs to a brand or to a single restaurant, holds the whole product tree (categories, products, steps), and is assigned to sales channels (kiosk, web, POS, marketplaces) and POS devices. Changes only become visible to customers once the menu is published on each channel.

Managing Menus

GET/v2/menusList Menus V2

Retrieve all menus for a brand or restaurant. At least one of brandId or restaurantId parameter is required.

Parameters

NameTypeRequiredDescription
brandIdintegerNoThe ID of the brand.
restaurantIdintegerNoThe ID of the restaurant.

Response

json
{
  "status": 200,
  "code": "menu_succeed",
  "message": "You can access these menus.",
  "data": [
    {
      "menuId": 106477,
      "name": "Main Menu",
      "channels": [
        {
          "channelId": 2,
          "name": "web"
        }
      ],
      "posDevices": [
        {
          "posDeviceId": 8063,
          "deviceName": "Main Register"
        }
      ],
      "isActive": true
    }
  ]
}
Response Properties

Every field in the example is listed below. Explicit requiredness is shown when the endpoint contract defines it.

PropertyTypeExampleDescription
statusinteger200HTTP status code returned by the API.
codestring"menu_succeed"Machine-readable application code for the result.
messagestring"You can access these menus."Human-readable result message. Do not use this value for program logic.
dataarray[…]Endpoint-specific response payload.
data[]object{…}Endpoint-specific response payload.
data[].menuIdinteger106477Identifier of the menu.
data[].namestring"Main Menu"The name value.
data[].channelsarray[…]List of channels entries.
data[].channels[]object{…}Object containing channels fields.
data[].channels[].channelIdinteger2Identifier of the associated channel.
data[].channels[].namestring"web"The name value.
data[].posDevicesarray[…]List of pos devices entries.
data[].posDevices[]object{…}Object containing pos devices fields.
data[].posDevices[].posDeviceIdinteger8063Identifier of the associated pos device.
data[].posDevices[].deviceNamestring"Main Register"The device name value.
data[].isActivebooleantrueWhether this resource is active.

POST/v2/menusCreate Menu (V2)

Create a new menu with specific channel and device assignments. You can import an existing structure using the "import" field. A menu created on the kiosk channel deactivates the restaurant up-selling pages served by the previous kiosk menu; deactivatedUpsellingPagesCount reports how many.

Request Body

json
{
  "name": "Summer Menu",
  "brandId": 3325,
  "restaurantId": 6801,
  "channels": [
    1,
    2,
    5
  ],
  "posDevices": [
    8063
  ],
  "isSyncFromPosEnabled": false,
  "import": {
    "categories": {},
    "products": {},
    "steps": {}
  }
}
Request Body Properties

Every field in the example is listed below. Explicit requiredness is shown when the endpoint contract defines it.

PropertyTypeExampleDescription
namestring"Summer Menu"The name value.
brandIdinteger3325Identifier of the brand.
restaurantIdinteger6801Identifier of the restaurant.
channelsarray[…]List of channels entries.
channels[]integer1The channels value.
posDevicesarray[…]List of pos devices entries.
posDevices[]integer8063The pos devices value.
isSyncFromPosEnabledbooleanfalseWhether sync from pos enabled is enabled or applies.
importobject{…}Object containing import fields.
import.categoriesobject{…}Object containing categories fields.
import.productsobject{…}Object containing products fields.
import.stepsobject{…}Object containing steps fields.

Response

json
{
  "status": 201,
  "code": "menu_v2_creation_succeed",
  "message": "Menu has been successfully created.",
  "data": {
    "menuId": 107001,
    "name": "Summer Menu",
    "is_enabled": true,
    "created_at": "2025-11-28T10:00:00.000Z",
    "deactivatedUpsellingPagesCount": 0
  }
}
Response Properties

Every field in the example is listed below. Explicit requiredness is shown when the endpoint contract defines it.

PropertyTypeExampleDescription
statusinteger201HTTP status code returned by the API.
codestring"menu_v2_creation_succeed"Machine-readable application code for the result.
messagestring"Menu has been successfully created."Human-readable result message. Do not use this value for program logic.
dataobject{…}Endpoint-specific response payload.
data.menuIdinteger107001Identifier of the menu.
data.namestring"Summer Menu"The name value.
data.is_enabledbooleantrueWhether enabled is enabled or applies.
data.created_atstring"2025-11-28T10:00:00.000Z"Timestamp when this resource was created.
data.deactivatedUpsellingPagesCountinteger0The deactivated upselling pages count value.

PUT/v2/menus/{menuId}Update Menu (V2)

Update an existing menu. Taking the menu off the kiosk channel, or putting it on, deactivates the restaurant up-selling pages served by the kiosk menu; deactivatedUpsellingPagesCount reports how many.

Parameters

NameTypeRequiredDescription
menuIdintegerYesThe unique identifier of the menu.

Request Body

json
{
  "name": "Updated Menu Name",
  "channels": [
    2
  ],
  "isSyncFromPosEnabled": true
}
Request Body Properties

Every field in the example is listed below. Explicit requiredness is shown when the endpoint contract defines it.

PropertyTypeExampleDescription
namestring"Updated Menu Name"The name value.
channelsarray[…]List of channels entries.
channels[]integer2The channels value.
isSyncFromPosEnabledbooleantrueWhether sync from pos enabled is enabled or applies.

Response

json
{
  "status": 200,
  "code": "menu_update_succeed",
  "message": "Menu has been successfully updated.",
  "data": {
    "menuId": 106477,
    "name": "Updated Menu Name",
    "updated_at": "2025-11-29T10:00:00.000Z",
    "deactivatedUpsellingPagesCount": 0
  }
}
Response Properties

Every field in the example is listed below. Explicit requiredness is shown when the endpoint contract defines it.

PropertyTypeExampleDescription
statusinteger200HTTP status code returned by the API.
codestring"menu_update_succeed"Machine-readable application code for the result.
messagestring"Menu has been successfully updated."Human-readable result message. Do not use this value for program logic.
dataobject{…}Endpoint-specific response payload.
data.menuIdinteger106477Identifier of the menu.
data.namestring"Updated Menu Name"The name value.
data.updated_atstring"2025-11-29T10:00:00.000Z"Timestamp when this resource was last updated.
data.deactivatedUpsellingPagesCountinteger0The deactivated upselling pages count value.

POST/v2/menus/{menuId}/channels/{channelId}/publishPublish Menu

Publish a specific menu to a sales channel.

Parameters

NameTypeRequiredDescription
menuIdintegerYesThe unique identifier of the menu.
channelIdintegerYesThe unique identifier of the channel (e.g., 1 for Kiosk, 2 for Web).

Response

json
{
  "status": 200,
  "code": "menu_publish_succeed",
  "message": "Menu has been successfully published.",
  "data": 106477
}
Response Properties

Every field in the example is listed below. Explicit requiredness is shown when the endpoint contract defines it.

PropertyTypeExampleDescription
statusinteger200HTTP status code returned by the API.
codestring"menu_publish_succeed"Machine-readable application code for the result.
messagestring"Menu has been successfully published."Human-readable result message. Do not use this value for program logic.
datainteger106477Endpoint-specific response payload.

GET/v2/menus/operationsGet Menu Operations

Retrieve expected menu imports and operations status.

Parameters

NameTypeRequiredDescription
brandIdintegerNoThe ID of the brand.
menuIdintegerNoThe ID of the menu.
restaurantIdintegerNoThe ID of the restaurant.
limitintegerNoMax results (default 10).
offsetintegerNoResults to skip (default 0).
sortstringNoSort order (ASC/DESC).

Response

json
{
  "status": 200,
  "code": "menu_operations_found",
  "message": "Menu operations have been successfully found.",
  "data": [
    {
      "menuOperationId": 12345,
      "name": "Import Menu",
      "status": "COMPLETED",
      "type": "IMPORT",
      "createdAt": "2025-11-28T10:00:00.000Z",
      "userId": 104848
    }
  ]
}
Response Properties

Every field in the example is listed below. Explicit requiredness is shown when the endpoint contract defines it.

PropertyTypeExampleDescription
statusinteger200HTTP status code returned by the API.
codestring"menu_operations_found"Machine-readable application code for the result.
messagestring"Menu operations have been successfully found."Human-readable result message. Do not use this value for program logic.
dataarray[…]Endpoint-specific response payload.
data[]object{…}Endpoint-specific response payload.
data[].menuOperationIdinteger12345Identifier of the associated menu operation.
data[].namestring"Import Menu"The name value.
data[].statusstring"COMPLETED"HTTP status code returned by the API.
data[].typestring"IMPORT"The type value.
data[].createdAtstring"2025-11-28T10:00:00.000Z"Timestamp when this resource was created.
data[].userIdinteger104848Identifier of the user.

Classic Menu Endpoints

These established menu routes remain available alongside the V2 API. They require an authenticated Admin, Brand, or Restaurant user; creation and updates additionally require the relevant menu access flag.

GET/menusList Menus

Lists menus owned by one accessible brand or restaurant. At least one scope is required. When both are supplied, the current implementation resolves the brand scope.

Parameters

NameTypeRequiredDescription
brandIdintegerNoBrand scope. Required when restaurantId is omitted.
restaurantIdintegerNoRestaurant scope. Required when brandId is omitted.

Response

json
{
  "status": 200,
  "code": "menu_succeed",
  "message": "You can access these menus.",
  "data": [
    {
      "menuId": 106477,
      "name": "Main Menu",
      "brandId": 3325,
      "restaurantId": null,
      "imageId": 1001,
      "is_enabled": true,
      "isSyncFromPosEnabled": false,
      "hasInitModalBeenShowed": false,
      "created_at": "2026-06-01T08:30:00.000Z",
      "updated_at": "2026-06-02T10:15:00.000Z",
      "channels": [
        {
          "menuId": 106477,
          "channelId": 2,
          "created_at": "2026-06-01T08:30:00.000Z",
          "updated_at": "2026-06-01T08:30:00.000Z"
        }
      ],
      "isActive": true
    }
  ]
}
Response Properties

Every field in the example is listed below. Explicit requiredness is shown when the endpoint contract defines it.

PropertyTypeExampleDescription
statusinteger200HTTP status code returned by the API.
codestring"menu_succeed"Machine-readable application code for the result.
messagestring"You can access these menus."Human-readable result message. Do not use this value for program logic.
dataarray[…]Endpoint-specific response payload.
data[]object{…}Endpoint-specific response payload.
data[].menuIdinteger106477Identifier of the menu.
data[].namestring"Main Menu"The name value.
data[].brandIdinteger3325Identifier of the brand.
data[].restaurantIdnullnullIdentifier of the restaurant.
data[].imageIdinteger1001Identifier of the associated image.
data[].is_enabledbooleantrueWhether enabled is enabled or applies.
data[].isSyncFromPosEnabledbooleanfalseWhether sync from pos enabled is enabled or applies.
data[].hasInitModalBeenShowedbooleanfalseWhether init modal been showed is enabled or applies.
data[].created_atstring"2026-06-01T08:30:00.000Z"Timestamp when this resource was created.
data[].updated_atstring"2026-06-02T10:15:00.000Z"Timestamp when this resource was last updated.
data[].channelsarray[…]List of channels entries.
data[].channels[]object{…}Object containing channels fields.
data[].channels[].menuIdinteger106477Identifier of the menu.
data[].channels[].channelIdinteger2Identifier of the associated channel.
data[].channels[].created_atstring"2026-06-01T08:30:00.000Z"Timestamp when this resource was created.
data[].channels[].updated_atstring"2026-06-01T08:30:00.000Z"Timestamp when this resource was last updated.
data[].isActivebooleantrueWhether this resource is active.

POST/menusCreate Menu

Creates a menu for a brand or restaurant. The server permits a long-running import window of up to 15 minutes and invalidates the corresponding web-ordering cache after creation.

Request Body

json
{
  "name": "Summer Menu",
  "brandId": 3325,
  "channels": [
    2,
    5
  ],
  "imageId": 1001,
  "posDevices": [
    8063
  ],
  "nayaxDevices": [],
  "sourcePosId": 8063
}
Request Body Properties

Every field in the example is listed below. Explicit requiredness is shown when the endpoint contract defines it.

PropertyTypeRequiredExampleDescription
namestringYes"Summer Menu"Menu display name.
brandIdintegerNo3325Brand owner. Supply one of brandId or restaurantId.
channelsarrayNot specified[…]List of channels entries.
channels[]integerYes2Sales channel identifiers assigned to the new menu.
imageIdintegerNo1001Optional image-library identifier.
posDevicesarrayNot specified[…]List of pos devices entries.
posDevices[]integerNo8063Optional POS device identifiers assigned to the menu.
nayaxDevicesarrayNot specified[]List of nayax devices entries.
sourcePosIdintegerNo8063Optional source POS identifier used by the import flow.
restaurantIdintegerNoNot providedRestaurant owner. Supply one of brandId or restaurantId.
nayaxDevices[]integerNoNot providedOptional Nayax device identifiers assigned to the menu.
importobjectNoNot providedOptional full MenuImportDTO snapshot. Its categories, products, steps, tags, relations, images, layout and POS data are imported into the new menu.

Response

json
{
  "status": 200,
  "code": "menu_create_succeed",
  "message": "Menu has been successfully created.",
  "data": {
    "menuId": 107001,
    "name": "Summer Menu",
    "brandId": 3325,
    "restaurantId": null,
    "imageId": 1001,
    "is_enabled": true,
    "isSyncFromPosEnabled": false,
    "hasInitModalBeenShowed": false,
    "created_at": "2026-06-02T10:15:00.000Z",
    "updated_at": "2026-06-02T10:15:00.000Z",
    "channels": [
      {
        "channelId": 2
      },
      {
        "channelId": 5
      }
    ],
    "posDevices": [
      {
        "posDeviceId": 8063,
        "deviceName": "Main Register"
      }
    ],
    "moduleMarketplaces": []
  }
}
Response Properties

Every field in the example is listed below. Explicit requiredness is shown when the endpoint contract defines it.

PropertyTypeExampleDescription
statusinteger200HTTP status code returned by the API.
codestring"menu_create_succeed"Machine-readable application code for the result.
messagestring"Menu has been successfully created."Human-readable result message. Do not use this value for program logic.
dataobject{…}Endpoint-specific response payload.
data.menuIdinteger107001Identifier of the menu.
data.namestring"Summer Menu"The name value.
data.brandIdinteger3325Identifier of the brand.
data.restaurantIdnullnullIdentifier of the restaurant.
data.imageIdinteger1001Identifier of the associated image.
data.is_enabledbooleantrueWhether enabled is enabled or applies.
data.isSyncFromPosEnabledbooleanfalseWhether sync from pos enabled is enabled or applies.
data.hasInitModalBeenShowedbooleanfalseWhether init modal been showed is enabled or applies.
data.created_atstring"2026-06-02T10:15:00.000Z"Timestamp when this resource was created.
data.updated_atstring"2026-06-02T10:15:00.000Z"Timestamp when this resource was last updated.
data.channelsarray[…]List of channels entries.
data.channels[]object{…}Object containing channels fields.
data.channels[].channelIdinteger2Identifier of the associated channel.
data.posDevicesarray[…]List of pos devices entries.
data.posDevices[]object{…}Object containing pos devices fields.
data.posDevices[].posDeviceIdinteger8063Identifier of the associated pos device.
data.posDevices[].deviceNamestring"Main Register"The device name value.
data.moduleMarketplacesarray[]List of module marketplaces entries.

POST/menus/importImport a Menu File

Imports a menu from a single multipart file. Send the file in the file field and pass the target scope in the query string. name and one target scope are required; channels is a numeric array encoded in the query string.

Parameters

NameTypeRequiredDescription
namestringYesName assigned to the imported menu.
brandIdintegerNoTarget brand. Supply one of brandId or restaurantId.
restaurantIdintegerNoTarget restaurant. Supply one of brandId or restaurantId.
channelsarray<integer>NoNumeric channel IDs, encoded as an array in the query string.

Request Body

json
multipart/form-data: file=[binary menu import file]
Request Body Properties

Every field in the example is listed below. Explicit requiredness is shown when the endpoint contract defines it.

PropertyTypeRequiredExampleDescription
filebinaryYes[binary menu import file]The single menu import file.

Response

json
{
  "status": 201,
  "code": "menu_import_creation_succeed",
  "message": "The menu has been successfully imported.",
  "data": {
    "menuId": 107002,
    "name": "Imported Summer Menu",
    "brandId": 3325,
    "restaurantId": null,
    "imageId": null,
    "is_enabled": true,
    "isSyncFromPosEnabled": false,
    "hasInitModalBeenShowed": false,
    "created_at": "2026-06-02T10:20:00.000Z",
    "updated_at": "2026-06-02T10:20:00.000Z",
    "channels": [
      {
        "channelId": 2
      }
    ],
    "posDevices": [],
    "moduleMarketplaces": []
  }
}
Response Properties

Every field in the example is listed below. Explicit requiredness is shown when the endpoint contract defines it.

PropertyTypeExampleDescription
statusinteger201HTTP status code returned by the API.
codestring"menu_import_creation_succeed"Machine-readable application code for the result.
messagestring"The menu has been successfully imported."Human-readable result message. Do not use this value for program logic.
dataobject{…}Endpoint-specific response payload.
data.menuIdinteger107002Identifier of the menu.
data.namestring"Imported Summer Menu"The name value.
data.brandIdinteger3325Identifier of the brand.
data.restaurantIdnullnullIdentifier of the restaurant.
data.imageIdnullnullIdentifier of the associated image.
data.is_enabledbooleantrueWhether enabled is enabled or applies.
data.isSyncFromPosEnabledbooleanfalseWhether sync from pos enabled is enabled or applies.
data.hasInitModalBeenShowedbooleanfalseWhether init modal been showed is enabled or applies.
data.created_atstring"2026-06-02T10:20:00.000Z"Timestamp when this resource was created.
data.updated_atstring"2026-06-02T10:20:00.000Z"Timestamp when this resource was last updated.
data.channelsarray[…]List of channels entries.
data.channels[]object{…}Object containing channels fields.
data.channels[].channelIdinteger2Identifier of the associated channel.
data.posDevicesarray[]List of pos devices entries.
data.moduleMarketplacesarray[]List of module marketplaces entries.

GET/menus/restaurantsGet Eligible Menus by Restaurant

Returns the menus available to each requested restaurant for at least one requested channel. It is intended for propagation and supports an optional POS-device filter.

Parameters

NameTypeRequiredDescription
restaurantIdsstringYesComma-separated positive restaurant IDs, for example 6801,6802.
channelIdsstringYesComma-separated channel IDs. A menu is returned when it matches at least one requested channel.
posDeviceIdintegerNoOptional POS device; when supplied, only menus linked to that device are returned.

Response

json
{
  "status": 200,
  "code": "menus_by_restaurants_succeed",
  "message": "Menus by restaurants retrieved successfully.",
  "data": [
    {
      "restaurantId": 6801,
      "menus": [
        {
          "menuId": 106477,
          "name": "Main Menu"
        }
      ]
    },
    {
      "restaurantId": 6802,
      "menus": []
    }
  ]
}
Response Properties

Every field in the example is listed below. Explicit requiredness is shown when the endpoint contract defines it.

PropertyTypeExampleDescription
statusinteger200HTTP status code returned by the API.
codestring"menus_by_restaurants_succeed"Machine-readable application code for the result.
messagestring"Menus by restaurants retrieved successfully."Human-readable result message. Do not use this value for program logic.
dataarray[…]Endpoint-specific response payload.
data[]object{…}Endpoint-specific response payload.
data[].restaurantIdinteger6801Identifier of the restaurant.
data[].menusarray[…]List of menus entries.
data[].menus[]object{…}Object containing menus fields.
data[].menus[].menuIdinteger106477Identifier of the menu.
data[].menus[].namestring"Main Menu"The name value.

GET/menus/{menuId}/hash_mapGet Full Menu Structure

Returns the complete menu tree through layout, categories, products, and steps in a compressed hash-map format. This is the primary endpoint used by front-ends to render the catalog. Image objects expose public metadata only; internal filesystem paths are omitted.

Parameters

NameTypeRequiredDescription
menuIdstringYesThe unique identifier of the menu.

Response

json
{
  "status": 200,
  "code": "menu_hash_map_succeed",
  "message": "You can access these menus.",
  "data": {
    "layout": [
      30085
    ],
    "categories": {
      "30085": {
        "categoryId": 30085,
        "name": "Burgers",
        "products": [
          464462
        ]
      }
    },
    "products": {
      "464462": {
        "productId": 464462,
        "name": "Cheeseburger",
        "price": 1200,
        "steps": [
          554
        ]
      }
    },
    "steps": {
      "554": {
        "stepId": 554,
        "name": "Cooking",
        "products": [
          991,
          992
        ]
      }
    }
  }
}
Response Properties

Every field in the example is listed below. Explicit requiredness is shown when the endpoint contract defines it.

PropertyTypeExampleDescription
statusinteger200HTTP status code returned by the API.
codestring"menu_hash_map_succeed"Machine-readable application code for the result.
messagestring"You can access these menus."Human-readable result message. Do not use this value for program logic.
dataobject{…}Endpoint-specific response payload.
data.layoutarray[…]List of layout entries.
data.layout[]integer30085The layout value.
data.categoriesobject{…}Object containing categories fields.
data.categories.30085object{…}Object containing 30085 fields.
data.categories.30085.categoryIdinteger30085Identifier of the category.
data.categories.30085.namestring"Burgers"The name value.
data.categories.30085.productsarray[…]List of products entries.
data.categories.30085.products[]integer464462The products value.
data.productsobject{…}Object containing products fields.
data.products.464462object{…}Object containing 464462 fields.
data.products.464462.productIdinteger464462Identifier of the product.
data.products.464462.namestring"Cheeseburger"The name value.
data.products.464462.priceinteger1200The price value.
data.products.464462.stepsarray[…]List of steps entries.
data.products.464462.steps[]integer554The steps value.
data.stepsobject{…}Object containing steps fields.
data.steps.554object{…}Object containing 554 fields.
data.steps.554.stepIdinteger554Identifier of the associated step.
data.steps.554.namestring"Cooking"The name value.
data.steps.554.productsarray[…]List of products entries.
data.steps.554.products[]integer991The products value.

Menu Lifecycle

These endpoints manage the lifecycle of a single menu: read its configuration, export its full catalog, duplicate it to other restaurants, and delete it.

GET/menus/{menuId}Get Menu Configuration

Retrieve the full configuration of a menu: menu attributes, active channels (filtered to the channels visible to your user), associated POS devices, linked marketplace modules and cover image. This endpoint does NOT return the product catalog - use GET /menus/{menuId}/export or the /hash_map endpoint for that.

Parameters

NameTypeRequiredDescription
menuIdintegerYesThe unique identifier of the menu.

Response

json
{
  "status": 200,
  "code": "menu_succeed",
  "message": "You can access these menus.",
  "data": {
    "menuId": 106477,
    "name": "Main Menu",
    "brandId": 3325,
    "restaurantId": 6801,
    "channels": [
      {
        "channelId": 2,
        "name": "web"
      }
    ],
    "posDevices": [
      {
        "posDeviceId": 8063,
        "deviceName": "Main Register"
      }
    ],
    "moduleMarketplaces": [],
    "isActive": true,
    "image": {
      "imageId": 1001,
      "fullUrl": "https://static.innovorder.fr/images/..."
    }
  }
}
Response Properties

Every field in the example is listed below. Explicit requiredness is shown when the endpoint contract defines it.

PropertyTypeExampleDescription
statusinteger200HTTP status code returned by the API.
codestring"menu_succeed"Machine-readable application code for the result.
messagestring"You can access these menus."Human-readable result message. Do not use this value for program logic.
dataobject{…}Endpoint-specific response payload.
data.menuIdinteger106477Identifier of the menu.
data.namestring"Main Menu"The name value.
data.brandIdinteger3325Identifier of the brand.
data.restaurantIdinteger6801Identifier of the restaurant.
data.channelsarray[…]List of channels entries.
data.channels[]object{…}Object containing channels fields.
data.channels[].channelIdinteger2Identifier of the associated channel.
data.channels[].namestring"web"The name value.
data.posDevicesarray[…]List of pos devices entries.
data.posDevices[]object{…}Object containing pos devices fields.
data.posDevices[].posDeviceIdinteger8063Identifier of the associated pos device.
data.posDevices[].deviceNamestring"Main Register"The device name value.
data.moduleMarketplacesarray[]List of module marketplaces entries.
data.isActivebooleantrueWhether this resource is active.
data.imageobject{…}Object containing image fields.
data.image.imageIdinteger1001Identifier of the associated image.
data.image.fullUrlstring"https://static.innovorder.fr/images/..."The full url value.
Response Notes
  • isActive is derived: it is true when the menu has at least one active channel, it is not a stored attribute.
  • image is { imageId, fullUrl }, or null if the menu references an image that no longer exists; the field is absent when the menu has no image.
  • Returns 404 data_not_found if the menu does not exist or if its parent brand/restaurant cannot be found.

GET/menus/{menuId}/exportExport Menu Catalog

Export the complete catalog snapshot of a menu in the flattened read-model format used by menu import and duplication: products, categories and steps hash maps, plus the POS layout items. Each product embeds a "pos" object (its POS-specific settings with the posLocalId) or null. Image objects retain their public URL for reimport, while internal filesystem paths are omitted.

Parameters

NameTypeRequiredDescription
menuIdintegerYesThe unique identifier of the menu.

Response

json
{
  "status": 200,
  "code": "menu_export_succeed",
  "message": "Menu has been successfully exported.",
  "data": {
    "products": {
      "464462": {
        "productId": 464462,
        "name": "Cheeseburger",
        "price": 1200,
        "pos": {
          "posLocalId": 789
        }
      }
    },
    "categories": {
      "30085": {
        "categoryId": 30085,
        "name": "Burgers"
      }
    },
    "steps": {
      "554": {
        "stepId": 554,
        "name": "Cooking Level"
      }
    },
    "posLayoutItems": []
  }
}
Response Properties

Every field in the example is listed below. Explicit requiredness is shown when the endpoint contract defines it.

PropertyTypeExampleDescription
statusinteger200HTTP status code returned by the API.
codestring"menu_export_succeed"Machine-readable application code for the result.
messagestring"Menu has been successfully exported."Human-readable result message. Do not use this value for program logic.
dataobject{…}Endpoint-specific response payload.
data.productsobject{…}Object containing products fields.
data.products.464462object{…}Object containing 464462 fields.
data.products.464462.productIdinteger464462Identifier of the product.
data.products.464462.namestring"Cheeseburger"The name value.
data.products.464462.priceinteger1200The price value.
data.products.464462.posobject{…}Object containing pos fields.
data.products.464462.pos.posLocalIdinteger789Identifier of the associated pos local.
data.categoriesobject{…}Object containing categories fields.
data.categories.30085object{…}Object containing 30085 fields.
data.categories.30085.categoryIdinteger30085Identifier of the category.
data.categories.30085.namestring"Burgers"The name value.
data.stepsobject{…}Object containing steps fields.
data.steps.554object{…}Object containing 554 fields.
data.steps.554.stepIdinteger554Identifier of the associated step.
data.steps.554.namestring"Cooking Level"The name value.
data.posLayoutItemsarray[]List of pos layout items entries.

PUT/menus/{menuId}Update Menu

Replaces the menu configuration and its channel, POS-device, and marketplace assignments. channels, posDevices, and moduleMarketplaces are full replacement lists; the caller needs the MENU_EDIT access flag.

Parameters

NameTypeRequiredDescription
menuIdintegerYesMenu to update.

Request Body

json
{
  "name": "Updated Main Menu",
  "channels": [
    2,
    5
  ],
  "posDevices": [
    8063
  ],
  "moduleMarketplaces": [],
  "imageId": 1001,
  "isSyncFromPosEnabled": true,
  "hasInitModalBeenShowed": true,
  "externalId": "partner-menu-42"
}
Request Body Properties

Every field in the example is listed below. Explicit requiredness is shown when the endpoint contract defines it.

PropertyTypeRequiredExampleDescription
namestringYes"Updated Main Menu"Updated display name.
channelsarrayNot specified[…]List of channels entries.
channels[]integerYes2Complete replacement list of sales channel IDs.
posDevicesarrayNot specified[…]List of pos devices entries.
posDevices[]integerYes8063Complete replacement list of POS device IDs.
moduleMarketplacesarrayNot specified[]List of module marketplaces entries.
imageIdintegerNo1001Image-library ID. Set to null to clear the image.
isSyncFromPosEnabledbooleanNotrueWhether catalog synchronization from POS is enabled.
hasInitModalBeenShowedbooleanNotrueWhether the menu initialization modal has already been acknowledged.
externalIdstringNo"partner-menu-42"Optional external menu reference. It is stored through the external-ID mapping flow for restaurant menus.
moduleMarketplaces[]stringYesNot providedComplete replacement list of marketplace module IDs.

Response

json
{
  "status": 200,
  "code": "menu_update_succeed",
  "message": "Menu has been successfully updated.",
  "data": {
    "menuId": 106477,
    "name": "Updated Main Menu",
    "brandId": 3325,
    "restaurantId": 6801,
    "imageId": 1001,
    "is_enabled": true,
    "isSyncFromPosEnabled": true,
    "hasInitModalBeenShowed": true,
    "created_at": "2026-06-01T08:30:00.000Z",
    "updated_at": "2026-06-02T10:30:00.000Z",
    "channels": [
      {
        "channelId": 2
      },
      {
        "channelId": 5
      }
    ],
    "posDevices": [
      8063
    ],
    "moduleMarketplaces": []
  }
}
Response Properties

Every field in the example is listed below. Explicit requiredness is shown when the endpoint contract defines it.

PropertyTypeExampleDescription
statusinteger200HTTP status code returned by the API.
codestring"menu_update_succeed"Machine-readable application code for the result.
messagestring"Menu has been successfully updated."Human-readable result message. Do not use this value for program logic.
dataobject{…}Endpoint-specific response payload.
data.menuIdinteger106477Identifier of the menu.
data.namestring"Updated Main Menu"The name value.
data.brandIdinteger3325Identifier of the brand.
data.restaurantIdinteger6801Identifier of the restaurant.
data.imageIdinteger1001Identifier of the associated image.
data.is_enabledbooleantrueWhether enabled is enabled or applies.
data.isSyncFromPosEnabledbooleantrueWhether sync from pos enabled is enabled or applies.
data.hasInitModalBeenShowedbooleantrueWhether init modal been showed is enabled or applies.
data.created_atstring"2026-06-01T08:30:00.000Z"Timestamp when this resource was created.
data.updated_atstring"2026-06-02T10:30:00.000Z"Timestamp when this resource was last updated.
data.channelsarray[…]List of channels entries.
data.channels[]object{…}Object containing channels fields.
data.channels[].channelIdinteger2Identifier of the associated channel.
data.posDevicesarray[…]List of pos devices entries.
data.posDevices[]integer8063The pos devices value.
data.moduleMarketplacesarray[]List of module marketplaces entries.

Large Response

The export contains the entire catalog and can be very large. The products, categories and steps collections are hash maps indexed by ID (e.g. products["464462"]), not arrays - only posLayoutItems is an array.

GET/menus/{menuId}/products-exportExport Products as Flat Rows

Exports every product in a menu as a flat JSON row for spreadsheet and partner synchronization use cases. Product, price, VAT, stock, category, tag, step, and scope columns are all present for every row.

Parameters

NameTypeRequiredDescription
menuIdintegerYesMenu whose products are exported.

Response

json
{
  "status": 200,
  "code": "products_succeed",
  "message": "Products found.",
  "data": [
    {
      "productId": 464462,
      "menuId": 106477,
      "sku": "BURGER-001",
      "barCode": "3760123456789",
      "billingCode": "BURGER",
      "restaurant": "Central Restaurant",
      "menuName": "Main Menu",
      "productName": "Cheeseburger",
      "ticketLabel": "Cheeseburger",
      "type": "Produit",
      "description": "Beef burger with cheese",
      "additionalInformation": "Contains gluten and milk",
      "tags": "Popular / Beef",
      "parentCategories": "Burgers",
      "directCategories": "Classic burgers",
      "claimOrder": 12,
      "priceTtc": 12,
      "contractPrice": 9.5,
      "vatDefault": 1,
      "vatSitIn": 1,
      "vatTakeAway": 1,
      "vatDelivery": 1,
      "subsidizable": "OUI",
      "admissible": "OUI",
      "discountable": "OUI",
      "currentQuantity": 24,
      "defaultQuantity": 30,
      "servingCount": 1,
      "isMenu": "NON",
      "belongsToSteps": "Choose a side (0)",
      "containsSteps": "",
      "alwaysAskForCustomization": "NON",
      "brandId": 3325,
      "restaurantId": 6801,
      "signature": "f1cb6b30-cfa3-4e4e-92c9-4ae1be615e81"
    }
  ]
}
Response Properties

Every field in the example is listed below. Explicit requiredness is shown when the endpoint contract defines it.

PropertyTypeExampleDescription
statusinteger200HTTP status code returned by the API.
codestring"products_succeed"Machine-readable application code for the result.
messagestring"Products found."Human-readable result message. Do not use this value for program logic.
dataarray[…]Endpoint-specific response payload.
data[]object{…}Endpoint-specific response payload.
data[].productIdinteger464462Identifier of the product.
data[].menuIdinteger106477Identifier of the menu.
data[].skustring"BURGER-001"The sku value.
data[].barCodestring"3760123456789"The bar code value.
data[].billingCodestring"BURGER"The billing code value.
data[].restaurantstring"Central Restaurant"The restaurant value.
data[].menuNamestring"Main Menu"The menu name value.
data[].productNamestring"Cheeseburger"The product name value.
data[].ticketLabelstring"Cheeseburger"The ticket label value.
data[].typestring"Produit"The type value.
data[].descriptionstring"Beef burger with cheese"The description value.
data[].additionalInformationstring"Contains gluten and milk"The additional information value.
data[].tagsstring"Popular / Beef"The tags value.
data[].parentCategoriesstring"Burgers"The parent categories value.
data[].directCategoriesstring"Classic burgers"The direct categories value.
data[].claimOrderinteger12The claim order value.
data[].priceTtcinteger12The price ttc value.
data[].contractPricenumber9.5The contract price value.
data[].vatDefaultinteger1The vat default value.
data[].vatSitIninteger1The vat sit in value.
data[].vatTakeAwayinteger1The vat take away value.
data[].vatDeliveryinteger1The vat delivery value.
data[].subsidizablestring"OUI"The subsidizable value.
data[].admissiblestring"OUI"The admissible value.
data[].discountablestring"OUI"The discountable value.
data[].currentQuantityinteger24The current quantity value.
data[].defaultQuantityinteger30The default quantity value.
data[].servingCountinteger1The serving count value.
data[].isMenustring"NON"Whether menu is enabled or applies.
data[].belongsToStepsstring"Choose a side (0)"The belongs to steps value.
data[].containsStepsstring""The contains steps value.
data[].alwaysAskForCustomizationstring"NON"The always ask for customization value.
data[].brandIdinteger3325Identifier of the brand.
data[].restaurantIdinteger6801Identifier of the restaurant.
data[].signaturestring"f1cb6b30-cfa3-4e4e-92c9-4ae1be615e81"The signature value.

POST/menus/{menuId}/duplicateDuplicate Menu

Duplicate an existing menu under a new name, to a brand or to one or several restaurants. The whole catalog (products, categories, steps, POS layout) is re-imported into the target menu(s). "name" is required, plus at least one of "restaurantId" (single target restaurant), "brandId" (brand-level menu) or "restaurantList" (several target restaurants) - otherwise 400 missing_parameters. If "restaurantId" is provided, it takes precedence over "restaurantList". Requires the MENU_CREATE_OR_DELETE access flag on your user.

Parameters

NameTypeRequiredDescription
menuIdintegerYesThe unique identifier of the source menu.

Request Body

json
{
  "name": "Main Menu (Copy)",
  "restaurantList": [
    6801,
    6802
  ]
}
Request Body Properties

Every field in the example is listed below. Explicit requiredness is shown when the endpoint contract defines it.

PropertyTypeExampleDescription
namestring"Main Menu (Copy)"The name value.
restaurantListarray[…]List of restaurant list entries.
restaurantList[]integer6801The restaurant list value.

Response

json
{
  "status": 200,
  "code": "menu_update_succeed",
  "message": "Menu has been successfully updated.",
  "data": [
    {
      "menuId": 107002,
      "name": "Main Menu (Copy)",
      "restaurantId": 6801
    },
    {
      "menuId": 107003,
      "name": "Main Menu (Copy)",
      "restaurantId": 6802
    }
  ]
}
Response Properties

Every field in the example is listed below. Explicit requiredness is shown when the endpoint contract defines it.

PropertyTypeExampleDescription
statusinteger200HTTP status code returned by the API.
codestring"menu_update_succeed"Machine-readable application code for the result.
messagestring"Menu has been successfully updated."Human-readable result message. Do not use this value for program logic.
dataarray[…]Endpoint-specific response payload.
data[]object{…}Endpoint-specific response payload.
data[].menuIdinteger107002Identifier of the menu.
data[].namestring"Main Menu (Copy)"The name value.
data[].restaurantIdinteger6801Identifier of the restaurant.

Duplicate Behavior

  • The response shape depends on the request body: a single menu object when restaurantId is provided, an array of created menus otherwise (one per restaurant of restaurantList, or a single element for brandId).
  • The response code is menu_update_succeed - there is no dedicated "duplicate" code.
  • Duplication is a long-running operation: the server allows up to 15 minutes, so configure a large client-side timeout.
  • Returns 404 menu_not_found if no usable target (restaurantId, brandId or restaurantList) can be resolved.

DELETE/menus/{menuId}Delete Menu

Delete a menu. This is a soft delete: the menu is disabled (is_enabled set to false) and disappears from listings, but its data is kept. Requires the MENU_CREATE_OR_DELETE access flag on your user. Menu caches (hash maps and web ordering initialization) are invalidated automatically.

Parameters

NameTypeRequiredDescription
menuIdintegerYesThe unique identifier of the menu to delete.

Response

json
{
  "status": 200,
  "code": "menu_delete_succeed",
  "message": "Menu has been successfully deleted.",
  "data": {
    "menuId": 106477,
    "name": "Main Menu",
    "is_enabled": false
  }
}
Response Properties

Every field in the example is listed below. Explicit requiredness is shown when the endpoint contract defines it.

PropertyTypeExampleDescription
statusinteger200HTTP status code returned by the API.
codestring"menu_delete_succeed"Machine-readable application code for the result.
messagestring"Menu has been successfully deleted."Human-readable result message. Do not use this value for program logic.
dataobject{…}Endpoint-specific response payload.
data.menuIdinteger106477Identifier of the menu.
data.namestring"Main Menu"The name value.
data.is_enabledbooleanfalseWhether enabled is enabled or applies.

Soft Delete Only

Deleting a menu never removes it physically: is_enabled is set to false and the menu no longer appears in listings. The returned data is the updated menu record.

Data Models

PostMenu Schema
yaml
type: object
properties:
  name:
    type: string
  channels:
    type: array
    items: number
    description: 1=KIOSK, 2=WEB, 5=POS, 9=UBER_EATS, 10=DELIVEROO...
  posDevices:
    type: array
    items: number
  import:
    $ref: MenuImportDTO
  isSyncFromPosEnabled:
    type: boolean
  brandId:
    type: number
  restaurantId:
    type: number
MenuOperation
yaml
type: object
properties:
  menuOperationId: integer
  name: string
  status: string
  type: string
  brandId: integer
  menuId: integer
  userId: integer
  createdAt: date-time
  updatedAt: date-time
MenuImportDTO

Used to populate the menu with existing items upon creation.

yaml
type: object
properties:
  layout:
    type: array
    items: number
  categories:
    type: object
    additionalProperties: CategoryAttributes
  products:
    type: object
    additionalProperties: ProductAttributes
  steps:
    type: object
    additionalProperties: StepAttributes