Skip to content
Seismic Orchestration

GET /accounts/fiat/external/requirements

The fields Seismic requires to register an external fiat account (payout destination) for a given currency, bank country, account holder type, and optional settlement rail. Fetch it before rendering an account form, then submit POST /customers/:id/accounts/fiat/external using the returned field requirements alongside the create request’s top-level fields (currency, rails, details, and account_holder.type). Every field is a dotted path into that create request's body.

Use this endpoint as the source of truth for the selected corridor and rail. It includes the create endpoint’s required holder identity: account_holder.first_name and account_holder.last_name for individuals, or account_holder.business_name for businesses, plus account_holder.address.country for both. Send these values even when the customer’s verified profile already contains them.

Production requirements are resolved live per corridor. Sandbox uses the same create validation and a checked-in requirements catalog; it does not fetch production requirements live. A successful requirements response describes account registration, not availability of every quote pair. A field's validation metadata (regex, max_length, options) is best-effort and worth enforcing client-side when present.

For invoices and other supporting documents required to accept a payment, read the selected quote's acceptance_requirements.files_required. See Quote acceptance requirements for the response field and when to collect the upload.

For USD, rail distinguishes domestic from SWIFT registration. rail=ach or rail=wire at a US bank selects the us shape and requires details.routing_number. rail=swift selects the swift shape, including at a US bank: details.bic is required and the correspondent details.routing_number is optional unless the live corridor recipe specifically requires it. A USD account at a non-US bank is always the swift shape. Omit rail only when you need the conservative union across eligible rails.

No authentication required. The response reflects the corridor's default payout configuration. Account creation resolves the recipe again for that customer and can require additional fields when its payout configuration differs from the default.

Query parameters

ParameterTypeNotes
currencystringFiat currency code of the destination account (USD, EUR, …).
bank_countrystringISO-3166-1 alpha-2 country of the destination bank (US, GB, …).
account_holder_type"individual" | "business"Who owns the destination account. Requirements differ: individuals need name fields, businesses a legal name.
railstringOptional intended settlement rail. Use swift to get SWIFT requirements for a USD account at a US bank; omit for the conservative union.

Response 200

FieldTypeNotes
currencystringEcho of the query, normalized to uppercase.
bank_countrystringEcho of the query, normalized to uppercase.
account_holder_type"individual" | "business"Echo of the query.
fieldsarrayOne entry per create-request field, details.* first, then account_holder.*.

Each entry of fields:

FieldTypeNotes
fieldstringDotted path into the create-request body, e.g. details.account_number, account_holder.address.city.
requirement"required" | "optional"Required fields must be present on the create call. Optional ones are accepted but not needed.
required_for_railsstring[]?Rails that escalate this field to required. Present only on optional fields: e.g. a wire-only identifier is optional for a corridor also reachable by another rail, but required once the account settles over that rail. Use it to treat an optional field as required when the partner targets one of these rails. A required field is needed regardless of rail and never carries this list.
accepted_for_railsstring[]?Rails that accept this field. Present only when some of the corridor's rails do not: see requirements without a rail.
required_whenarray?Conditions on other fields of the same create request, any one of which makes this field required. Present only on optional fields: e.g. details.phone with [{ "field": "account_holder.address.country", "in": ["BR", "MX"] }] is required when the holder's address is in Brazil or Mexico. Each entry has field (a dotted request path) and in (the values that trigger it; countries are ISO 3166-1 alpha-2).
labelstring?Human-readable name, suitable as a form label.
regexstring?Pattern the value must match.
max_lengthnumber?Maximum accepted length.
examplestring?A valid sample value.
optionsarray?Allowed values when the field is enumerated: render a picker instead of a free-form input. Each entry has value and an optional label.

A field can also appear here ahead of being enforced. Where a corridor is about to start asking for a field, it is published as optional first so you can add it to your integration, and a later release moves it to required. Sending such a field early is always safe — it is accepted the whole time — so treat a newly appearing optional field as the notice that it is coming, and watch the changelog for the release that requires it.

