Authentication
API keys, scopes, 401 and 403 errors, and the good practices that keep a key secret.
The API key
Every request carries an API key of the store in the Authorization header:
GET /v1/products HTTP/1.1
Host: api.kivoo.africa
Authorization: Bearer kv_live_EXAMPLE0000000000000000000000000000000000- A key belongs to one store only. It only reaches that store’s resources, and no address of the API carries a store id.
- It starts with
kv_live_: the prefix lets secret scanners (GitHub, GitGuardian…) recognise it. There is no test mode. - It is shown once, when it is created. Kivoo only keeps a fingerprint: a lost key cannot be recovered, create another one.
- A store has at most ten active keys. A key may expire (30 days, 90 days, 1 year) or never.
- A revoked key is refused at once, and for good.
Keys are managed in Paramètres › Développeur › Clés API (Settings › Developer › API keys) by the owner of the store and Admin members.
Scopes
A key holds scopes: what it may do, resource by resource. They are chosen at creation and never change; to change them, create a new key, then revoke the old one.
| Resource | Read | Write |
|---|---|---|
| Store | store:read | — |
| Products | products:read | products:write |
| Orders | orders:read | — |
| Customers | customers:read | customers:write |
| Payment links | payment_links:read | payment_links:write |
- Write implies read on the same resource: a
products:writekey reads products too. - The store and the orders cannot be written through the API.
- Every page of the reference gives the scope the operation requires.
- Nothing a key does goes beyond what an Admin member of the store can do.
- A change made with a key is recorded in the activity journal under the key’s name (“Clé API « Zapier »”), not under the name of the person who created it.
Authentication errors
A refused request gets the usual error body (see Conventions) with a stable code:
| Status | code | What happened |
|---|---|---|
| 401 | api_key_missing | No Authorization header, or not in the Bearer <key> form. |
| 401 | api_key_invalid | The key does not exist (copy mistake, key of another platform). |
| 401 | api_key_revoked | The key was revoked. |
| 401 | api_key_expired | The key is past its expiry date. |
| 403 | insufficient_scope | The key lacks the required scope; details.required names it. |
| 403 | store_unavailable | The store is suspended or closed: its keys are refused while it stays so. |
401 answers also carry the WWW-Authenticate: Bearer realm="Kivoo API" header.
{
"statusCode": 403,
"code": "insufficient_scope",
"message": "This API key lacks the products:write scope",
"details": { "required": "products:write" },
"requestId": "5b0f6a2c-6a0e-4f65-9d2b-2f3d1c0b9a77",
"timestamp": "2026-09-26T10:00:00.000Z"
}Good practices
Never client-side
An API key never goes into a browser, a mobile app or a code repository: whoever reads it acts on your store. The API refuses calls from a browser anyway (no CORS header is sent back): call it from your server.
- Keep the key in an environment variable or a secret manager, never hard-coded.
- One key per tool: you can revoke one without cutting the others, and the activity journal tells which tool did what.
- Give each key the scopes it needs, no more.
- To replace a key, create the new one, deploy it, then revoke the old one.
- At the slightest doubt (key published by mistake, a contractor leaving), revoke the key: it is immediate.