Scope
customers:writeto create, update and delete;customers:readto list and read.
A customer is someone who pays you repeatedly. Each gets permanent deposit addresses of their own: money sent there at any time is detected and announced as customer.payment_detected, with no invoice to create first.
Create a customer#
/customers
Authorization: Bearer cv2_<mode>_<prefix>_<secret>
Content-Type: application/json{
"external_ref": "user_123",
"label": "Jane's store",
"chains": ["1", "tron-mainnet", "bitcoin-mainnet"]
}Idempotency-Key is optional here — see Idempotency.
| Field | Type | Required | Description |
|---|---|---|---|
chains |
string[] | Yes* | The networks this customer gets a permanent address on (at most 25) — any family, including Tron and the XRP Ledger |
external_ref |
string | No | Your own id for the customer (at most 255 characters) |
label |
string | No | A name you recognise (at most 255 characters) |
payment_source |
string | No | exchange_only, self_custody or unknown (default) |
receive_method |
string | No | auto (default), pool, static_derived or contract |
supported_assets |
string[] | No | Stored and returned; nothing decides on it |
evm |
boolean | — | Older integrations: true gives one EVM address on every EVM network you may hold a permanent address on |
btc, btc_chain_id |
boolean, string | — | Older integrations: a Bitcoin address on btc_chain_id (bitcoin-mainnet, bitcoin-testnet or bitcoin-signet) |
* Name at least one network, with chains (recommended), evm or btc; a request naming none is refused 400.
You need a verified wallet key for each family you ask for (set up in the dashboard). If any chosen network cannot give the customer an address, nothing is created: the answer is 422 with networks listing each refused network as { chainId, chainName, reason }.
Response 201:
{
"id": "uuid",
"merchant_id": "uuid",
"external_ref": "user_123",
"label": "Jane's store",
"supported_assets": ["native"],
"evm_address": null,
"btc_address": null,
"payment_source": "unknown",
"receive_method": "auto",
"deposits": [
{ "chainId": "1", "address": "0x...", "destinationTag": null },
{ "chainId": "tron-mainnet", "address": "T...", "destinationTag": null },
{ "chainId": "bitcoin-mainnet", "address": "bc1q...", "destinationTag": null }
]
}deposits lists the customer's address on each network you chose — on the XRP Ledger in tag mode, destinationTag is part of the destination. When an address could not be created on a network after the customer was, the response adds deposit_failures (chainId, chainName, reason, and a code when the reason is a stated rule such as ACCOUNT_RESOURCE_LIMIT_REACHED; without a code a retry from the dashboard may succeed). evm_address and btc_address are older fields, filled only by the evm / btc flags; with chains, read deposits. Those flags also add registration_warnings: ["registration_pending"] — the address is registered for watching on the next sync, within about a minute.
Two plan limits apply. The number of customers (Free: 2) — past it, create answers 402 PAYMENT_REQUIRED. The number of distinct deposit addresses (Free: 1) — past it, an address is refused 409 ACCOUNT_RESOURCE_LIMIT_REACHED, reported in deposit_failures when you used chains.
Read customers#
GET /customers
GET /customers/:id
GET /customers/:id/addressesGET /customers→{ "customers": [ … ] }; add?external_ref=user_123to find the one customer with that exact reference. Each customer carriesid,external_ref,label,evm_address,btc_address,created_at,deposit_addresses[](chain_id,chain_name,address,destination_tag,chain_enabled, andwatched_without_invoice— whether a payment there is seen:true,false, ornullwhen it could not be checked) and what the customer has paid you:confirmed_totals(what their paid invoices received, on time or late) andpending_totals(the invoiced amounts of invoices still confirming), each a list of{ chain_id, asset_key, total }in base units. ⚠️ The single figuresconfirmed_totalandpending_totaladd different assets together and are kept only for compatibility — read the lists.GET /customers/:id→{ "customer": { … }, "invoices": [ { "id", "chain_id", "asset_key", "expected_amount", "status", "matched_tx_hash", "created_at", "confirmed_at" } ] }GET /customers/:id/addresses→{ "addresses": [ { "id", "chainId", "address", "addressIndex", "destinationTag", "isPrimary", "createdAt" } ] }. A customer created with the olderevm/btcflags also lists rows withidprimary-evm/primary-btcandchainIdevm/btc, repeating its per-network rows.
Update and delete#
PATCH /customers/:id { "label": "…", "supported_assets": ["…"] } → { "success": true }
DELETE /customers/:id → { "success": true }Deleting a customer hides them from your list and cancels every subscription they still have (subscription.canceled with reason customer_deleted). Their addresses stay watched: a payment sent there later is still credited and announced, and the customer reappears. Their external_ref stays taken: POST /customers with it is refused 409 CUSTOMER_EXTERNAL_REF_TAKEN, and subscribing it is refused 409 CUSTOMER_ARCHIVED.