Some fields stay optional here even where account create requires them, because this endpoint doesn't know the customer: see route-specific bank details.

Requirements without a rail

Without rail, a corridor whose rails take different bank details (BRL: pix and ted) returns the union of every rail's fields. In that union a field that only some rails need is optional with required_for_rails, and a field that only some rails accept carries accepted_for_rails. Leave a field that carries accepted_for_rails out of the create request unless the rail you settle over is listed there; otherwise the request is rejected. Pass rail to get the recipe for one rail instead.

Excerpt of the BRL response without rail (other fields omitted):

{
  "currency": "BRL",
  "bank_country": "BR",
  "account_holder_type": "individual",
  "fields": [
    {
      "field": "details.bank_address",
      "requirement": "required"
    },
    {
      "field": "details.phone",
      "requirement": "optional",
      "accepted_for_rails": [
        "ted"
      ]
    },
    {
      "field": "details.pix_key",
      "requirement": "optional",
      "required_for_rails": [
        "pix"
      ],
      "accepted_for_rails": [
        "pix"
      ]
    }
  ]
}

Recipient relationship

For ACH, domestic wire (wire, including Fedwire), and SWIFT, send the recipient's relationship to the customer in account_holder.relationship when creating the external account. For a vendor's account, send "VEND" and set account_holder.is_third_party to true.

Render a dropdown from the options on the account_holder.relationship entry returned for your selected currency, bank country, holder type, and rail. The holder type is the destination account owner's type. Individual and business holders have different option sets. The field is published as optional, but send it on every third-party account (is_third_party: true): without it the account can be registered for fewer settlement options, and one that has no other option is created but not registered for settlement until the field is added. See holder relationship and industry.

details.relationship_to_debtor is a separate bank-details field accepted only on the sg_fast (SGD), in_ifsc (INR), and ph_bank (PHP) shapes. It does not populate account_holder.relationship and is not accepted in USD bank details. If the response lists both fields, follow each field's own requirements and options.

Field catalog

Every field value comes from the fixed catalog below. The endpoint never returns a path outside it. Which paths a corridor uses, and whether each is required or optional, is still resolved live. The catalog is the full universe, not the per-corridor answer.

The TypeScript client ships the catalog as constants: EXTERNAL_FIAT_DETAILS_FIELDS (per shape) and EXTERNAL_FIAT_HOLDER_FIELDS, with the path union typed as ExternalFiatFieldPath.

details.bank_address is the block as a whole and is always required. Which of its parts a corridor needs is listed on the part paths: details.bank_address.country on every shape (it decides the shape: USD at a bank outside the US is swift), and on swift the street address too, which some routes file with the account.

