
# Customers

Kibanda remembers each customer so they never type the same thing twice: their name, saved delivery addresses, and the M-Pesa number they pay with. The API lets you read that, add your own notes and tags, and link each customer to the record in your CRM or ERP.

## The customer object

```json
{
  "id": "ct_…",
  "object": "customer",
  "name": "Achieng Otieno",
  "phone": "+254712345678",
  "mpesa_phone": "+254712345678",
  "whatsapp_user_id": "254712345678",
  "email": "achieng@example.com",
  "notes": "Gate B, call on arrival",
  "tags": ["vip"],
  "payment_terms": "default",
  "delivered_orders": 12,
  "refused_orders": 0,
  "order_count": 13,
  "total_spent": 512000,
  "addresses": [{ "id": "ad_…", "object": "address", "label": "Home", "lat": -1.2921, "lng": 36.7856, "landmark": "Blue gate", "last_used": 1792716000 }],
  "external_id": "res.partner/4211",
  "metadata": {},
  "last_message_at": 1792716000,
  "created": 1792000000
}
```

`order_count`, `total_spent` and `addresses` are included when you retrieve one customer. `phone` can be `null` for WhatsApp username users who haven't shared their number.

## Create a customer

`POST /v1/customers` — e.g. importing from Shopify or Odoo. When they later message the shop on WhatsApp they're recognised, and their saved details apply.

| Parameter | |
|---|---|
| `phone` | **Required.** `+254712345678`, `0712 345 678`, … |
| `name`, `email`, `notes`, `tags`, `mpesa_phone`, `external_id`, `metadata` | |
| `upsert` | `true` to update the existing customer with this phone instead of getting `409 customer_exists`. |

## Update a customer

`POST /v1/customers/{id}` — `name`, `email`, `notes`, `tags` (replaces the list), `mpesa_phone`, `payment_terms` (`default` = the shop's rules, `pay_first`, `trusted`), `external_id`, `metadata`.

## Saved addresses

- `POST /v1/customers/{id}/addresses` — `lat`, `lng` (required), `label`, `landmark`. Offered at checkout so the customer doesn't share a pin.
- `DELETE /v1/customers/{id}/addresses/{address_id}`

## Retrieve and list

- `GET /v1/customers/{id}`
- `GET /v1/customers` — filters: `phone`, `email`, `external_id`, `tag`, `created_gte`, `created_lt`.

## Keeping your CRM in sync

1. Subscribe to `customer.created`. For each, find or create the person in your system (match on `phone`).
2. Write your id back: `POST /v1/customers/{id}` with `{"external_id": "res.partner/4211"}`.
3. From then on, every order carries `customer.external_id`, so you can file it without a lookup.
