Catalog Push API
Push products, categories, locations, stock and pages from your server in idempotent batches, including full replace_all runs.
The Catalog Push API lets your server send catalog changes as they happen. It is available on every plan.
Authentication
Create an API key in Developers → API keys with the scope catalog:write, restricted to the store. Send it as Authorization: Bearer sa_live_… from your server only; never put it in a browser. See authentication.
Endpoints
POST/v1/stores/{store_id}/catalog/products:batchScope catalog:write
POST/v1/stores/{store_id}/catalog/products:deleteScope catalog:write
POST/v1/stores/{store_id}/catalog/categories:batchScope catalog:write
POST/v1/stores/{store_id}/catalog/locations:batchScope catalog:write
POST/v1/stores/{store_id}/catalog/inventory:batchScope catalog:write
POST/v1/stores/{store_id}/catalog/pages:batchScope catalog:write
Field reference: API reference → Catalog Push API. The locations:batch and inventory:batch endpoints also work for Magento, WooCommerce and PrestaShop stores that send store stock by feed.
Batches
- At most 500 items per batch and 5 MB per request; 120 batches per minute per store.
- Every batch needs an
Idempotency-Keyheader. Retrying with the same key returns the original response; reusing a key with a different body fails with422 idempotency_key_reused. Generate a new key for each new batch and reuse it only for retries of that batch. - The answer is
202 Acceptedwithaccepted,rejected(index and error per invalid item) and async_run_id. Valid items are processed even when others are rejected. - Batches of one store are applied in the order they were received.
curl -X POST "https://api.shopassist.coec.dk/v1/stores/sto_.../catalog/products:batch" \
-H "Authorization: Bearer $SHOPASSIST_API_KEY" \
-H "Idempotency-Key: 7f9c3a12-batch-0001" \
-H "Content-Type: application/json" \
-d '{"products":[{"external_id":"SHIRT-42","title":"Linen shirt","url":"https://shop.example.com/products/linen-shirt",
"variants":[{"external_id":"SHIRT-42-BLUE","sku":"SHIRT-42-BLUE","price":{"amount":"499.00","currency":"DKK"},"available_qty":12}]}]}'Prices are decimal strings in the store currency. Product URLs must be HTTPS on one of your allowed domains (url_not_allowed otherwise).
Full replace runs
To replace the whole catalog (products you no longer send are removed), push all products as one run:
- every batch carries
mode: "replace_all", the samerun_id(up to 64 characters,A–Z a–z 0–9 _ -) and abatch_indexstarting at 0; - the last batch carries
is_last_batch: true.
When all batches up to the last index have arrived, ShopAssist removes products that were not in the run. If that would remove more than half of the catalog, it stops and asks for confirmation in the dashboard. A run that is incomplete six hours after its first batch fails and removes nothing (push_run_incomplete). A batch for a finished run is refused (409 conflict, reason run_closed).
Errors
| Response | Meaning |
|---|---|
202 with rejected[] | Some items were invalid: validation_error, currency_mismatch, duplicate_external_id, too_many_variants, url_not_allowed |
409 conflict (feed_authoritative) | A full primary feed is enabled for this store |
409 conflict (run_closed) | The replace_all run already finished |
403 forbidden (test_key) | Test keys cannot write |
429 rate_limited | Wait for Retry-After seconds |
All error codes: API errors.
Order reports
To attribute revenue to conversations, report placed orders (no personal data, no order status) with the orders:report scope:
POST/v1/stores/{store_id}/orders:reportScope orders:report
Last updated on
Product feeds
Google Shopping XML, CSV and JSON feeds for Generic stores: supported fields, schedules, authentication, ETag caching and full-replace semantics.
Generic RPC for orders
Let the assistant read order status and run cancellations and returns on any store by answering signed RPC calls from ShopAssist.