Save a Bank Counterparty
Saves a US account a withdrawal can pay. The coin is USD. Which fields the rail needs is in The rails.
reference is required and unique among the workspace's live bank accounts, counterparties and deposit accounts included. A reference already in use answers 409 counterparty_reference_taken. Deleting the counterparty frees the reference.
customer_id is required from every key: a workspace-scoped key names any account of the workspace; an account-scoped key names its own.
Send an Idempotency-Key with every save. There is no grace period: a request without it is refused. Retrying a save that went through with the same key answers the saved record again, with Idempotency-Replayed: true.
The response carries the full account number. There is no webhook.
Replaces POST /api/v2/banking/counterparties. A v2 withdrawal pays a counterparty saved here.
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/banking/counterparties
Headers
| Header | Description |
|---|---|
Idempotency-Key | Required, for API keys and dashboard sessions. One key per counterparty you mean to save: any printable-ASCII string of 1 to 255 characters (a UUID is recommended), sent again unchanged on every retry of it. A retry answers the first response, with Idempotency-Replayed: true. See Safe retries. |
Request Body Sample
ACH
{
"customer_id": "cst_01h455vb4pex5vsknk084sn02q",
"reference": "vendor-42",
"name": "Northwind LLC",
"holder_type": "business",
"bank_name": "Chase",
"instrument": "ach",
"account_type": "checking",
"routing_number": "021000021",
"account_number": "000123456789",
"address": {
"line1": "1 Market Street",
"line2": "Suite 400",
"city": "San Francisco",
"state": "CA",
"postal_code": "94105",
"country": "US"
},
"bank_address": {
"line1": "270 Park Avenue",
"city": "New York",
"state": "NY",
"postal_code": "10017",
"country": "US"
}
}
International wire
{
"customer_id": "cst_01h455vb4pex5vsknk084sn02q",
"reference": "intl-vendor-001",
"name": "Global Corp",
"holder_type": "business",
"bank_name": "National Westminster Bank",
"instrument": "wire",
"wire_type": "international",
"routing_number": "NWBKGB2L",
"swift": "NWBKGB2L",
"iban": "GB29 NWBK 6016 1331 9268 19",
"address": {
"line1": "10 Downing Street",
"city": "London",
"state": "London",
"postal_code": "SW1A 2AA",
"country": "GB"
}
}
Spaces in iban are dropped and it is stored upper case, as swift is.
Request Body Schema
| Field | Type | Description |
|---|---|---|
customer_id | string (cst_…) | Required. The account the counterparty belongs to. |
reference | string | Required. Your own reference, 1 to 255 characters. Unique among the workspace's live bank accounts. |
name | string | Required. Who is paid, 2 to 255 characters. Extra spaces are collapsed. |
holder_type | string | Required. individual or business. |
bank_name | string | Required. The bank, 2 to 255 characters. |
instrument | string | Required. ach or wire. |
wire_type | string | Required for a wire. domestic or international. Leave it out on ACH. |
account_type | string | Required for ACH. checking or savings. |
routing_number | string | Required. See The rails. At most 34 characters. |
account_number | string | Required for ACH and a domestic wire, and for an international wire that sends no IBAN. At most 34 characters. |
swift | string | Required for an international wire. 8 or 11 letters and digits. Stored upper case. |
iban | string | An international wire sends this or account_number. 15 to 34 letters and digits once spaces are dropped. Stored upper case. |
address | object | Required. line1 (1 to 255), line2 (optional, at most 255), city and state (each 1 to 100), postal_code (1 to 20), country (two letters). |
bank_address | object | Optional. The same shape as address. A domestic ACH often has none. Sending any of it means sending a complete address. |
Response Sample
200 OK
{
"id": "bcp_01k8z5q7r9s1t3v5w7x9y1z3a5",
"customer_id": "cst_01h455vb4pex5vsknk084sn02q",
"reference": "vendor-42",
"coin": "USD",
"name": "Northwind LLC",
"holder_type": "business",
"bank_name": "Chase",
"instrument": "ach",
"account_type": "checking",
"routing_number": "021000021",
"account_number": "000123456789",
"status": "active",
"address": {
"line1": "1 Market Street",
"line2": "Suite 400",
"city": "San Francisco",
"state": "CA",
"postal_code": "94105",
"country": "US"
},
"bank_address": {
"line1": "270 Park Avenue",
"city": "New York",
"state": "NY",
"postal_code": "10017",
"country": "US"
},
"created_at": "2026-10-23T12:00:00Z",
"updated_at": "2026-10-23T12:00:00Z"
}
Response Schema
The counterparty, with the fields of a List Bank Counterparties row, without customer. status is active. coin is USD.
Errors
| Status | message | When |
|---|---|---|
400 | failed to parse request | The body is not valid JSON, customer_id is not a cst_… id, or holder_type, instrument, wire_type or account_type is not one of its values. |
400 | customer_required | No customer_id. |
400 | invalid_holder_name | name is shorter than 2 characters once spaces are collapsed. |
400 | invalid_holder_type | holder_type is missing or not individual or business. |
400 | invalid_bank_name | bank_name is shorter than 2 characters. |
400 | invalid_reference | reference is empty once trimmed. |
400 | invalid_address | address or a bank_address that was sent is missing a line, a city, a state or a postal code, a line is too long, or country is not two letters. |
400 | invalid_instrument | instrument is not ach or wire. |
400 | invalid_wire_type | A wire was sent without wire_type domestic or international. |
400 | invalid_account_type | An ACH was sent without account_type checking or savings. |
400 | invalid_routing_number | ACH or a domestic wire: not a 9-digit ABA whose check digit holds. An international wire: empty. |
400 | invalid_account_number | ACH: not 4 to 17 digits. A domestic wire: empty or longer than 17. An international wire: neither an account number nor an IBAN, or the account number is longer than 34. |
400 | invalid_swift | An international wire whose SWIFT is not 8 or 11 letters and digits. |
400 | invalid_iban | An IBAN that is not 15 to 34 letters and digits. |
400 | idempotency_key_required | No Idempotency-Key header. |
400 | idempotency_key_invalid | The Idempotency-Key is longer than 255 characters or not printable ASCII. |
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. |
409 | counterparty_reference_taken | A live bank account in the workspace already uses this reference. |
409 | idempotency_in_progress | The same Idempotency-Key is still running. Retry after Retry-After seconds with the same key. |
422 | Validation failed | A required field is missing, or reference, name, bank_name or a number is longer than allowed; details names it. |
422 | idempotency_key_conflict | The same Idempotency-Key was used for a different request. |
503 | idempotency_unavailable | The retry store could not be reached. Nothing was saved: retry later with the same key. |
Coming from v2
v2 (POST /api/v2/banking/counterparties) | v3 |
|---|---|
| no idempotency header | Idempotency-Key required, with no grace period |
accountId (uuid) | customer_id (cst_…) |
counterpartyName | name |
type optional | holder_type required |
instrumentType, wireType, accountType | instrument, wire_type, account_type |
swiftCode | swift |
address.address1, address2, postalCode | address.line1, line2, postal_code |
bankAddress | bank_address |
| routing number of 9 digits for every rail | an international wire's routing number is only required to be present |
id (uuid), currency | id (bcp_…), coin (USD, not sent) |
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!