Products
What customers browse on WhatsApp. Changes show up in the chat immediately.
The product object
{
"id": "pr_…",
"object": "product",
"name": "Unga 2kg",
"description": "Jogoo, sifted",
"price": 25000,
"currency": "KES",
"active": true,
"stock": 40,
"available": 37,
"image_url": "https://api.kibanda.africa/media/…",
"code": "UNG4",
"external_id": "SKU-1001",
"metadata": {},
"created": 1792700000,
"updated": 1792716000
}
| Field | |
|---|---|
price |
Cents. 25000 = KES 250. |
stock |
Units on hand, or null to not track stock (never sells out). |
available |
stock minus units held by open orders. When it hits 0 the product shows as sold out. |
code |
Share code: "P-UNG4" sent to the shop opens this product. Also in its wa.me share link. |
active |
false hides it from the menu (kept for order history). |
external_id |
Your id (SKU, Shopify variant id, Odoo product.product id). Unique per shop. |
Stock is reserved when an order is placed, released if it's cancelled or fails, and sold when it's delivered — two customers can't buy the last one.
Create a product
POST /v1/products
| Parameter | |
|---|---|
name |
Required. 1–60 characters (WhatsApp shows ~24 in lists). |
price |
Required. Integer cents, > 0. |
description |
≤ 72 characters. |
stock |
Integer ≥ 0, or null. |
active |
Default true. |
external_id, metadata |
Update a product
POST /v1/products/{id} — send only what changes. Setting stock is how you restock:
curl $KIBANDA_API/v1/products/pr_123 -H "Authorization: Bearer $KIBANDA_KEY" \
-H "Content-Type: application/json" -d '{"stock": 120}'
Batch upsert
POST /v1/products/batch — up to 100 products, matched by external_id: existing ones are updated (only the fields you send), new ones created. This is the call for catalog sync.
{ "products": [
{ "external_id": "SKU-1001", "name": "Unga 2kg", "price": 25000, "stock": 40 },
{ "external_id": "SKU-1002", "stock": 0 }
] }
Returns a list of the products plus created and updated counts. If any item is invalid the error's param points at it (e.g. products[3].price).
Retrieve, list, archive
GET /v1/products/{id}GET /v1/products— filters:active=true|false,external_id,code. Paginated, most recently updated first.DELETE /v1/products/{id}— archives (setsactive: false).