JENNi Stores API
## Manage your stores A **store** is a physical or virtual location you sell from. Every inventory level you push is written *to a store*, so a store must be registered before its first level — a level against an unregistered store is rejected with `422 unknown-store`. Register with `POST /provider/v1/stores`; afterwards, read and maintain the store with the routes below. ### Identity You address a store by **your own** `retailer_store_id` — the one you chose when you registered it. JENNi assigns a `jenni_store_id` too, but you never need to send it. A store always belongs to the provider on your API key, which is why none of the management routes take a `provider_id` (sending one is a `400`). A store you did not register, or one that has since been deleted or merged into another, is a `404 store-not-found`. ### Which key Reads (`GET`) accept a read, write or ingest key. Writes (`PATCH`, `PUT …/hours`, `POST`) need a write or ingest key. Every write except the original `POST` requires an `Idempotency-Key` header. ### Details `PATCH /provider/v1/stores/{retailer_store_id}` changes any subset of the store's details — name, address, coordinates, contact, `store_url`, `logo_url`, `is_active`. Send only the fields you want to change: omitted fields are untouched, `null` clears a field. `logo_url` must be `https://`, at most 2048 characters, with a real hostname (never an IP address). Types are strict: `is_active` is `true` or `false` and cannot be cleared with `null`; `lat`/`lng` are JSON numbers, never strings. Send `lat` and `lng` together: both numbers, or both `null` to clear the location. A lone `lat` or `lng`, a mix of number and `null`, and `0,0` are refused with a 400. The response is the full store as it now stands. ### Hours Hours live in the store's `hours` block: a `weekly` schedule keyed by the seven upper-case day names, each a list of up to three `{open, close}` intervals on a 24-hour `HH:MM` clock (an empty list means closed that day; `close` earlier than `open` means the store closes after midnight), plus `special` — dated overrides such as holidays, at most 60, each with a `closed` flag and an optional `reason`. Each `special` date may appear only once; a second row for the same day is a `400`, not a merge. Set them with `PUT /provider/v1/stores/{retailer_store_id}/hours` (or as `hours` inside a `PATCH`); read them back as the `hours` block of `GET /provider/v1/stores/{retailer_store_id}` (the separate `GET …/hours` read is deprecated and answers with a `Sunset` header). `hours.source` tells you who owns them. Once a merchant edits a store's hours in the JENNi Console the source becomes `merchant` and **your hours writes are refused with `409 hours-merchant-managed`** — nothing is applied, including other fields in the same `PATCH`. Ask the merchant to hand hours back to you, or leave them; everything else about the store stays yours to update. The `store_hours` field on `POST /provider/v1/stores` is **deprecated**. It still works, but only with the same weekly dict `PUT …/hours` takes; any other shape is a `400` that points you at the new route.