Catalog API2026-11Preview
Sync rules
What happens to your listing when a seller in China changes a price or runs out.
- We read a listing again when an order for it comes in and on a regular schedule; each product's last_checked_at says when we last did. Keeping products in sync is free.
- Every change we act on is also an event: product.cost_changed and product.out_of_stock.
The Sync rule object
idstring- Starts rule_; the default rule is rule_default.
applies_tostring- all for the default rule, or a product id for an override.
on_cost_increase.actionstring- reprice to keep your margin, pause the product, or notify only.
on_cost_increase.keep_margin_percentstring- With reprice: the margin to keep, of the sale price.
on_cost_increase.max_increase_percentstring|null- With reprice: the most a price may rise at once. Above it, above_max applies: pause or notify.
on_cost_decreasestring- keep_price, or reprice down to the same margin.
on_out_of_stockstring- Always zero_stock: a sold-out SKU shows 0 on your channels.
on_back_in_stockstring- restock, or stay_paused until you resume it.
round_tostring|null- A price ending for repriced prices, such as .99 or .00.
{
"id": "rule_default",
"applies_to": "all",
"on_cost_increase": {
"action": "reprice",
"keep_margin_percent": "30",
"max_increase_percent": "15",
"above_max": "pause"
},
"on_cost_decrease": "keep_price",
"on_out_of_stock": "zero_stock",
"on_back_in_stock": "restock",
"round_to": ".99",
"updated_at": "2026-11-02T08:00:00Z"
}List sync rules
GET/v1/sync_rules
The default rule first, then every per-product override.
Scopeproducts:read
curl "https://www.ninjabuy.com/api/v1/sync_rules" \
-H "Authorization: Bearer $NINJABUY_API_KEY" \
-H "NinjaBuy-Version: 2026-11"HTTP/2 200 OK
{
"data": [
{
"id": "rule_default",
"applies_to": "all",
"on_cost_increase": {
"action": "reprice",
"keep_margin_percent": "30",
"max_increase_percent": "15",
"above_max": "pause"
},
"on_cost_decrease": "keep_price",
"on_out_of_stock": "zero_stock",
"on_back_in_stock": "restock",
"round_to": ".99",
"updated_at": "2026-11-02T08:00:00Z"
},
{
"id": "rule_9p3e",
"applies_to": "prd_1x0a",
"on_cost_increase": { "action": "pause" },
"on_cost_decrease": "keep_price",
"on_out_of_stock": "zero_stock",
"on_back_in_stock": "stay_paused",
"round_to": null,
"updated_at": "2026-11-03T10:14:00Z"
}
],
"has_more": false,
"cursor": null
}Retrieve a sync rule
GET/v1/sync_rules/{id}
One rule.
Scopeproducts:read
Path parameters
idstringrequired- The rule's id.
Errors
| Status | Type | When |
|---|---|---|
| 404 | not-found | No such rule on this account. |
curl "https://www.ninjabuy.com/api/v1/sync_rules/rule_default" \
-H "Authorization: Bearer $NINJABUY_API_KEY" \
-H "NinjaBuy-Version: 2026-11"HTTP/2 200 OK
{
"id": "rule_default",
"applies_to": "all",
"on_cost_increase": {
"action": "reprice",
"keep_margin_percent": "30",
"max_increase_percent": "15",
"above_max": "pause"
},
"on_cost_decrease": "keep_price",
"on_out_of_stock": "zero_stock",
"on_back_in_stock": "restock",
"round_to": ".99",
"updated_at": "2026-11-02T08:00:00Z"
}Override for a product
POST/v1/sync_rules
A product with its own rule follows it instead of the default. Fields you leave out take the default's.
Scopeproducts:write
Body
applies_tostringrequired- all for the default rule, or a product id for an override.
on_cost_increase.actionstring- reprice to keep your margin, pause the product, or notify only.
on_cost_increase.keep_margin_percentstring- With reprice: the margin to keep, of the sale price.
on_cost_increase.max_increase_percentstring|null- With reprice: the most a price may rise at once. Above it, above_max applies: pause or notify.
on_cost_decreasestring- keep_price, or reprice down to the same margin.
on_out_of_stockstring- Always zero_stock: a sold-out SKU shows 0 on your channels.
on_back_in_stockstring- restock, or stay_paused until you resume it.
round_tostring|null- A price ending for repriced prices, such as .99 or .00.
Errors
| Status | Type | When |
|---|---|---|
| 404 | not-found | No such product on this account. |
| 409 | invalid-state | The product has an override already: replace that one. |
curl -X POST "https://www.ninjabuy.com/api/v1/sync_rules" \
-H "Authorization: Bearer $NINJABUY_API_KEY" \
-H "NinjaBuy-Version: 2026-11" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"applies_to": "prd_1x0a",
"on_cost_increase": { "action": "pause" },
"on_back_in_stock": "stay_paused"
}'HTTP/2 201 Created
{
"id": "rule_9p3e",
"applies_to": "prd_1x0a",
"on_cost_increase": { "action": "pause" },
"on_cost_decrease": "keep_price",
"on_out_of_stock": "zero_stock",
"on_back_in_stock": "stay_paused",
"round_to": null,
"updated_at": "2026-11-03T10:14:00Z"
}Replace a sync rule
PUT/v1/sync_rules/{id}
Send the whole rule. It applies from the next time we read each listing.
Scopeproducts:write
Path parameters
idstringrequired- The rule's id.
Body
on_cost_increase.actionstring- reprice to keep your margin, pause the product, or notify only.
on_cost_increase.keep_margin_percentstring- With reprice: the margin to keep, of the sale price.
on_cost_increase.max_increase_percentstring|null- With reprice: the most a price may rise at once. Above it, above_max applies: pause or notify.
on_cost_decreasestring- keep_price, or reprice down to the same margin.
on_out_of_stockstring- Always zero_stock: a sold-out SKU shows 0 on your channels.
on_back_in_stockstring- restock, or stay_paused until you resume it.
round_tostring|null- A price ending for repriced prices, such as .99 or .00.
Errors
| Status | Type | When |
|---|---|---|
| 404 | not-found | No such rule on this account. |
curl -X PUT "https://www.ninjabuy.com/api/v1/sync_rules/rule_default" \
-H "Authorization: Bearer $NINJABUY_API_KEY" \
-H "NinjaBuy-Version: 2026-11" \
-H "Content-Type: application/json" \
-d '{
"on_cost_increase": { "action": "notify" },
"on_cost_decrease": "keep_price",
"on_out_of_stock": "zero_stock",
"on_back_in_stock": "restock",
"round_to": ".99"
}'HTTP/2 200 OK
{
"id": "rule_default",
"applies_to": "all",
"on_cost_increase": { "action": "notify" },
"on_cost_decrease": "keep_price",
"on_out_of_stock": "zero_stock",
"on_back_in_stock": "restock",
"round_to": ".99",
"updated_at": "2026-11-02T08:00:00Z"
}Delete an override
DELETE/v1/sync_rules/{id}
The product follows the default rule again. rule_default itself cannot be deleted.
Scopeproducts:write
Path parameters
idstringrequired- The rule's id.
Errors
| Status | Type | When |
|---|---|---|
| 409 | invalid-state | rule_default cannot be deleted. |
curl -X DELETE "https://www.ninjabuy.com/api/v1/sync_rules/rule_9p3e" \
-H "Authorization: Bearer $NINJABUY_API_KEY" \
-H "NinjaBuy-Version: 2026-11"HTTP/2 200 OK
{ "id": "rule_9p3e", "deleted": true }