Customers
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 look up (store_id, phone). If a row exists, we update its email/address/wilaya and reuse it. If not, we create. Email is not used for dedup — historically merchants get many anonymous orders without an email.
GET /v1/customers
List customers in your store. Cursor-paginated.
Auth: platform key with customers:read.
Query parameters
| Param | Type | Notes |
|---|---|---|
limit | int 1–200 | Default 50 |
cursor | string | Opaque |
phone | string | Exact match |
email | string | Exact match (case-sensitive at v1) |
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
}
}
total_orders and total_spent are kept in sync by the platform whenever the customer's orders change status; you don't need to recompute them.
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": "john@example.com",
"wilaya_id": 16,
"commune": "Bab Ezzouar",
"address": "12 Rue X",
"notes": "Prefers afternoon delivery",
"total_orders": 3,
"total_spent": 4500,
"fraud_score": 10,
"is_banned": false,
"created_at": "2026-03-17 15:18:13",
"updated_at": "2026-04-15 12:01:08"
}
}
| Field | Notes |
|---|---|
notes | Merchant-private comment, set in dashboard |
fraud_score | 0-100 internal heuristic (high = suspect) |
is_banned | Set if you blacklisted them in dashboard. Future orders auto-rejected. |
device_fingerprint | 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.
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-AD3C", "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 — fields are the same as the orders list summary. 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. Walk the customer list and sort client-side; the dataset is small (typical store has < 5K active customers). Or query /v1/orders?since=... and aggregate by customer_id.
Privacy notes
- The API never exposes
device_fingerprintoridentity_id(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.