details.* paths, by the shape the currency infers to:

  • us (USD, US bank over ACH / domestic wire)
    • details.account_type
    • details.phone
    • details.tax_number
    • details.id_type
    • details.id_number
    • details.registration_type
    • details.registration_number
    • details.account_number
    • details.routing_number
    • details.bic
    • details.bank_name
    • details.bank_address
    • details.bank_address.country
  • swift (USD over SWIFT, including US banks)
    • details.bic
    • details.account_number
    • details.phone
    • details.tax_number
    • details.swift_payment_code: purpose-of-payment code, with the values the bank's country accepts as options
    • details.ifsc: the branch IFSC, for a bank in India
    • details.bank_name
    • details.routing_number: deprecated spelling of details.intermediary_bank.routing_number, listed for individual account holders while it is still accepted
    • details.intermediary_bank: the recipient bank's US correspondent (intermediary) bank — its name, its own BIC, the destination bank's account at it, and its country
    • details.intermediary_bank.routing_number: ABA routing number of that correspondent. Required for individual account holders from 2026-11-01
    • details.bank_address
    • details.bank_address.country
    • details.bank_address.line1
    • details.bank_address.line2
    • details.bank_address.city
    • details.bank_address.state
    • details.bank_address.postal_code
  • uk (GBP)
    • details.sort_code
    • details.account_number
    • details.iban
    • details.bank_name
    • details.bank_address
    • details.bank_address.country
  • iban (EUR, CHF, NOK, SEK, DKK, AED)
    • details.account_number
    • details.bic
    • details.bank_code
    • details.phone
    • details.id_number: individuals only
    • details.id_type: individuals only
    • details.registration_number: businesses only
    • details.registration_type: businesses only
    • details.bank_name
    • details.bank_address
    • details.bank_address.country
  • cn_cnaps (CNY)
    • details.account_number
    • details.cnaps_code
    • details.id_number
    • details.id_type: individuals only
    • details.registration_number: businesses only
    • details.registration_type: businesses only
    • details.bank_name
    • details.branch_name: businesses only
    • details.bank_address
    • details.bank_address.country
  • hk_fps (HKD)
    • details.account_number
    • details.bank_name
    • details.bic
    • details.registration_number: businesses only
    • details.registration_type: businesses only
    • details.date_of_incorporation: businesses only
    • details.bank_address
    • details.bank_address.country
  • sg_fast (SGD)
    • details.account_number
    • details.bank_name
    • details.phone
    • details.id_number: individuals only
    • details.id_type: individuals only
    • details.registration_number: businesses only
    • details.registration_type: businesses only
    • details.relationship_to_debtor
    • details.bank_address
    • details.bank_address.country
  • br_pix (BRL, PIX)
    • details.pix_key
    • details.pix_key_type
    • details.bank_address
    • details.bank_address.country
  • br_bank (BRL, TED)
    • details.bank_code
    • details.agency
    • details.account_number
    • details.account_subtype
    • details.tax_number
    • details.phone
    • details.id_number: individuals only
    • details.id_type: individuals only
    • details.registration_number: businesses only
    • details.registration_type: businesses only
    • details.bank_name
    • details.bank_address
    • details.bank_address.country
  • mx_clabe (MXN)
    • details.clabe
    • details.tax_number
    • details.bank_name
    • details.bank_address
    • details.bank_address.country
  • in_ifsc (INR)
    • details.ifsc
    • details.account_number
    • details.phone
    • details.id_number: individuals only
    • details.id_type: individuals only
    • details.registration_number: businesses only
    • details.registration_type: businesses only
    • details.relationship_to_debtor
    • details.bank_name
    • details.bank_address
    • details.bank_address.country
  • ar_cbu (ARS)
    • details.cbu
    • details.alias
    • details.tax_number
    • details.phone
    • details.id_number: individuals only
    • details.id_type: individuals only
    • details.registration_number: businesses only
    • details.registration_type: businesses only
    • details.bank_name
    • details.bank_address
    • details.bank_address.country
  • ph_bank (PHP)
    • details.account_number
    • details.bank_name
    • details.phone
    • details.registration_number: businesses only
    • details.registration_type: businesses only
    • details.date_of_incorporation: businesses only
    • details.relationship_to_debtor
    • details.bank_address
    • details.bank_address.country
  • thb_bank (THB, PromptPay)
    • details.account_number
    • details.bank_name
    • details.bank_address
    • details.bank_address.country
  • idr_bank (IDR, BI-FAST / Artajasa)
    • details.account_number
    • details.bank_name
    • details.bank_address
    • details.bank_address.country
  • jp_zengin (JPY, Zengin)
    • details.bank_code: required, 4 digits
    • details.branch_code: required, 3 digits
    • details.account_number: required, 7 digits
    • details.bank_name: required
    • details.phone: required
    • details.bank_address: required
    • details.bank_address.country: required
    • account_holder.address.line1: required
  • ca_eft (CAD, EFT)
    • details.institution_number
    • details.transit_number
    • details.account_number
    • details.bank_address
    • details.bank_address.country
  • pk_iban (PKR, Raast)
    • details.iban
    • details.bank_name
    • details.bank_address
    • details.bank_address.country
  • ng_bank (NGN, NIP)
    • details.account_number
    • details.bank_code
    • details.bank_name
    • details.bank_address
    • details.bank_address.country
  • au_bsb (AUD, BECS)
    • details.bsb
    • details.account_number
    • details.bank_address
    • details.bank_address.country
  • co_bank (COP, ACH Colombia; account_holder_type=individual only)
    • details.bank_code
    • details.account_number
    • details.account_type
    • details.id_type
    • details.id_number
    • details.bank_address
    • details.bank_address.country

