Skip to content
innovorder
⌘K

Product graph

Availability & Cross-Selling

Manage product availability in real-time across different sales channels. This endpoint allows operations to instantly "86" (disable) an item that has run out of stock during service, without needing a full menu republication.

PUT/availability/{menuId}/{channelId}/product/{productId}Update Availability

Toggle the availability status of a specific product for a given menu and channel.

Parameters

NameTypeRequiredDescription
menuIdintegerYesThe unique identifier of the menu.
channelIdintegerYesThe sales channel ID. Available values: 1 (Kiosk), 2 (Web), 9 (Uber Eats), 10 (Deliveroo). For marketplace channels (9, 10), the availability is pushed to the marketplace and the body must also contain the store reference and marketplace product ID (uberEatsStoreReference/uberEatsProductId or deliverooStoreReference/deliverooProductId).
productIdintegerYesThe unique identifier of the product.

Request Body

json
{
  "actionId": 464462,
  "availability": false,
  "channel": 2,
  "menuId": 106477
}
Request Body Properties

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

PropertyTypeExampleDescription
actionIdinteger464462Identifier of the associated action.
availabilitybooleanfalseThe availability value.
channelinteger2The channel value.
menuIdinteger106477Identifier of the menu.

Response

json
{
  "status": 200,
  "message": "OK"
}
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.
messagestring"OK"Human-readable result message. Do not use this value for program logic.
Payload Fields
  • actionId: Must match the productId being updated.
  • availability: true to enable, false to disable.
  • channel: The channel ID (must match URL).
  • menuId: The menu ID (must match URL).

PUT/availability/{menuId}/{channelId}/category/{categoryId}Update Category Availability

Toggle the availability of a whole category for a given menu and sales channel. Updates the category kioskAvailability (channelId 1) or webAvailability (channelId 2) flag, broadcasts a real-time CATEGORY_AVAILABILITY_UPDATED event to the brand front-ends and invalidates the menu cache.

Parameters

NameTypeRequiredDescription
menuIdintegerYesThe unique identifier of the menu.
channelIdintegerYesThe sales channel ID. Only 1 (Kiosk) and 2 (Web) are accepted for categories - unlike the product variant, marketplace channels are not supported. Any other value returns 400 missing_parameters.
categoryIdintegerYesThe unique identifier of the category.

Request Body

json
{
  "availability": false
}
Request Body Properties

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

PropertyTypeExampleDescription
availabilitybooleanfalseThe availability value.

Response

