Reorder Cross-sells
Rewrite the display order of every complete cross-sell on the owner product.
The body must list every cross-sell exactly once — including inactive ones.
order is 1-based and must be a permutation of 1 through N. Array position
is ignored — order is what counts. Reorder does not change parent_id.
The cross-sell object has no order field. List Cross-sells
returns this display order. Incomplete items are omitted, matching GET — see
Incomplete items.
Live writes return 409 when the product has has_draft: true. Draft writes
require draft_version.
Request
Live:
POST /products/{productId}/cross-sells/reorder
Draft:
POST /products/{productId}/draft/cross-sells/reorder
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
productId | string | Yes | Owner product UUID. |
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
draft_version | integer | Draft only | Current overlay version from Get Product Draft. Minimum 1. A mismatch returns 409. |
items | array | Yes | One entry per complete cross-sell. Extra, missing, or duplicate ids return 422. |
Items Object
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Cross-sell UUID. |
order | integer | Yes | 1-based display position. Must be a permutation of 1 through N. |
Unknown keys on the body or on an item return 422.
Example Request
curl -X POST "https://cart.easy.tools/api/v1/products/0632bef5-c308-42cd-9cba-89a7a4f722bb/cross-sells/reorder" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"items": [
{ "id": "c1d8e4a6-7b29-4f53-a810-6e9c2d5f1b70", "order": 1 },
{ "id": "37643a70-be0f-4f09-ae36-c36e3ddb35dc", "order": 2 }
]
}'
Draft reorder adds "draft_version": 15 to the body and uses the
/draft/cross-sells/reorder path.
Response
Success Response (200)
Live returns { items } in display order, with no pagination. Draft returns
{ items, draft_version, preview_url }. See
Draft preview.
{
"items": [
{
"id": "c1d8e4a6-7b29-4f53-a810-6e9c2d5f1b70",
"product_id": "70dbd819-fac2-4dcf-b655-fb925e24410b",
"variant_id": "d91c65aa-b221-4aa4-b626-cf0d8a198749",
"parent_id": "37643a70-be0f-4f09-ae36-c36e3ddb35dc",
"title": "Or start with the checklist",
"main_description": null,
"description": null,
"button_text": null,
"amount": 1900,
"currency": "usd",
"discount": null,
"validity_minutes": 15,
"one_purchase": true,
"send_offer": true,
"active": true
},
{
"id": "37643a70-be0f-4f09-ae36-c36e3ddb35dc",
"product_id": "70dbd819-fac2-4dcf-b655-fb925e24410b",
"variant_id": "5272bfcf-4e92-458d-b513-80ca474a16e4",
"parent_id": null,
"title": "Add the workbook",
"main_description": null,
"description": null,
"button_text": "Yes, add it",
"amount": 4900,
"currency": "usd",
"discount": null,
"validity_minutes": 15,
"one_purchase": true,
"send_offer": true,
"active": true
}
]
}
Each entry has the Cross-sell Object shape.
draft_version and preview_url sit on the draft envelope, not on each item.
Response Fields
| Field | Type | Nullable | Description |
|---|---|---|---|
items | array | No | Complete cross-sells in display order. Inactive stay. |
draft_version | integer | No | Draft only. New overlay version after this write. |
preview_url | string | No | Draft only. Temporary signed checkout preview. Always reminted. Expires after about one hour. |
Error Responses
Bad Request (400)
{
"message": "Invalid product ID"
}
Not Found Error (404)
{
"message": "Product with ID 0632bef5-c308-42cd-9cba-89a7a4f722bb not found"
}
Conflict Error (409 — Unpublished Draft)
Live write while has_draft is true:
{
"message": "This product has an unpublished draft. Publish, unpublish, or delete the draft before making live changes."
}
Conflict Error (409 — Stale Draft Version)
Draft write when draft_version does not match:
{
"message": "The draft was edited elsewhere. GET the draft and retry with the current draft_version."
}
Validation Error (422 Unprocessable Entity)
Returned when draft_version is missing on a draft write, items is not an
exact permutation of the complete set, order is not 1 through N, or an
unknown key is sent.
{
"message": "The given data was invalid.",
"errors": {
"items": [
"The items list must include every cross-sell of this product exactly once."
]
}
}
Unauthorized Error (401)
{
"message": "Unauthenticated."
}
Forbidden Error (403)
{
"message": "You do not have API access to the requested store."
}