SWIFT Cross-Border Payouts

Cross-border payouts use the SWIFT destination type when the destination country or currency has no local corridor (no ACH, SEPA, domestic GBP, mobile money, etc.). SWIFT is the fallback wire rail for USD, EUR, HKD, and similar currencies into most countries around the world.

When to use SWIFT

If GET /api/payouts/supported-countries/:country returns a corridor whose destination_types array contains "swift", that country supports SWIFT payouts. SWIFT is typically the only option when the destination currency isn't the country's native currency (e.g. paying USD into the UK, or EUR into Switzerland).


Three-Step Flow

SWIFT payouts are three separate HTTP calls. Beneficiary details go on the initialize call — not on the quote.

SWIFT Payout Flow
Beneficiary lives on Initialize

A common integration mistake is putting beneficiary/bank details on the quote. The quote body only carries currency/amount/country — all beneficiary information (SWIFT code, bank address, recipient address, sender identity) goes on the initialize call.


Step 1 — Create Quote

Describes the currency, amount, and destination country. No beneficiary info.

Create Quote
Request Body
field
type
required
description
from_asset
String
Required
Source asset being debited. Examples: 'USDC', 'USD', 'BTC', 'USDT'. Alphanumeric, max 10 chars.
to_currency
String
Required
Destination currency the beneficiary receives. Examples: 'USD', 'EUR', 'GBP', 'HKD'. Alphanumeric, max 10 chars.
source
String
Required
'offchain' debits your company balance; 'onchain' means the user funds the payout via crypto transfer.
chain
String
Conditional
Required when source = 'onchain'. Values: 'ETHEREUM', 'TRON', 'BTC', etc.
amount
String (decimal)
Conditional
Source-asset amount (e.g. '1500.00'). One of amount / settlement_amount / amount_in_base_units must be provided.
settlement_amount
String (decimal)
Conditional
Destination-currency amount. Use instead of amount when you want to pin the receive side.
amount_in_base_units
String (integer)
Conditional
Source amount in the asset's smallest unit. Alternative to amount.
country
String
Required
Destination country (ISO 3166-1 alpha-2 or alpha-3).
payment_reason
String
Optional
Free-text description of the payment.
reference
String
Optional
Client-generated idempotency / tracking key.
client_meta_data
String
Optional
Arbitrary metadata string for your own bookkeeping.
Example Request
Create Quote — SWIFT into GB
Example Response
Quote Response

Step 2 — Initialize with SWIFT Beneficiary

The initialize call carries the full SWIFT beneficiary payload. The server validates the beneficiary object against the corridor schema registered for (country, destination_type).

Initialize Payout
Top-Level Fields
field
type
required
description
beneficiary
Object
Required
The SWIFT beneficiary payload. Validated against the corridor schema for (country, destination_type). Details below.
customer_id
UUID
Optional
Link the payout to a persisted customer record.
reference
String
Optional
Overrides or supplements the quote's reference.
payment_reason
String
Optional
Free-text description of the payment.
callback_url
String
Optional
Per-payout webhook override URL.
client_meta_data
String
Optional
Arbitrary client metadata.
Snake_case input, uppercase enums internally

All fields are snake_case on our API. Enum values (destination_type, remittance_purpose, sender.type) are lowercase on input — the server uppercases them before forwarding to the underlying rail. Sending SWIFT also works (the discriminator lookup is case-insensitive), but swift / family_support / business is the canonical form.


Beneficiary — Core SWIFT Fields

Required on every SWIFT payload, regardless of destination country:

