JENNi Retailers API
## Bring a retailer onto JENNi A **retailer** is a business you are bringing onto JENNi — the merchant whose stores you will push inventory for. Registering it gives the merchant a place in the JENNi Console to claim; until they do, the retailer exists but has no owner. You register, you deliver the claim link, you can watch the claim land. ### The flow 1. `POST /provider/v1/retailers` with **your** `external_retailer_id` and the retailer's name — `201` with a `retailer_id`. Store it. Registering the same `external_retailer_id` again is a `200` with the same retailer, never a second one. 2. `POST /provider/v1/retailers/{retailer_id}/claim-links` — `201` with a `url` of the form `{CLAIM_URL_BASE}/claim?r=&t=`: `r` names the retailer being claimed and `t` is a single-use secret that expires at `expires_at` (7 days unless you shorten it). **The URL is shown once** — JENNi keeps only a hash of the token. Deliver it to the merchant yourself (JENNi sends nothing); if it is lost, issue a new link, which supersedes the old one. 3. `GET /provider/v1/retailers/{retailer_id}` — `claim.status` moves from `provisioned` to `invited` (a live link exists) to `claimed` (the merchant signed in and owns it), with `claimed_at` and a secret-free summary of the latest link. Poll it, or show it to your users as onboarding progress. 4. When you register the retailer's stores with `POST /provider/v1/stores`, send the `retailer_id` so JENNi can tie the store to the merchant who claimed it. ### Which key Reads (`GET`) accept a read, write or ingest key. The two `POST`s need a write or ingest key and an `Idempotency-Key` header. Everything is scoped to the provider on your key: no route takes a `provider_id`, and a retailer another provider registered is a `404 retailer-not-found` — exactly the response for an id that was never issued. ### Finding a retailer again `GET /provider/v1/retailers?external_retailer_id=…` returns the retailer you registered under that id (or an empty page). A paged listing of all your retailers, with `claim_status`, `cursor` and `limit`, is planned on the same route and will not break this call. ### Availability This surface is rolling out per environment. Where it is not enabled yet every call answers `503 retailers-unavailable` — retryable, and never a `404` you could mistake for a typo. Everything else in this API works regardless.