User recommendations
The user recommendations call returns three lists of products tailored to a specific user:
topPicks- products the user should buy right now.replenishment- products the user regularly buys but does not need right now.discovery- products the user might be interested in.
Request
Recommendations are requested by a POST to the following endpoint:
POST {{OpenAppUrl}}/merchant/v1/recommendations/user
- Request
- Schema
{
"loggedUser": "user-id-from-webshop",
"limits": {
"topPicks": 3,
"replenishment": 5,
"discovery": 5
}
}
loggedUserstringRequiredThe merchant's own stable identifier for the user.
maxLength: 255
limitsobjectOptionalMaximum number of items to return per list. All fields are optional; omit to use the defaults.
Show child parametersHide child parameters3
topPicksintegerOptionalMaximum number of top-pick items to return. Defaults to 20.
minimum: 1 · maximum: 200
replenishmentintegerOptionalMaximum number of replenishment items to return. Defaults to 20.
minimum: 1 · maximum: 200
discoveryintegerOptionalMaximum number of discovery items to return. Defaults to 20.
minimum: 1 · maximum: 200
Raw JSON Schema
{
"description": "Request for product recommendations for a user",
"additionalProperties": false,
"type": "object",
"properties": {
"loggedUser": {
"description": "The merchant's own stable identifier for the user.",
"maxLength": 255,
"type": "string",
"title": "loggedUser"
},
"limits": {
"description": "Maximum number of items to return per list. All fields are optional; omit to use the defaults.",
"additionalProperties": false,
"type": "object",
"properties": {
"topPicks": {
"description": "Maximum number of top-pick items to return. Defaults to 20.",
"minimum": 1,
"maximum": 200,
"type": "integer",
"title": "topPicks"
},
"replenishment": {
"description": "Maximum number of replenishment items to return. Defaults to 20.",
"minimum": 1,
"maximum": 200,
"type": "integer",
"title": "replenishment"
},
"discovery": {
"description": "Maximum number of discovery items to return. Defaults to 20.",
"minimum": 1,
"maximum": 200,
"type": "integer",
"title": "discovery"
}
},
"title": "limits"
}
},
"required": [
"loggedUser"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}
Each list has a configurable limit (default 20, max 200). Omit limits or any of its fields to use the defaults.
Response
- Response
- Schema
{
"topPicks": [
{
"id": "id124",
"ean": "5901234123464",
"quantity": 1
}
],
"replenishment": [
{
"id": "id123-red",
"ean": "5901234123457",
"quantity": 2,
"expectedAt": "2026-06-20T00:00:00.000Z"
}
],
"discovery": [
{
"id": "id123-blue",
"ean": "5901234123471",
"quantity": 1,
"score": 0.44
}
],
"expiresAt": "2026-06-10T09:42:00.000Z"
}
topPicksarray of RecommendedProductRequiredProducts the user should buy right now, ordered in a stable sort order. Applying a presentation order pleasant for the user (e.g. grouping by product category) is the merchant's responsibility.
Show child parametersHide child parameters3
idstringRequiredThe catalogue variant ID of the recommended product.
maxLength: 36
eanstringOptionalThe ean (or other barcode) of the recommended product, as known from the catalogue.
maxLength: 36
quantityintegerRequiredThe proposed number of items to add to the basket.
minimum: 1
replenishmentarray of ReplenishmentProductRequiredProducts the user regularly buys but does not need right now - returned in a stable sort order. Each item includes an expectedAt date indicating when the user is expected to want to buy it. A product that appears in topPicks will not appear here. Applying a presentation order pleasant for the user (e.g. grouping by product category) is the merchant's responsibility.
Show child parametersHide child parameters4
idstringRequiredThe catalogue variant ID of the recommended product.
maxLength: 36
eanstringOptionalThe ean (or other barcode) of the recommended product, as known from the catalogue.
maxLength: 36
quantityintegerRequiredThe proposed number of items to add to the basket.
minimum: 1
expectedAtstringRequiredThe moment when the user is expected to want to buy this product.
format: date-time
discoveryarray of DiscoveryProductRequiredProducts the user might be interested in, returned in a stable sort order. Each item carries a relevance score. Applying a presentation order pleasant for the user (e.g. grouping by product category) is the merchant's responsibility.
Show child parametersHide child parameters4
idstringRequiredThe catalogue variant ID of the recommended product.
maxLength: 36
eanstringOptionalThe ean (or other barcode) of the recommended product, as known from the catalogue.
maxLength: 36
quantityintegerRequiredThe proposed number of items to add to the basket.
minimum: 1
scorenumberRequiredThe relevance of the recommendation, between 0 and 1. Higher is more relevant.
minimum: 0 · maximum: 1
expiresAtstringOptionalThe moment until which the recommendations can be cached and reused for the same user. When absent, the response must not be cached.
format: date-time
Raw JSON Schema
{
"description": "Product recommendations returned for a user",
"additionalProperties": false,
"type": "object",
"properties": {
"topPicks": {
"description": "Products the user should buy right now, ordered in a stable sort order. Applying a presentation order pleasant for the user (e.g. grouping by product category) is the merchant's responsibility.",
"type": "array",
"items": {
"$ref": "#/definitions/RecommendedProduct"
},
"title": "topPicks"
},
"replenishment": {
"description": "Products the user regularly buys but does not need right now - returned in a stable sort order. Each item includes an expectedAt date indicating when the user is expected to want to buy it. A product that appears in topPicks will not appear here. Applying a presentation order pleasant for the user (e.g. grouping by product category) is the merchant's responsibility.",
"type": "array",
"items": {
"$ref": "#/definitions/ReplenishmentProduct"
},
"title": "replenishment"
},
"discovery": {
"description": "Products the user might be interested in, returned in a stable sort order. Each item carries a relevance score. Applying a presentation order pleasant for the user (e.g. grouping by product category) is the merchant's responsibility.",
"type": "array",
"items": {
"$ref": "#/definitions/DiscoveryProduct"
},
"title": "discovery"
},
"expiresAt": {
"description": "The moment until which the recommendations can be cached and reused for the same user. When absent, the response must not be cached.",
"format": "date-time",
"type": "string",
"title": "expiresAt"
}
},
"required": [
"topPicks",
"replenishment",
"discovery"
],
"definitions": {
"RecommendedProduct": {
"title": "RecommendedProduct",
"type": "object",
"properties": {
"id": {
"description": "The catalogue variant ID of the recommended product.",
"maxLength": 36,
"type": "string",
"title": "id"
},
"ean": {
"description": "The ean (or other barcode) of the recommended product, as known from the catalogue.",
"maxLength": 36,
"type": "string",
"title": "ean"
},
"quantity": {
"description": "The proposed number of items to add to the basket.",
"minimum": 1,
"type": "integer",
"title": "quantity"
}
},
"required": [
"id",
"quantity"
]
},
"ReplenishmentProduct": {
"title": "ReplenishmentProduct",
"type": "object",
"properties": {
"id": {
"description": "The catalogue variant ID of the recommended product.",
"maxLength": 36,
"type": "string",
"title": "id"
},
"ean": {
"description": "The ean (or other barcode) of the recommended product, as known from the catalogue.",
"maxLength": 36,
"type": "string",
"title": "ean"
},
"quantity": {
"description": "The proposed number of items to add to the basket.",
"minimum": 1,
"type": "integer",
"title": "quantity"
},
"expectedAt": {
"description": "The moment when the user is expected to want to buy this product.",
"format": "date-time",
"type": "string",
"title": "expectedAt"
}
},
"required": [
"id",
"quantity",
"expectedAt"
]
},
"DiscoveryProduct": {
"title": "DiscoveryProduct",
"type": "object",
"properties": {
"id": {
"description": "The catalogue variant ID of the recommended product.",
"maxLength": 36,
"type": "string",
"title": "id"
},
"ean": {
"description": "The ean (or other barcode) of the recommended product, as known from the catalogue.",
"maxLength": 36,
"type": "string",
"title": "ean"
},
"quantity": {
"description": "The proposed number of items to add to the basket.",
"minimum": 1,
"type": "integer",
"title": "quantity"
},
"score": {
"description": "The relevance of the recommendation, between 0 and 1. Higher is more relevant.",
"minimum": 0,
"maximum": 1,
"type": "number",
"title": "score"
}
},
"required": [
"id",
"quantity",
"score"
]
}
},
"$schema": "http://json-schema.org/draft-07/schema#"
}
Only products known from the catalogue and currently available are returned. Any list can be shorter than its limit - or empty - when OpenApp has no sufficiently relevant recommendations. For a loggedUser OpenApp has not yet seen in the order feed, all three lists are empty. The merchant should design placements to handle empty lists gracefully.
Items within each list are returned in a stable sort order. Applying a presentation order that is pleasant for the user - for example grouping by product category - is the merchant's responsibility.
Recommendations for a user are recalculated once a day. A product the user has just purchased may still appear in the lists until the next recalculation. The merchant should hide recently purchased products when rendering the placement.
When expiresAt is present, the response can be cached and reused for the same user until that moment - it marks when the next recalculation will be available. When expiresAt is absent, the response must not be cached.
The call may take a few seconds and must not block the user. Fetch recommendations asynchronously - for example ahead of time or in a background request - and render the placement when the response arrives.
Errors
| Error name | Code |
|---|---|
RecommendationValidationException | 400 |
RecommendationsNotReadyException | 409 |