Overview / Authentication

Authentication

Every request carries an API key and its secret. The pair identifies a brand and a set of scopes; there is no user session and no cookie.

Creating a key

In the panel: System → API keys. Pick the scopes the integration actually needs and either set an expiry date or mark the key as never expiring.

The secret is shown once, at creation time. It is stored hashed, so it cannot be recovered — only rotated. Rotating changes the secret and keeps the key, so an integration only has to update one value.

Sending credentials

Three equivalent forms. Use the first unless something in your stack prevents it.

Authorization: Bearer <key>:<secret>

X-Api-Key: <key>
X-Api-Secret: <secret>

Authorization: Basic base64(<key>:<secret>)

What each rejection means

CodeMeaning
authentication_requiredNothing was sent, or the header could not be parsed.
invalid_credentialsThe key does not exist, or the secret does not match. The two cases are deliberately indistinguishable — a wrong key must not confirm that another key exists.
key_revokedSomeone switched the key off in the panel. Create a new one.
key_expiredPast its expiry date. The message names the exact date.
insufficient_scopeCredentials are fine; this key was not given the scope this endpoint needs.
plan_upgrade_requiredAPI access starts with the Zincir plan.

Brand isolation

A key can only ever see its own brand. Asking for a record that belongs to someone else returns not_found, exactly as if the record did not exist — the API never confirms that another brand's id is real.