Identifiers
Two kinds of ids show up in the API:item_id/sku/competitor_name/ etc. - your stable business identifier. You provide it. Use it for upserts.item_idis the unique SKU-level key for products and transactions;product_idis an optional product-level code that groups related items.id/entity_id- Retailgrid’s internal row id, returned in responses. Use it in path parameters when patching or deleting (PATCH /v1/products/{entity_id}).
entity_id is a UUID for products, product variants, and transactions. For competitor prices it is an integer - the only place this varies in the API.
Bulk endpoints
Every entity has aPOST /v1/<entity>/bulk endpoint that accepts an items array and returns per-item results.
Request:
BulkResponse):
BulkItemResult.ok before declaring victory.
Recommended batch size: 500 to 2,000 items per request depending on row width. Larger payloads will work but increase latency and the chance of a transport-level retry.
Async jobs
ThePOST /v1/imports/* endpoints accept a multipart CSV and return immediately with a JobHandle:
GET /v1/jobs/{job_id}:
status is one of queued, running, completed, failed. A reasonable polling cadence is every 5-10 seconds for active jobs and every 30-60 seconds for queued jobs.
Sync vs async
See Imports vs bulk for the full decision tree.
Decimals
Money, quantities, and rates are returned as strings, not floats. This avoids the rounding surprises you would get with IEEE-754:Timestamps
All timestamps are ISO 8601 in UTC:YYYY-MM-DD. The API does not perform timezone conversion - send UTC, get UTC.
Idempotency
POST /v1/<entity>/{entity_id} is an upsert keyed on the path’s entity_id, which makes it safe to retry. PATCH is also idempotent at the field level. DELETE is idempotent (deleting an already-deleted row returns 204).
The /bulk endpoints are idempotent per item, keyed on the business identifier inside each item (item_id, sku, etc.).
There is no Idempotency-Key header today - we will add one before we recommend this API for payment-adjacent flows.
Pagination
List endpoints (products, transactions, grids, jobs, approved prices) use cursor-based pagination. Passlimit to set the page size, and to fetch the next page pass the cursor value returned as next_cursor in the previous response. A null next_cursor means there are no more rows.
Rate limits
Rate limits are applied per API key. Today’s limits are generous enough that well-behaved sync pipelines do not hit them; if you do, you will receive429 Too Many Requests with a Retry-After header. Specific numbers will be published here once we have stable production data.
