Skip to main content
Read this once and you will be able to use any endpoint in the API without surprises.

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_id is the unique SKU-level key for products and transactions; product_id is 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 a POST /v1/<entity>/bulk endpoint that accepts an items array and returns per-item results. Request:
Response (BulkResponse):
A bulk request is never all-or-nothing. Successful rows are written even if other rows fail. Always inspect each 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

The POST /v1/imports/* endpoints accept a multipart CSV and return immediately with a JobHandle:
Poll status with 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:
You can submit them as either numbers or strings on the way in, but expect strings in responses. Parse with a decimal library on the client side.

Timestamps

All timestamps are ISO 8601 in UTC:
Date-only fields use 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. Pass limit 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 receive 429 Too Many Requests with a Retry-After header. Specific numbers will be published here once we have stable production data.