account_holder.* paths are shared by every shape:

  • account_holder.first_name
  • account_holder.last_name
  • account_holder.business_name
  • account_holder.address.country
  • account_holder.email
  • account_holder.date_of_birth
  • account_holder.address.line1
  • account_holder.address.line2
  • account_holder.address.city
  • account_holder.address.state
  • account_holder.address.postal_code
  • account_holder.is_third_party
  • account_holder.relationship
  • account_holder.industry

Name fields are required according to the holder type, and address.country is always required. is_third_party, relationship and industry are optional on every corridor; the other fields depend on the corridor.

account_holder.is_third_party is optional — omitting it registers an account the customer owns — but set it to true when the account belongs to someone else, because some payment setups verify the holder's name against the customer's own and only skip that check for a third party.

account_holder.relationship says who the holder is to the customer, and is also optional. Send it on every third-party account: a payment setup that asks the question cannot otherwise tell an employee from a supplier, and without it the account can be registered for fewer settlement options. For an account the customer owns, is_third_party: false is the answer.

account_holder.industry is the six-digit NAICS code of the holder business's industry, from GET /v0/industries/account-holder. It is listed only when account_holder_type is business. On a first-party account it falls back to the industry on the customer's KYB profile. Send it for a third-party business: some payment setups file a business account under its owner's industry, and without one the account can be registered for fewer settlement options. A code that GET /v0/industries/account-holder doesn't list is rejected.

details.relationship_to_debtor, listed above for sg_fast, in_ifsc and ph_bank, is separate from account_holder.relationship. Setting one does not set the other, and their accepted option sets can differ. See recipient relationship.

The accepted codes come back in the field's own options, each with a label, and the set depends on account_holder_type — individuals are offered family and personal relationships alongside the commercial ones, businesses only the commercial ones. Read options; it is authoritative, and the sets can widen without a release here. A code outside the set for the requested holder type is rejected, and the refusal names the ones that would have been accepted.

Two corridor rules are worth calling out because they aren't obvious from the field names:

  • account_holder.address.postal_code is required on all EUR and GBP external accounts.
  • On the swift shape, details.intermediary_bank.routing_number carries the ABA routing number of the recipient bank's US correspondent bank, not the recipient bank's own code. From 2026-11-01 it is required when account_holder_type is individual; it stays optional for a business. The rest of the correspondent goes in the same block (name, bic, account_number, country) — quote its own BIC there when the correspondent is outside the US and so has no ABA. The top-level details.routing_number is a deprecated spelling of the same nine digits: it is still accepted, and supplying both with different values is rejected.

Example

Excerpt of the response to the rail=swift query shown below, from 2026-11-01 (before then details.intermediary_bank.routing_number reads optional); other required and optional fields are omitted for brevity:

