Recommendations

By admin , 29 March 2026

How Recommendations Work

The Recommendations feature provides a structured way to surface AI-generated or manually created suggestions for improving the performance of a shop. Recommendations can target any entity — menu items, menu sections, campaigns, journeys, communications, and more. Each suggestion is stored as a pending recommendation that the shop owner can review and approve before any change is applied.

Core Concepts

What Is a Recommendation?

A recommendation is a structured suggestion to either update or remove a specific entity. It always has:

  • A type — either create, update (change one or more fields) or remove (delete the entry)
  • A category — the broad area the recommendation belongs to (e.g. menu, campaign, journey)
  • A subcategory — optional further classification within the category
  • A rationale — a plain-language explanation of why the change is being suggested
  • A status — tracks where the recommendation is in its lifecycle
  • A data payload — the target entity ID and the specific field values to change (for updates)

Recommendation Lifecycle

Every recommendation moves through the following statuses:

StatusMeaning
pendingNewly created, awaiting review
acceptedAccepted via the /accept endpoint
rejectedDismissed via the /reject endpoint — no change will be applied

Recommendation Fields

FieldTypeRequiredDescription
idintegerUnique identifier
placeIdintegerThe place this recommendation belongs to
typestringYescreate, update or remove
categorystringYesThe area this recommendation targets (e.g. menu, campaign, journey)
subcategorystringNoOptional further classification within the category
rationalestringYesHuman-readable explanation of why this change is recommended (10–500 characters)
dataobjectNoThe target entity and proposed changes — structure depends on category (see below)
statusstringpending, accepted or rejected. Defaults to pending.
createdintegerUnix timestamp (seconds) when the recommendation was created
updatedintegerUnix timestamp (seconds) of the last update

The data Object

The shape of data is flexible and depends on what is being recommended. At minimum it identifies the target entity. For update recommendations it also contains the proposed field changes.

Example — an update recommendation:

{
  "id": 1042,
  "type": "item",
  "title": "Crispy Chicken Burger",
  "description": "Juicy fried chicken with pickles and sriracha mayo on a toasted brioche bun."
}

Example — a remove recommendation:

{
  "id": 2071,
  "type": "campaign"
}

Only fields that differ from the current values are included in update payloads — if the suggested value already matches the existing value, it is omitted.

API Reference

All endpoints are under /places/{placeId}/recommendations and require a valid Api-Key header. The authenticated user must have cashier access to the place.

MethodPathDescription
GET/places/{placeId}/recommendationsList all recommendations for a place (paginated)
GET/places/{placeId}/recommendations/{id}Get a single recommendation by ID
POST/places/{placeId}/recommendationsCreate a recommendation manually
PUT/places/{placeId}/recommendations/{id}Update a recommendation (e.g. change status)
DELETE/places/{placeId}/recommendations/{id}Delete a recommendation
POST/places/{placeId}/recommendations/{id}/acceptAccept a recommendation (sets status to accepted)
POST/places/{placeId}/recommendations/{id}/rejectReject a recommendation (sets status to rejected)

Listing Recommendations

Supports standard pagination query parameters: page, limit, where (URL-encoded JSON filter), order, and include.

Fetch all pending recommendations for a place:

GET /places/123/recommendations?where={"status":"pending"}

Filter by category:

GET /places/123/recommendations?where={"category":"campaign","status":"pending"}

Creating a Recommendation Manually

Required fields: type, category, rationale. Optional: data, subcategory.

POST /places/123/recommendations
Content-Type: application/json
Api-Key: <your-key>

{
  "type": "update",
  "category": "journey",
  "rationale": "This journey has not been updated in over 6 months and the entry trigger no longer matches current customer behaviour.",
  "data": {
    "id": 77,
    "type": "journey"
  }
}

Common Workflows

Reviewing recommendations

  1. GET /places/{placeId}/recommendations?where={"status":"pending"} — fetch all pending suggestions
  2. Read each recommendation's rationale and data to understand what is proposed and why
  3. Use POST /{id}/accept to accept the recommendation
  4. Use POST /{id}/reject to reject the recommendation

Filtering by category

Use the where parameter to scope the list to a specific category:

GET /places/123/recommendations?where={"category":"menu","type":"update"}

API Examples

Fetch all pending recommendations

GET /places/123/recommendations?where={"status":"pending"}
Api-Key: <your-key>

Fetch recommendations for a specific category

GET /places/123/recommendations?where={"category":"campaign","status":"pending"}
Api-Key: <your-key>

Create a menu item update recommendation

POST /places/123/recommendations
Content-Type: application/json
Api-Key: <your-key>

{
  "type": "update",
  "category": "menu",
  "rationale": "The item title is generic and does not describe the dish. A more descriptive title will improve discoverability.",
  "data": {
    "id": 1042,
    "type": "item",
    "title": "Crispy Chicken Burger",
    "description": "Juicy fried chicken with pickles and sriracha mayo on a toasted brioche bun."
  }
}

Create a menu section removal recommendation

POST /places/123/recommendations
Content-Type: application/json
Api-Key: <your-key>

{
  "type": "remove",
  "category": "menu",
  "rationale": "This section contains only one item and has not received any orders in the past 90 days. Removing it will reduce menu clutter.",
  "data": {
    "id": 88,
    "type": "section"
  }
}

Create a campaign update recommendation

POST /places/123/recommendations
Content-Type: application/json
Api-Key: <your-key>

{
  "type": "update",
  "category": "campaign",
  "rationale": "The campaign end date has passed but the campaign is still active. It should be deactivated.",
  "data": {
    "id": 55,
    "type": "campaign",
    "active": false
  }
}

Create a journey recommendation

POST /places/123/recommendations
Content-Type: application/json
Api-Key: <your-key>

{
  "type": "update",
  "category": "journey",
  "subcategory": "win-back",
  "rationale": "The win-back journey targets customers inactive for 30 days, but the average re-engagement window for this place is 60 days. Adjusting the trigger delay will improve conversion.",
  "data": {
    "id": 12,
    "type": "journey"
  }
}

Accept a recommendation

POST /places/123/recommendations/456/accept
Api-Key: <your-key>

Reject a recommendation

POST /places/123/recommendations/456/reject
Api-Key: <your-key>

Delete a recommendation

DELETE /places/123/recommendations/456
Api-Key: <your-key>

List recommendations with pagination and sorting

Fetch the 10 most recently created pending recommendations:

GET /places/123/recommendations?where={"status":"pending"}&limit=10&order=-created
Api-Key: <your-key>

Comments