Save a Counterparty
Saves a destination an account can withdraw to: a coin and an address, plus the memo on chains that route by one. v2 calls it a beneficiary; it is the same record.
An account cannot save the same destination twice for one coin. Saving one that was deleted brings the original record back, with the same id, so withdrawals that named it before still find it. The restored record takes the label, network and reference sent now; one left out is cleared.
The address is checked for its form only, not against the chain: an address that is not valid on the coin's network is saved all the same. Check it before saving.
This endpoint takes no Idempotency-Key. Retrying a save that went through answers 409 counterparty_already_exists; find the record with List Counterparties.
Part of crypto v3, in beta. While crypto v3 counterparties are off for the account, this answers 404 feature_not_enabled.
customer_id is required from every key: a workspace-scoped key names any account of the workspace; an account-scoped key names its own.
Replaces POST /api/v2/crypto/beneficiaries.
Authorization:
Every request is signed with your API key: a short-lived JWT, signed with your private key, sent in one header on /v3/* and /api/v2/* alike.
Headers:
Authorization: APIKey {SIGNED_JWT}
How to build and sign the JWT: Authentication.
Endpoint
/v3/crypto/counterparties
Request Body Sample
{
"customer_id": "cst_01h455vb4pex5vsknk084sn02q",
"coin": "USDC",
"address": "0x8f3b2c1d0e9a7b6c5d4e3f2a1b0c9d8e7f6a5b4c",
"label": "Supplier payouts",
"network": "ERC20",
"reference": "supplier-17"
}
Request Body Schema
| Field | Type | Description |
|---|---|---|
customer_id | string (cst_…) | Required. The account the counterparty belongs to. |
coin | string | Required. A crypto ticker, for example BTC or USDC. Any casing is accepted; the answer is upper case. |
address | string | Required. Where the money goes, up to 255 characters, with no spaces. On a chain that routes by memo it may carry the memo as <address>?dt=<tag>, the way exchanges often show it. |
tag | string | The memo, on chains that route by one (XRP); up to 64 characters, with no spaces. Sending it as well as a memo inside address is fine when the two agree. |
label | string | Optional. Your name for it, up to 255 characters. |
network | string | Optional. A note of the chain, for example ERC20, up to 255 characters. Descriptive only: the coin decides where the money goes. |
reference | string | Optional. Your own string, up to 255 characters, answered back on reads. It need not be unique. |
Response Sample
200 OK
{
"id": "wlt_01k8z5q7r9s1t3v5w7x9y1z3a5",
"customer_id": "cst_01h455vb4pex5vsknk084sn02q",
"coin": "USDC",
"address": "0x8f3b2c1d0e9a7b6c5d4e3f2a1b0c9d8e7f6a5b4c",
"label": "Supplier payouts",
"network": "ERC20",
"reference": "supplier-17",
"status": "active",
"created_at": "2026-10-20T15:40:00Z",
"updated_at": "2026-10-20T15:40:00Z"
}
Response Schema
The counterparty, with the fields of a List Counterparties row, without customer. The memo, if any, is in tag, never inside address.
It also sends the crypto_beneficiary_created webhook.
Errors
| Status | message | When |
|---|---|---|
400 | failed to parse request | The body is not valid JSON, customer_id is not a cst_… id, or coin is not a ticker. |
400 | customer_required | No customer_id. |
400 | invalid_account_id | A workspace-scoped key sent an account_id query parameter (see Turning it on) that is not a cst_… id. |
400 | coin_not_crypto | coin is a fiat currency, such as USD. |
400 | invalid_address | address is only spaces, has spaces or control characters inside it, ends in ?dt= with no memo, carries ?dt= twice, or is longer than 255 characters together with its memo. |
400 | tag_conflict | address carries one memo and tag another. |
400 | invalid_tag | tag has spaces or control characters, or contains ?dt=. |
400 | invalid_label | label is longer than 255 bytes (characters outside ASCII take more than one). |
401 | unauthorized | Missing or invalid signature. |
403 | forbidden | An account-scoped key named another account, or customer_id is not an account of the workspace. |
404 | feature_not_enabled | Crypto v3 counterparties are not enabled for the account. See Turning it on. |
409 | counterparty_already_exists | The account already has this destination for this coin. |
422 | Validation failed | coin or address is missing, or a text field is longer than allowed; details names it. |
Coming from v2
v2 (POST /api/v2/crypto/beneficiaries) | v3 |
|---|---|
accountId (uuid) | customer_id (cst_…) |
reference required | reference optional, and not unique |
memo only inside address | tag, or inside address |
id (uuid) | id (wlt_…): the same id as a TypeID |
createdAt, updatedAt | created_at, updated_at |
Support and Resources
If you need assistance or have any questions, our support team is here to help. You can contact our support team at support@blockwyre.com.
Stay Updated
Stay up-to-date with the latest news, updates, and features from BlockWyre by following us on social media:
- Instagram: BlockWyre Instagram
- Twitter: BlockWyre Twitter
- Facebook: BlockWyre Facebook
- LinkedIn: BlockWyre LinkedIn
We are excited to have you on board and look forward to seeing how you leverage BlockWyre's powerful tools to enhance your financial operations. Happy integrating!