{
  "currency": "USD",
  "bank_country": "US",
  "account_holder_type": "individual",
  "fields": [
    {
      "field": "details.account_number",
      "requirement": "required",
      "label": "Account number",
      "regex": "^[0-9]{4,21}$",
      "max_length": 21,
      "example": "26207729"
    },
    {
      "field": "details.bic",
      "requirement": "required",
      "label": "BIC / SWIFT Code",
      "regex": "^[A-Z0-9]{8}([A-Z0-9]{3})?$",
      "example": "CHASUS33"
    },
    {
      "field": "details.bank_address",
      "requirement": "required"
    },
    {
      "field": "details.intermediary_bank.routing_number",
      "requirement": "required",
      "label": "Correspondent ABA Routing Number",
      "regex": "^[0-9]{9}$",
      "max_length": 9,
      "example": "121000248"
    },
    {
      "field": "account_holder.first_name",
      "requirement": "required"
    },
    {
      "field": "account_holder.last_name",
      "requirement": "required"
    },
    {
      "field": "account_holder.address.country",
      "requirement": "required"
    },
    {
      "field": "account_holder.address.city",
      "requirement": "required",
      "label": "City",
      "max_length": 150
    }
  ]
}

On corridors that hold details.bank_name to a published bank list (SGD, CAD), the field carries options: the same catalog GET /banks serves for the create path. HKD used to route this way; it now routes off details.bic and accepts any bank name.

Unique keys

Seismic registers one external account per destination. When a create call repeats the identifying fields of one of the customer's still-active accounts in the same currency, it returns a 400 naming the existing account. Those identifying fields are the account's unique key, and they depend on the shape the corridor infers to:

This table lists a subset of account formats. For all countries and rails supported, see Local rails.

ShapeCurrenciesUnique key
usUSD over ACH / domestic wiredetails.account_number + details.routing_number
swiftUSD over SWIFTdetails.bic + details.account_number
ukGBPdetails.account_number + details.sort_code
ibanEUR, CHF, NOK, SEK, DKK, AEDdetails.account_number (the IBAN)
cn_cnapsCNYdetails.account_number + details.cnaps_code
hk_fpsHKDdetails.account_number + details.bic
sg_fastSGDdetails.account_number + details.bank_name
br_pixBRL (PIX)details.pix_key
br_bankBRL (TED)details.bank_code + details.agency + details.account_number
mx_clabeMXNdetails.clabe
in_ifscINRdetails.ifsc + details.account_number
ar_cbuARSdetails.cbu
ph_bankPHPdetails.account_number + details.bank_name
thb_bankTHB (PromptPay)details.account_number + details.bank_name
idr_bankIDR (BI-FAST / Artajasa)details.account_number + details.bank_name
ca_eftCAD (EFT)details.institution_number + details.transit_number + details.account_number + details.bank_name
jp_zenginJPY (Zengin)details.bank_code + details.branch_code + details.account_number
pk_ibanPKR (Raast)details.iban
ng_bankNGN (NIP)details.account_number + details.bank_code
au_bsbAUD (BECS)details.bsb + details.account_number
co_bankCOP (ACH Colombia)details.bank_code + details.account_number

IBANs and bank names compare case-insensitively. Numeric identifiers (account, routing, sort, CNAPS) must match exactly. Every other field (bank_address, bic on a routing-numbered account, optional bank names on numeric-routed corridors, the whole account_holder block) is display-only: changing it does not make the destination a new account. To re-register a destination (say, with a corrected holder), DELETE /accounts/:id the existing account first, then create it again with the corrected values — the correction is what makes it a new account rather than a restore of the deleted one.

The TypeScript client ships this table as the EXTERNAL_FIAT_UNIQUE_KEYS constant, keyed by shape.

Errors

  • 400: bank_country isn't a two-letter country code, or account_holder_type isn't individual / business.
  • 422 CorridorUnsupported: an external fiat account can't be created for this currency, bank country, and rail.
  • 503: requirements couldn't be fetched right now. Retry with backoff.

Example

No API key needed:

curl "$SEISMIC_ORCHESTRATION_URL/v0/accounts/fiat/external/requirements?currency=USD&bank_country=US&account_holder_type=individual&rail=swift"