field
type
required
description
destination_type
String
Required
Must be 'swift' (lowercase). Explicitly set this — the server will fall back to 'bank' otherwise.
country
String
Required
ISO 3166-1 alpha-2 destination country. Must match the quote's country.
account_name
String
Required
Recipient's name. Must contain ≥2 space-separated parts of ≥2 chars each. Honorifics (Mr/Mrs/Dr) and single-letter-plus-dot (e.g. 'J.') are rejected.
account_number
String
Required
For IBAN countries (GB, DE, AT, AD, BE, BG, CH, FR, …) the IBAN, regex ^[A-Z0-9]{15,34}$. For non-IBAN countries (AR, BW, CN, …) a plain account number, 5–34 chars.
swift_code
String
Required
BIC/SWIFT code. 8 or 11 uppercase chars. Pattern: ^[A-Z]{4}[A-Z]{2}[A-Z0-9]{2}([A-Z0-9]{3})?$. Example: 'DEUTDEFF' or 'DEUTDEFF500'.
bank_name
String
Required
Full legal name of the receiving bank. Example: 'Deutsche Bank AG'.
bank_address
String
Required
Street address of the receiving bank branch.
bank_city
String
Required
City of the receiving bank branch.
bank_post_code
String
Required
Postal/ZIP code of the receiving bank.
bank_country
String
Required
ISO 3166-1 alpha-2 country of the receiving bank.
remittance_purpose
String (enum)
Required
Lowercase snake_case enum value — see the Remittance Purpose section below for the full list.
beneficiary
Object (nested)
Required
Physical address of the recipient — see 'Nested beneficiary' below.
sender
Object (nested)
Required
Payer identity — discriminated on type. See 'Sender variants' below.

Nested beneficiary — Recipient's Physical Address

Separate from the bank_* fields — this is the person or company receiving the money, not the bank branch.

field
type
required
description
country
String
Required
ISO 3166-1 alpha-2.
city
String
Required
Recipient's city.
post_code
String
Required
Recipient's postal/ZIP code.
address
String
Required
Recipient's street address.
type
String
Conditional
Only required when the destination country is RW (Rwanda) or SG (Singapore). One of 'business' or 'individual'. Every other SWIFT country omits it.

Sender — Payer Identity

The payer. Discriminated by type. Both variants share a common set of address fields; each variant adds its own.

Shared Fields (Both Variants)
field
type
required
description
type
String
Required
'business' or 'individual' (case-insensitive — normalized server-side).
account_name
String
Required
Legal name of the sender. Same name-format rules as beneficiary.account_name.
country
String
Required
ISO 3166-1 alpha-2 country of the sender.
city
String
Required
Sender's city.
address
String
Required
Sender's street address.
post_code
String
Required
Sender's postal/ZIP code.
type: "business" Only
field
type
required
description
registration_number
String
Required
Company registration number. 2–30 characters. Examples: US EIN '12-3456789', UK Companies House '12345678'.
type: "individual" Only
field
type
required
description
date_of_birth
String
Required
Format YYYY-MM-DD (strict regex — no other formats accepted).
country_of_birth
String
Required
ISO 3166-1 alpha-2 of the sender's country of birth.
Variant mismatch

A type: "individual" sender with a registration_number has that field silently dropped. A type: "business" sender missing registration_number fails validation outright. Always match required fields to the declared variant.


Country-Specific Required Fields

A handful of destinations add extra required fields on top of the 12 core SWIFT fields. GET /api/payouts/supported-countries/:country is always the source of truth — these are the notable quirks:

country
extra required field
format / notes
AU (Australia)
bsb_number
6-digit Bank State Branch code, regex ^\d{6}$. The corridor placeholder shows '062-000' but the regex does not allow dashes — strip them before sending.
IN (India)
IFSCode
11-char IFSC code, regex ^[A-Z]{4}0[A-Z0-9]{6}$. The key is literally camelCase 'IFSCode' — unlike every other snake_case field in the payload. Sending 'ifs_code' or 'ifsc_code' silently fails as 'missing required field'.
HK (Hong Kong)
swift_code (different regex)
Regex is ^[A-Za-z]{4}HK[A-Za-z0-9]{2}([A-Za-z0-9]{3})?$ — case-insensitive and pins the country bits to literal 'HK'. All other SWIFT-supporting countries use the global 8/11-char BIC regex.
RW (Rwanda), SG (Singapore)
beneficiary.type
One of 'business' or 'individual'. Required only for these two countries on the nested beneficiary object.

