Product Recommendations API
Manual recommendation picks are directional links from one product to another, typed related or cross_sell. (The Upsell shelf takes no manual links — it derives from the related-products rules.) All endpoints require admin authentication.
Endpoints
Add a product link
Links a product to the product identified by product_id (both are product UUIDs). Rejects self-links, links to a variant of the same group (they can never render — the shelf excludes the viewed product's own variants), and duplicates of the same (product, linked product, type).
| Field Name | Field Type | Required |
|---|---|---|
| linked_product_id | string | Yes |
| type | string (related, cross_sell) | Yes |
| sort_order | integer | No |
- cURL
- JavaScript
curl
-H "Accept: application/json"
-H "Authorization: Bearer <admin JWT token>"
--data-raw '<JSON DATA>'
https://<your domain>/api/products/{product_id}/links
fetch('https://<your domain>/api/products/{product_id}/links', {
headers: {
'Accept': 'application/json',
'Authorization': 'Bearer <admin JWT token>'
},
body: <JSON DATA>
})
.then(response => response.json())
.then(data => {
if(data.error) {
// Handle the error
} else {
// Handle the data
}
})
.catch(error => {
// Handle the error
});
{
"success": true,
"data": {
"uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"product_id": 14,
"linked_product_id": 76,
"type": "related",
"sort_order": 1
}
}
Update a product link
Updates the pin position of a link. The link must belong to the product in the path.
| Field Name | Field Type | Required |
|---|---|---|
| sort_order | integer | Yes |
- cURL
- JavaScript
curl
-H "Accept: application/json"
-H "Authorization: Bearer <admin JWT token>"
--data-raw '<JSON DATA>'
https://<your domain>/api/products/{product_id}/links/{link_uuid}
fetch('https://<your domain>/api/products/{product_id}/links/{link_uuid}', {
headers: {
'Accept': 'application/json',
'Authorization': 'Bearer <admin JWT token>'
},
body: <JSON DATA>
})
.then(response => response.json())
.then(data => {
if(data.error) {
// Handle the error
} else {
// Handle the data
}
})
.catch(error => {
// Handle the error
});
{
"success": true,
"data": {
"uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"sort_order": 3
}
}
Remove a product link
- cURL
- JavaScript
curl
-H "Accept: application/json"
-H "Authorization: Bearer <admin JWT token>"
https://<your domain>/api/products/{product_id}/links/{link_uuid}
fetch('https://<your domain>/api/products/{product_id}/links/{link_uuid}', {
headers: {
'Accept': 'application/json',
'Authorization': 'Bearer <admin JWT token>'
}
})
.then(response => response.json())
.then(data => {
if(data.error) {
// Handle the error
} else {
// Handle the data
}
})
.catch(error => {
// Handle the error
});
{
"success": true,
"data": {
"uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
}
Rebuild co-purchase statistics
Rebuilds the frequently-bought-together statistics from the full order history — the same job that runs nightly. Safe to call while the nightly job runs; concurrent rebuilds are serialized.
- cURL
- JavaScript
curl
-H "Accept: application/json"
-H "Authorization: Bearer <admin JWT token>"
--data-raw '<JSON DATA>'
https://<your domain>/api/recommendationStats
fetch('https://<your domain>/api/recommendationStats', {
headers: {
'Accept': 'application/json',
'Authorization': 'Bearer <admin JWT token>'
},
body: <JSON DATA>
})
.then(response => response.json())
.then(data => {
if(data.error) {
// Handle the error
} else {
// Handle the data
}
})
.catch(error => {
// Handle the error
});
{
"success": true,
"data": {
"computedAt": "2026-07-16T02:00:01.000Z",
"totalOrderCount": 49019,
"pairCount": 194158
}
}