Merchant customers
Browse and inspect the merchant's customers from the Dashboard, including their saved payment instruments and order history.
These endpoints back the Dashboard's customers screen for a single merchant: list payers with search and filters, open one to see its full detail, and update or remove a record.
A customer groups everything a payer owns within this merchant — saved payment instruments, orders, and subscriptions. Customers never cross merchant boundaries, so the same person shopping at two of your merchants is two separate customer records.
These endpoints power the Tokeflow Dashboard UI. They are session-authenticated (JWT bearer) — the token comes from signing in to the Dashboard, not from an sk_/pk_ API key. Requests also carry the x-merchant-id header identifying the merchant in context, and the signed-in user must be a member with access to it.
The customer object
Returned by the list and retrieve endpoints on this page.
| Field | Type | Description |
|---|---|---|
id | string | — |
organization_id | string | — |
merchant_id | string | — |
merchant_name | string | — |
name | string | null | Nullable because the column is. The org service coerces it to '' when it builds its literals, but the merchant dashboard returns the entity through plainToInstance and so passes a real null straight to the client — which declaring this string hid, and which reached the UI as an empty page heading and a "Deleting null" confirmation. |
email | string | — |
phone | string | null | — |
document_type | string | null | — |
document_number | string | null | — |
metadata | object | null | — |
created_at | string | (ISO 8601 UTC). |
updated_at | string | (ISO 8601 UTC). |
deleted | boolean | True once the customer has been deleted. Deleted customers stay readable for history but cannot be used for new operations. |
payment_instruments | array | — |
linked_subscriptions | array | Linked subscriptions (future feature). |
linked_orders | array | — |
external_references | array | — |
Endpoints
GET/api/v1/merchant/customers
Auth: Dashboard session (JWT bearer). Merchant membership required.
List customers for merchant.
Query parameters
| Field | Type | Required | Description |
|---|---|---|---|
page | number | No | Page number (1-indexed). Default 1, min 1. |
limit | number | No | Number of items per page. Default 20, min 1, max 100. |
merchant_id | string | No | Filter by merchant ID |
search | string | No | Search by name, email, or customer ID |
start_date | string | No | Start date (ISO 8601) |
end_date | string | No | End date (ISO 8601) |
Example request
curl -G https://api.tokeflow.com/api/v1/merchant/customers \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…" \
-H "x-merchant-id: mrc_8a3f12d9" \
--data-urlencode "page=1" \
--data-urlencode "limit=20" \
--data-urlencode "merchant_id=mrc_8a3f12d9" \
--data-urlencode "search=string"DELETE/api/v1/merchant/customers/:id
Auth: Dashboard session (JWT bearer). Merchant membership required.
Permanently deletes a customer. Cancels every subscription that is not already cancelled or expired, revokes all saved payment methods — removing the stored card details — then retires the customer. This cannot be undone. The customer stays retrievable through GET /:id so its history remains reviewable, but drops out of the customer list and can no longer be used for new operations, and its email becomes available again. Note this differs from DELETE on the API-key surface (/customers/:customerId), which instead refuses with 409 when a customer has any history.
Path parameters
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | — |
Example request
curl -X DELETE https://api.tokeflow.com/api/v1/merchant/customers/obj_1a2b3c4d \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…" \
-H "x-merchant-id: mrc_8a3f12d9"Example response — 200
{
"id": "cust_123",
"object": "customer",
"deleted": true
}GET/api/v1/merchant/customers/:id
Auth: Dashboard session (JWT bearer). Merchant membership required.
Get customer by ID.
Path parameters
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | — |
Example request
curl https://api.tokeflow.com/api/v1/merchant/customers/obj_1a2b3c4d \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…" \
-H "x-merchant-id: mrc_8a3f12d9"Example response — 200
{
"id": "obj_1a2b3c4d",
"organization_id": "org_4b21e7c3",
"merchant_id": "mrc_8a3f12d9",
"merchant_name": "Acme Store",
"name": "Jane Buyer",
"email": "jane@example.com",
"phone": "+5511987654321",
"document_type": "12345678909",
"document_number": "12345678909",
"metadata": {},
"created_at": "2026-01-15T12:30:00.000Z",
"updated_at": "2026-01-15T12:30:00.000Z",
"deleted": false,
"payment_instruments": [
{
"id": "obj_1a2b3c4d",
"instrument_type": "standard",
"last4": "string",
"brand": "string",
"card_type": "standard",
"exp_month": 1,
"exp_year": 1,
"external_wallet_id": "string",
"status": "active",
"is_default": true,
"created_at": "2026-01-15T12:30:00.000Z"
}
],
"linked_subscriptions": [
{}
],
"linked_orders": [
{
"id": "obj_1a2b3c4d",
"status": "active",
"total_amount": 15000,
"currency": "BRL",
"created_at": "2026-01-15T12:30:00.000Z"
}
],
"external_references": [
{
"source_type": "standard",
"connector_name": "Acme Store",
"external_id": "string"
}
]
}PATCH/api/v1/merchant/customers/:id
Auth: Dashboard session (JWT bearer). Merchant membership required.
Update customer.
Path parameters
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | — |
Request fields
| Field | Type | Required | Description |
|---|---|---|---|
name | string | No | — |
email | string | No | — |
phone | string | No | — |
document_type | string | No | One of cpf, cnpj, passport, tax_id. |
document_number | string | No | — |
Example request
curl -X PATCH https://api.tokeflow.com/api/v1/merchant/customers/obj_1a2b3c4d \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…" \
-H "x-merchant-id: mrc_8a3f12d9" \
-H "Content-Type: application/json" \
-d '{
"name": "Acme Store",
"email": "jane@example.com",
"phone": "+5511987654321",
"document_type": "cpf",
"document_number": "12345678909"
}'Example response — 200
{
"id": "obj_1a2b3c4d",
"organization_id": "org_4b21e7c3",
"merchant_id": "mrc_8a3f12d9",
"merchant_name": "Acme Store",
"name": "Jane Buyer",
"email": "jane@example.com",
"phone": "+5511987654321",
"document_type": "12345678909",
"document_number": "12345678909",
"metadata": {},
"created_at": "2026-01-15T12:30:00.000Z",
"updated_at": "2026-01-15T12:30:00.000Z",
"deleted": false
}Errors
Errors use the standard envelope. The most common cases here:
| HTTP | Meaning |
|---|---|
400 | Invalid parameters or a state that does not allow this operation. |
401 | Missing, expired, or invalid Dashboard session token. |
403 | Authenticated, but the signed-in user lacks access to this entity. |
404 | The record does not exist or is not visible to this entity. |