Conventions

What holds across the whole API: format, ids, dates, amounts, pagination, sorting, search, errors and rate limit.

Format

  • Base address: https://api.kivoo.africa/v1.
  • Requests and answers in JSON, UTF-8 encoded: send Content-Type: application/json with a body.
  • Calls are made from a server: the API sends no CORS header, a browser cannot call it.

Ids

Every resource has a UUID id, for instance 3a6c2f1e-8b4d-4c1a-9e2f-5d7b8a9c0e1f. Keep it as is: it goes into the addresses (/v1/products/{id}) and comes back in webhook events.

Dates

Every date is ISO 8601, in UTC: 2026-09-12T10:05:00.000Z. A missing date is null (an order not paid yet has no paidAt). In period filters, from is inclusive and to exclusive.

Amounts

Amounts are integers, in minor units of the currency given by the currency field (ISO 4217 code), which is the store’s. The CFA franc (XAF) has no decimals: 5000 is 5,000 FCFA. Never divide an amount by 100 without looking at the currency.

Pagination

Lists are paginated with two query parameters:

ParameterValuesDefault
page1 or more1
pageSize1 to 10025

The answer gives the page (data) and what you need to walk the next ones:

GET /v1/products?page=2&pageSize=25
{
  "page": 2,
  "pageSize": 25,
  "total": 42,
  "data": [{ "id": "3a6c2f1e-8b4d-4c1a-9e2f-5d7b8a9c0e1f", "title": "Guide du freelance" }]
}

While page × pageSize < total, pages remain. A page past the last one returns data: [].

  • Lists are sorted newest first (createdAt descending).
  • The q parameter searches case-insensitively: the title of products, the name, email and phone of customers.
  • Each list has its own filters (status, type, from, to…), described in the reference.

One store, and that one only

A key only sees its store. A resource of another store does not exist for it: Kivoo answers 404 (for instance product_not_found), never 403.

Errors

A refused request gets a 4xx or 5xx HTTP status and this body:

404 Not Found
{
  "statusCode": 404,
  "code": "product_not_found",
  "message": "Product not found",
  "requestId": "5b0f6a2c-6a0e-4f65-9d2b-2f3d1c0b9a77",
  "timestamp": "2026-09-26T10:00:00.000Z"
}
FieldContent
statusCodeThe HTTP status, repeated.
codeA stable, machine-readable code: branch your code on it.
messageAn explanation in English, which may change.
detailsOnly for some errors: the missing scope (required), the list of refused fields for validation_failed, what publishing needs (missing).
requestIdThe id of the request: give it to support when you write to Kivoo.
timestampWhen the error happened.

The codes the API returns:

Statuscode
400validation_failed (invalid parameter or body), and a few precise codes: compare_at_invalid, phone_invalid, customer_identifier_required, payment_link_expiry_invalid
401api_key_missing, api_key_invalid, api_key_revoked, api_key_expired (see Authentication)
403insufficient_scope, store_unavailable
404product_not_found, order_not_found, customer_not_found, payment_link_not_found
409customer_conflict: another customer of the store already has this email or phone
422product_incomplete (details.missing says what publishing needs), product_type_unavailable, feature_disabled, payment_link_invalid_pricing, payment_link_expiry_past
429rate_limited
5xxAn error on Kivoo’s side: try again later, with a growing delay.

The page of each operation, in the reference, lists the codes it may return.

Rate limit

Each key may make 120 requests per minute, all routes together. Two keys of the same store each have their own counter. Every answer carries:

HeaderContent
X-RateLimit-LimitThe number of requests allowed per minute (120).
X-RateLimit-RemainingThe requests left in the current minute.
X-RateLimit-ResetThe seconds before the counter starts again.

Beyond that, Kivoo answers 429 with the rate_limited code and the Retry-After header, in seconds: wait that long before trying again.

An IP address presenting more than 20 unknown keys per minute also gets 429 rate_limited, without its keys being checked: fix the key your program sends rather than retrying.

On this page