json
{
  "status": 200,
  "code": "category_availability_update_succeed",
  "message": "The product category have been successfully updated",
  "data": {
    "categoryId": 30085,
    "menuId": 106477,
    "name": "Burgers",
    "webAvailability": false,
    "kioskAvailability": 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"category_availability_update_succeed"Machine-readable application code for the result.
messagestring"The product category have been successfully updated"Human-readable result message. Do not use this value for program logic.
dataobject{…}Endpoint-specific response payload.
data.categoryIdinteger30085Identifier of the category.
data.menuIdinteger106477Identifier of the menu.
data.namestring"Burgers"The name value.
data.webAvailabilitybooleanfalseThe web availability value.
data.kioskAvailabilitybooleantrueThe kiosk availability value.

Good to Know

  • The category is looked up by categoryId only: the API does not verify that it belongs to the menu in the path (only your access to the menu is checked). Always pass a category of that menu. Returns 404 data_not_found if the category does not exist.
  • availability must be a boolean - the value is written as-is without type validation.
  • On all PUT /availability routes, a Restaurant role token is only accepted if the menu's restaurant has stock management V2 enabled; otherwise the request fails with permission_denied.

💡 Integration Tips

1. Retrieving IDs

To perform this call, you need the menuId and productId.

  • Find Menu ID: Call GET /restaurants/{restaurantId}/menus to see which menus are attached to a specific restaurant.
  • Find Product ID: Call GET /menus/{menuId}/products to list all products in that menu.
2. Mapping from SKU

The API uses internal productId integers. If your external system uses SKUs (Stock Keeping Units):

  1. Fetch all products via GET /menus/{menuId}/products.
  2. Iterate through the response to find the product where skuValue matches your system's SKU.
  3. Use the found productId in the availability PUT request.

Cross-Selling

Get Runtime Suggestions

This anonymous endpoint is for the ordering flow. It returns enabled cross-selling pages after excluding products already present in the submitted carts. It only accepts the Web channel.

POST/cross-selling/enabled/with-productsGet Enabled Cross-Selling Products

Returns up to limit eligible products per enabled cross-selling page for the submitted Web-ordering carts. Authentication is not required.

Parameters

NameTypeRequiredDescription
limitintegerYesMaximum number of products returned for each cross-selling page.

Request Body

json
{
  "brandId": 3325,
  "channelId": 2,
  "consumptionMode": "MODE_TAKE_AWAY",
  "restaurantCarts": [
    {
      "restaurantId": 6801,
      "menuId": 106477,
      "expectedAt": "2026-06-02T12:15:00.000Z",
      "expectedAtEnd": "2026-06-02T12:30:00.000Z",
      "cartId": "cart-8c0db2d8",
      "cart": [
        {
          "productId": 464462,
          "productCartId": "line-main",
          "quantity": 1,
          "steps": [
            {
              "stepId": 554,
              "type": 1,
              "products": [
                {
                  "productId": 991,
                  "quantity": 1,
                  "steps": []
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}
Request Body Properties

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

PropertyTypeRequiredExampleDescription
brandIdintegerYes3325Brand whose enabled cross-selling pages are evaluated.
channelIdintegerYes2Must be 2, the Web channel.
consumptionModestringYes"MODE_TAKE_AWAY"One of MODE_DELIVERY, MODE_TAKE_AWAY, MODE_SIT_IN, or MODE_DRIVE.
restaurantCartsarrayNot specified[…]List of restaurant carts entries.
restaurantCarts[]objectYes{…}One cart context per restaurant.
restaurantCarts[].restaurantIdintegerYes6801Restaurant serving the cart.
restaurantCarts[].menuIdintegerYes106477Menu used by the cart.
restaurantCarts[].expectedAtdatetimeNo"2026-06-02T12:15:00.000Z"Optional ISO-8601 expected fulfillment time.
restaurantCarts[].expectedAtEnddatetimeNo"2026-06-02T12:30:00.000Z"Optional ISO-8601 end time; when supplied it must not precede expectedAt.
restaurantCarts[].cartIdstringNo"cart-8c0db2d8"Optional caller cart reference.
restaurantCarts[].cartarrayNot specified[…]List of cart entries.
restaurantCarts[].cart[]objectYes{…}Products already in the cart; they are excluded from suggestions.
restaurantCarts[].cart[].productIdinteger|stringYes464462Product identifier.
restaurantCarts[].cart[].productCartIdstringNo"line-main"Optional client-side line identifier.
restaurantCarts[].cart[].quantitynumberYes1Positive quantity, at most 10,000.
restaurantCarts[].cart[].stepsarrayNot specified[…]List of steps entries.
restaurantCarts[].cart[].steps[]objectYes{…}Selected customization or cross-selling step entries. An empty array is valid.
restaurantCarts[].cart[].steps[].stepIdintegerYes554Selected step identifier.
restaurantCarts[].cart[].steps[].typeintegerNo1Optional step type: 1 for customization or 2 for cross-selling.
restaurantCarts[].cart[].steps[].productsarrayNot specified[…]List of products entries.
restaurantCarts[].cart[].steps[].products[]objectYes{…}Selected products for that step; each recursively uses the same product-cart shape.
restaurantCarts[].cart[].steps[].products[].productIdintegerNot specified991Identifier of the product.
restaurantCarts[].cart[].steps[].products[].quantityintegerNot specified1The quantity value.
restaurantCarts[].cart[].steps[].products[].stepsarrayNot specified[]List of steps entries.
restaurantCarts[].cart[].imageUrlstringNoNot providedOptional client image URL.
restaurantCarts[].cart[].customPricenumberNoNot providedOptional client custom price.
restaurantCarts[].cart[].customLabelstringNoNot providedOptional client custom label.
restaurantCarts[].cart[].crossSellingobjectNoNot providedOptional source pair with stepId and productId for a cross-selling selection.
restaurantCarts[].cart[].measuredQuantitynumberNoNot providedOptional positive measured quantity, at most 100,000.
restaurantCarts[].cart[].measurementUnitstringNoNot providedOptional measurement unit for a weighted product.

Response

json
{
  "status": 200,
  "code": "cross_selling_succeed",
  "message": "Cross selling succeed.",
  "data": [
    {
      "title": "Complete your meal",
      "products": [
        {
          "position": 1,
          "productId": 464500,
          "menuId": 106477,
          "image": "https://static.innovorder.fr/images/fries.jpg",
          "price": 350,
          "name": "French fries",
          "restaurantId": 6801
        }
      ]
    }
  ]
}
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"cross_selling_succeed"Machine-readable application code for the result.
messagestring"Cross selling succeed."Human-readable result message. Do not use this value for program logic.
dataarray[…]Endpoint-specific response payload.
data[]object{…}Endpoint-specific response payload.
data[].titlestring"Complete your meal"The title value.
data[].productsarray[…]List of products entries.
data[].products[]object{…}Object containing products fields.
data[].products[].positioninteger1The position value.
data[].products[].productIdinteger464500Identifier of the product.
data[].products[].menuIdinteger106477Identifier of the menu.
data[].products[].imagestring"https://static.innovorder.fr/images/fries.jpg"The image value.
data[].products[].priceinteger350The price value.
data[].products[].namestring"French fries"The name value.
data[].products[].restaurantIdinteger6801Identifier of the restaurant.

List Rules

Retrieve all cross-selling rules for a brand or a specific restaurant. Cross-selling rules define product suggestions displayed to customers during the ordering flow.

GET/cross-sellingList Cross-Selling Rules

Returns all cross-selling rules. Requires either brandId or restaurantId (mutually exclusive).

Parameters

NameTypeRequiredDescription
brandIdintegerNoBrand identifier. Mutually exclusive with restaurantId.
restaurantIdintegerNoRestaurant identifier. Mutually exclusive with brandId.

Response

json
{
  "status": 200,
  "code": "cross_selling_succeed",
  "message": "Cross selling succeed.",
  "data": [
    {
      "crossSellingId": 1,
      "brandId": 22,
      "restaurantId": null,
      "name": "Dessert Upsell",
      "status": "enabled"
    }
  ]
}
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"cross_selling_succeed"Machine-readable application code for the result.
messagestring"Cross selling succeed."Human-readable result message. Do not use this value for program logic.
dataarray[…]Endpoint-specific response payload.
data[]object{…}Endpoint-specific response payload.
data[].crossSellingIdinteger1Identifier of the associated cross selling.
data[].brandIdinteger22Identifier of the brand.
data[].restaurantIdnullnullIdentifier of the restaurant.
data[].namestring"Dessert Upsell"The name value.
data[].statusstring"enabled"HTTP status code returned by the API.

Get Rule

Retrieve a single cross-selling rule by its ID, including its associated products.

GET/cross-selling/{crossSellingId}Get Cross-Selling Rule by ID

Returns the cross-selling rule identified by crossSellingId.

Parameters

NameTypeRequiredDescription
crossSellingIdintegerYesID of the cross-selling rule.

Response

json
{
  "status": 200,
  "code": "cross_selling_succeed",
  "message": "Cross selling succeed.",
  "data": {
    "crossSellingId": 1,
    "brandId": 22,
    "restaurantId": null,
    "name": "Dessert Upsell",
    "status": "enabled",
    "crossSellingProducts": [
      {
        "productId": 101,
        "position": 1
      },
      {
        "productId": 102,
        "position": 2
      }
    ]
  }
}
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"cross_selling_succeed"Machine-readable application code for the result.
messagestring"Cross selling succeed."Human-readable result message. Do not use this value for program logic.
dataobject{…}Endpoint-specific response payload.
data.crossSellingIdinteger1Identifier of the associated cross selling.
data.brandIdinteger22Identifier of the brand.
data.restaurantIdnullnullIdentifier of the restaurant.
data.namestring"Dessert Upsell"The name value.
data.statusstring"enabled"HTTP status code returned by the API.
data.crossSellingProductsarray[…]List of cross selling products entries.
data.crossSellingProducts[]object{…}Object containing cross selling products fields.
data.crossSellingProducts[].productIdinteger101Identifier of the product.
data.crossSellingProducts[].positioninteger1The position value.

List Products

Retrieve all products available for cross-selling configuration within a brand. Useful for building the product picker when creating or editing a cross-selling rule.

GET/cross-selling/brands/{brandId}/productsList Products by Brand

Returns all products for the given brand that can be used in cross-selling rules.

Parameters

NameTypeRequiredDescription
brandIdintegerYesBrand identifier.

Response

json
{
  "status": 200,
  "code": "cross_selling_succeed",
  "message": "Cross selling succeed.",
  "data": [
    {
      "productId": 101,
      "name": "Tiramisu",
      "price": 650
    },
    {
      "productId": 102,
      "name": "Brownie",
      "price": 450
    }
  ]
}
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"cross_selling_succeed"Machine-readable application code for the result.
messagestring"Cross selling succeed."Human-readable result message. Do not use this value for program logic.
dataarray[…]Endpoint-specific response payload.
data[]object{…}Endpoint-specific response payload.
data[].productIdinteger101Identifier of the product.
data[].namestring"Tiramisu"The name value.
data[].priceinteger650The price value.

Create Rule

Create a new cross-selling rule. Each rule is associated with a brand (and optionally a restaurant) and contains an ordered list of products to suggest.

POST/cross-sellingCreate Cross-Selling Rule

Creates a cross-selling rule with its product associations.

Request Body

json
{
  "brandId": 22,
  "restaurantId": null,
  "name": "Dessert Upsell",
  "status": "enabled",
  "crossSellingProducts": [
    {
      "productId": 101,
      "position": 1
    },
    {
      "productId": 102,
      "position": 2
    }
  ]
}
Request Body Properties

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

PropertyTypeExampleDescription
brandIdinteger22Identifier of the brand.
restaurantIdnullnullIdentifier of the restaurant.
namestring"Dessert Upsell"The name value.
statusstring"enabled"HTTP status code returned by the API.
crossSellingProductsarray[…]List of cross selling products entries.
crossSellingProducts[]object{…}Object containing cross selling products fields.
crossSellingProducts[].productIdinteger101Identifier of the product.
crossSellingProducts[].positioninteger1The position value.

Response

json
{
  "status": 200,
  "code": "cross_selling_succeed",
  "message": "Cross selling succeed.",
  "data": {
    "crossSellingId": 1,
    "brandId": 22,
    "name": "Dessert Upsell",
    "status": "enabled"
  }
}
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"cross_selling_succeed"Machine-readable application code for the result.
messagestring"Cross selling succeed."Human-readable result message. Do not use this value for program logic.
dataobject{…}Endpoint-specific response payload.
data.crossSellingIdinteger1Identifier of the associated cross selling.
data.brandIdinteger22Identifier of the brand.
data.namestring"Dessert Upsell"The name value.
data.statusstring"enabled"HTTP status code returned by the API.

Field Reference

FieldTypeRequiredDescription
brandIdIntegerYesThe brand this rule belongs to.
restaurantIdIntegerNoOptionally restrict this rule to a specific restaurant.
nameStringYesHuman-readable name for this cross-selling rule.
statusEnumYesenabled or disabled.
crossSellingProductsArray<Object>YesOrdered list of products. Each object has productId (integer) and position (integer).

Update Rule

Update an existing cross-selling rule. The full configuration including the product list must be provided. Requires either brandId or restaurantId (mutually exclusive).

PUT/cross-selling/{crossSellingId}Update Cross-Selling Rule

Replaces the cross-selling rule configuration identified by crossSellingId.

Parameters

NameTypeRequiredDescription
crossSellingIdintegerYesID of the cross-selling rule to update.

Request Body

json
{
  "brandId": 22,
  "name": "Dessert Upsell V2",
  "status": "enabled",
  "crossSellingProducts": [
    {
      "productId": 101,
      "position": 1
    },
    {
      "productId": 103,
      "position": 2
    }
  ]
}
Request Body Properties

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

PropertyTypeExampleDescription
brandIdinteger22Identifier of the brand.
namestring"Dessert Upsell V2"The name value.
statusstring"enabled"HTTP status code returned by the API.
crossSellingProductsarray[…]List of cross selling products entries.
crossSellingProducts[]object{…}Object containing cross selling products fields.
crossSellingProducts[].productIdinteger101Identifier of the product.
crossSellingProducts[].positioninteger1The position value.

Response

json
{
  "status": 200,
  "code": "cross_selling_succeed",
  "message": "Cross selling succeed.",
  "data": {
    "crossSellingId": 1,
    "brandId": 22,
    "name": "Dessert Upsell V2",
    "status": "enabled"
  }
}
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"cross_selling_succeed"Machine-readable application code for the result.
messagestring"Cross selling succeed."Human-readable result message. Do not use this value for program logic.
dataobject{…}Endpoint-specific response payload.
data.crossSellingIdinteger1Identifier of the associated cross selling.
data.brandIdinteger22Identifier of the brand.
data.namestring"Dessert Upsell V2"The name value.
data.statusstring"enabled"HTTP status code returned by the API.

Delete Rule

Permanently delete a cross-selling rule and all its product associations.

DELETE/cross-selling/{crossSellingId}Delete Cross-Selling Rule

Deletes the cross-selling rule identified by crossSellingId.

Parameters

NameTypeRequiredDescription
crossSellingIdintegerYesID of the cross-selling rule to delete.

Response

json
{
  "status": 200,
  "code": "cross_selling_succeed",
  "message": "Cross selling succeed."
}
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"cross_selling_succeed"Machine-readable application code for the result.
messagestring"Cross selling succeed."Human-readable result message. Do not use this value for program logic.

Duplicate Rule

Create a copy of an existing cross-selling rule with a new name. The duplicated rule inherits all product associations from the original.

POST/cross-selling/{crossSellingId}/duplicateDuplicate Cross-Selling Rule

Duplicates the cross-selling rule identified by crossSellingId with the provided name.

Parameters

NameTypeRequiredDescription
crossSellingIdintegerYesID of the cross-selling rule to duplicate.

Request Body

json
{
  "name": "Dessert Upsell (Copy)"
}
Request Body Properties

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

PropertyTypeExampleDescription
namestring"Dessert Upsell (Copy)"The name value.

Response

json
{
  "status": 200,
  "code": "cross_selling_succeed",
  "message": "Cross selling succeed.",
  "data": {
    "crossSellingId": 2,
    "brandId": 22,
    "name": "Dessert Upsell (Copy)",
    "status": "enabled",
    "crossSellingProducts": [
      {
        "productId": 101,
        "position": 1
      },
      {
        "productId": 102,
        "position": 2
      }
    ]
  }
}
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"cross_selling_succeed"Machine-readable application code for the result.
messagestring"Cross selling succeed."Human-readable result message. Do not use this value for program logic.
dataobject{…}Endpoint-specific response payload.
data.crossSellingIdinteger2Identifier of the associated cross selling.
data.brandIdinteger22Identifier of the brand.
data.namestring"Dessert Upsell (Copy)"The name value.
data.statusstring"enabled"HTTP status code returned by the API.
data.crossSellingProductsarray[…]List of cross selling products entries.
data.crossSellingProducts[]object{…}Object containing cross selling products fields.
data.crossSellingProducts[].productIdinteger101Identifier of the product.
data.crossSellingProducts[].positioninteger1The position value.

Toggle Status

Toggle the status of a cross-selling rule between enabled and disabled. No request body is needed.

PUT/cross-selling/{crossSellingId}/statusToggle Cross-Selling Status

Toggles the enabled/disabled status of the cross-selling rule identified by crossSellingId.

Parameters

NameTypeRequiredDescription
crossSellingIdintegerYesID of the cross-selling rule.

Response

json
{
  "status": 200,
  "code": "cross_selling_succeed",
  "message": "Cross selling succeed.",
  "data": {
    "crossSellingId": 1,
    "status": "disabled"
  }
}
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"cross_selling_succeed"Machine-readable application code for the result.
messagestring"Cross selling succeed."Human-readable result message. Do not use this value for program logic.
dataobject{…}Endpoint-specific response payload.
data.crossSellingIdinteger1Identifier of the associated cross selling.
data.statusstring"disabled"HTTP status code returned by the API.