remittance_purpose Enum

Lowercase snake_case values. The server uppercases them (family_supportFAMILY_SUPPORT) when forwarding to SWIFT.

remittance_purpose accepted values

Step 3 — Finalize

No request body. Just the URL. Finalize settles the payout and returns the final Payout record.

Finalize Payout
Finalize is bodyless

Any body you send is ignored. Finalize uses the state set during initialize.


Full Example — GB Destination, Business Sender

Step 1 — Create Quote
POST /api/payouts/quotes

Response → data.quote_id = "qte_01HY2Q..."

Step 2 — Initialize with SWIFT beneficiary
POST /api/payouts/qte_01HY2Q.../initialize
Step 3 — Finalize
Finalize

Full Example — DE Destination (EUR), Individual Sender

Step 1 — Create Quote
POST /api/payouts/quotes
Step 2 — Initialize
POST /api/payouts/:quoteId/initialize
Step 3 — Finalize
Finalize

Discovering SWIFT Support for a Country

Before building the payload, fetch the corridor config for the destination country:

Corridor lookup

Inspect the corridors[] array for entries whose destination_types includes "swift":

Partial response (GB, currency-filtered)

The returned destination_types["swift"] block carries the exact field schema — it is the authoritative source for that country's requirements, including any per-country extras listed in the Country-Specific Extra Fields section above.


Validation Failures

http
error code
cause
400
INVALID_BODY
Request body isn't valid JSON or doesn't match the expected shape at the HTTP parser.
400
INVALID_BENEFICIARY_DATA
`country` missing from beneficiary, OR a required SWIFT field is missing / violates its regex / fails min-max length. The error message lists each failing field.
422
UNSUPPORTED_CORRIDOR
The (country, destination_type) pair has no schema — e.g. SWIFT on a country that doesn't support it.
422
AMOUNT_OUTSIDE_LIMITS
Quote amount is below or above the corridor's min/max limits.
422
INSUFFICIENT_BALANCE
Company balance can't cover the payout (applies when source = 'offchain').
410
QUOTE_EXPIRED
Quote TTL elapsed before you called initialize or finalize. Fetch a fresh quote and start over.

Common Pitfalls

Putting beneficiary on the quote. It doesn't go there. The quote body has no beneficiary, no destination_type. Both live on initialize.

Casing on enums. Our API is lowercase snake_case for destination_type, remittance_purpose, sender.type. Uppercase is the downstream form — the adapter does the transform. Send swift / family_support / business.

Casing on SWIFT/BIC codes. Must be uppercase — DEUTDEFF, not deutdeff. Length is exactly 8 or 11 characters.

Three separate address blocks. bank_* = destination bank branch. Nested beneficiary.* = recipient's physical address. sender.* = payer's address. All three are independent — don't conflate them.

Finalize body. There is none. Sending a body is silently ignored.

country appears twice. Once at the top of beneficiary (lookup key for the corridor schema), and once nested inside beneficiary.country (recipient's country — often the same value).

Sender variant mismatch. type: "individual" with a registration_number — the field is silently ignored. type: "business" without registration_number — validation fails.

Name format. account_name (and sender.account_name) must have ≥2 space-separated parts, each ≥2 chars. No Mr/Mrs/Dr. No single-letter-plus-dot. J. Doe is rejected; John Doe passes.

IFSCode is the one camelCase field. Every other SWIFT field is snake_case; India's IFSC code field is literally IFSCode. Sending ifs_code or ifsc_code silently fails validation as "missing required field".

AU BSB number has no dashes. The placeholder shows 062-000, but the regex ^\d{6}$ rejects the dash. Submit as 062000.

API callers must supply sender. Dashboard users get it auto-injected from the authenticated company profile; direct API integrations do not.


Share on
Share on FacebookShare on XShare on LinkedIn
Did you find this page useful?