Customers are end-users who placed an order on your storefront. They're created automatically at first checkout — there is no public sign-up flow at v1. Each customer is scoped to one store: the same phone number on two different stores creates two customer rows.
Deduplication: when a new checkout arrives, we match on store + phone. If that customer already exists, their email/address/wilaya are updated and the record is reused; otherwise a new one is created. Email is not used for dedup — historically merchants get many anonymous orders without an email.
When a customer is created through POST /v1/orders, the entire customer.name string is stored in first_name and last_name is left empty — the first/last split shown in the examples below never happens for API-created records. For an existing customer matched by phone, only first_name is overwritten and any existing last_name is left untouched. Split client-side if you need it.
GET /v1/customers
List customers in your store. Cursor-paginated.
Auth: platform key with customers:read, which new keys carry by default. Without it the call answers 403 forbidden.
Query parameters
Param | Type | Notes |
| int 1–200 | Default 50 |
| string | Opaque |
| string | Exact match on the stored number. Storefront and landing page checkouts store Algerian mobiles as |
| string | Exact match, case-insensitive |
There are no date, free-text search, sort or is_banned filters at v1; results are always newest-id-first.
Request
curl 'https://api.dzbuild.app/v1/customers?limit=20' \ -H "Authorization: Bearer $DZ_KEY"
Response 200
{
"data": {
"items": [
{
"id": 5578,
"first_name": "John",
"last_name": "Doe",
"phone": "0555000000",
"email": null,
"wilaya_id": 16,
"commune": "Bab Ezzouar",
"total_orders": 3,
"total_spent": 4500,
"is_banned": false,
"created_at": "2026-03-17 15:18:13",
"updated_at": "2026-04-15 12:01:08"
}
],
"next_cursor": "NDk=",
"has_more": true
}
}
⚠️ Warning — total_orders / total_spent are stale counters, not live aggregates
They are only incremented when an order is placed from a landing page or created manually in the dashboard. They are never adjusted on a status change (a cancelled order still counts), and orders created via the storefront or POST /v1/orders never update them at all. Don't use them for revenue reporting — aggregate GET /v1/orders (or /v1/customers/{id}/orders) yourself.
GET /v1/customers/{id}
Full detail.
Auth: platform key with customers:read.
Response 200
{
"data": {
"id": 5578,
"first_name": "John",
"last_name": "Doe",
"phone": "0555000000",
"email": "[email protected]",
"wilaya_id": 16,
"commune": "Bab Ezzouar",
"address": "12 Rue X",
"notes": null,
"total_orders": 3,
"total_spent": 4500,
"fraud_score": 0,
"is_banned": false,
"created_at": "2026-03-17 15:18:13",
"updated_at": "2026-04-15 12:01:08"
}
}
Field | Notes |
| Reserved. Neither the dashboard nor the API writes it, so expect |
| Always |
| Set when you blacklist the customer in the dashboard. Storefront and landing-page checkouts reject banned customers — but |
Device / identity signals | Not exposed via API for privacy reasons |
GET /v1/customers/{id}/orders
Customer's orders, cursor-paginated, newest first.
Auth: platform key with customers:read.
The customer id is ownership-checked first, so an unknown id, or one belonging to another store, returns 404 not_found rather than an empty list.
Request
curl 'https://api.dzbuild.app/v1/customers/5578/orders?limit=10' \ -H "Authorization: Bearer $DZ_KEY"
Response 200
{
"data": {
"items": [
{ "id": 6894, "order_number": "ORD-13-20260317-AD3C91F7", "status": "confirmed",
"payment_status": "pending", "total": 1000, "created_at": "2026-03-17 15:18:13" }
],
"next_cursor": null,
"has_more": false
}
}
This is a subset of /v1/orders filtered by customer_id, with a shorter summary: id, order_number, status, payment_status, total and created_at only. To get the full order body call /v1/orders/{id}.
Common patterns
"Find a customer by phone, then list their orders"
PHONE="0555000000"
CUST=$(curl -sS "https://api.dzbuild.app/v1/customers?phone=$PHONE&limit=1" \
-H "Authorization: Bearer $DZ_KEY" | jq -r '.data.items[0].id')[ -z "$CUST" ] && { echo "no customer"; exit 1; }curl -sS "https://api.dzbuild.app/v1/customers/$CUST/orders" \
-H "Authorization: Bearer $DZ_KEY"
"Top 10 spenders this month"
There's no native sort-by-spend filter at v1, and total_spent is a stale counter (see the warning above). Query /v1/orders?since=... and sum total per customer_phone: the list summary carries the phone, not the customer id. Skip cancelled and returned orders if you only want kept sales.
Privacy notes
The API never exposes device fingerprints or any cross-store identity link.
Customer email/phone are PII — be careful about logging them.
Future right-to-erasure (RGPD-style) requests should go through dashboard / support; the API will gain a
DELETE /v1/customers/{id}endpoint in a future version with explicit cascade rules.