Bank Accounts
Add a bank account to a receiver for fiat payouts, with the fields the server checks per payment rail, Brazil PIX, errors and list behaviour
A bank account belongs to a receiver and is where a fiat payout lands.
Before you start
- The receiver exists and has
email,addressandcountryIsoCodeset. - You have the Skyline ids of the account's currency and of the bank's country. Get them from
GET /currencies?limit=250andGET /countries?limit=250. See Setup. - The user behind your API key is an active member of the organisation and is not view-only.
How the server decides which fields are required
Skyline pays out over payment rails (for example SEPA, Faster Payments, ACH or SWIFT). Each rail needs its own bank fields. When you create an account, the server:
- finds the rails enabled for the currency and bank country;
- leaves out SWIFT rails if you did not send
bicSwift; - checks every field that each remaining rail requires, and rejects the request at the first one that is missing or invalid.
The rails and their fields are configuration and can change, so read them before you build the request.
Get the rails and their fields
GET /payment-rails/available-rails?countryId=<country _id>¤cyId=<currency _id>
Send both ids (the same _id values you will send as bankCountry and currency). The response lists the rails enabled for that pair, each with the fields it needs:
[
{
"_id": "…",
"name": "SEPA",
"display": "SEPA",
"rail": "SEPA",
"requiredFields": [
{ "fieldName": "iban", "required": true },
{ "fieldName": "receiver.address.addressLine1", "required": true }
]
}
]- A field is needed if any listed rail requires it. Fields named
receiver.…are read from the receiver (see Receiver address). - An empty array means the pair cannot be paid out:
POST /bank-accountswould fail with 400No payment rails available. GET /payment-rails/required-fieldsreturns every rail's field list without the country and currency filter. Use it as a catalogue only.
If the server still names a missing field, add it and retry.
Create a bank account
POST /bank-accounts
Always required
| Field | Notes |
|---|---|
receiver | The receiver's _id |
currency | Currency _id from GET /currencies |
bankCountry | Country _id from GET /countries |
Rail fields
The server checks these fields against the rules below when a rail uses them. The IBAN checksum is checked whenever you send an IBAN.
| Field | Rule |
|---|---|
iban | Valid IBAN checksum |
accountNumber | 4 to 17 characters |
bicSwift | Valid BIC. Needed for SWIFT rails |
sortCode | 6 digits, no dashes. UK accounts are also checked against the account number |
routingNumber | 9 digits (ABA) |
ifscCode | Valid Indian IFSC |
Where a rail accepts either an IBAN or an account number, one of them is enough.
Optional bank details
bankName, bankCode, branchName, branchCode, bankAddress, bankAddress2, bankCity, bankState, bankZip, channel, intermediaryBankName, intermediaryRoutingCode. All are strings.
Receiver address
Some rails require the receiver's address (addressLine1, city, postCode). The server reads it from the receiver, not from the bank account request. Do not put address fields in this request: unknown fields return 400. If the receiver's address is incomplete, update the receiver first.
US dollar accounts in the United States
For a USD account with a US bank, choose the rails with two booleans:
| Field | Meaning |
|---|---|
achSupport | The account can receive ACH |
fedSupport | The account can receive Fedwire |
accountType | CHECKING or SAVINGS. Kept only when achSupport is true |
The response shows your choice as wireSupport: { "ach": "YES" | "NO", "fed": "YES" | "NO" }.
Example
{
"receiver": "665f1c2e9b1e8a0012a3b4c5",
"currency": "6150b94616b409003977df6d",
"bankCountry": "6150b94616b409003977df70",
"iban": "DE89370400440532013000",
"bicSwift": "COBADEFFXXX",
"bankName": "Commerzbank"
}The response is the bank account, with receiver expanded and paymentRails listing the rails the account can be paid on. Keep its _id for transactions.
Brazil (BRL)
BRL payouts use PIX. TED is currently unavailable. Do not create TED accounts.
The receiver needs valid Brazilian identity details:
| Receiver type | Needs |
|---|---|
INDIVIDUAL | taxId (CPF), nationality (ISO alpha-2), dateOfBirth |
COMPANY | taxId (CNPJ) |
Set address.state (the UF, for example SP) on Brazilian receivers as well.
You can send taxId, nationality and dateOfBirth in the bank account request. The server copies them onto the receiver only where the receiver's value is missing or invalid. If the request then fails, the receiver is left unchanged.
To fill the bank details, look the bank up with GET /brazilian-banks?search=<name or code>&limit=20. Each result has bankName, bankCode (COMPE), bicSwift (or null), ispb and bicRequired. Send bankName, bankCode and bicSwift from the result. When bicRequired is true the bank has no known BIC: send one you got from the account holder.
PIX fields:
| Field | Rule |
|---|---|
brazilRail | PIX |
pixKeyType | EMAIL, PHONE, CPF, CNPJ or EVP. CPF only for an individual, CNPJ only for a company |
pixKey | Required. Up to 50 characters, and valid for its type (see below) |
bankName, bankCode, bicSwift | The bank's name, its three-digit COMPE code and, if it has one, its BIC |
pixKeyType | Valid pixKey |
|---|---|
EMAIL | An email address |
PHONE | A Brazilian phone number. Stored in E.164, for example +5511999998888 |
CPF | An 11-digit CPF with valid check digits. Stored as digits only |
CNPJ | A 14-digit CNPJ with valid check digits. Stored as digits only |
EVP | A random key (UUID v4) |
{
"receiver": "665f1c2e9b1e8a0012a3b4c5",
"currency": "6150b94616b409003977df71",
"bankCountry": "6150b94616b409003977df72",
"brazilRail": "PIX",
"pixKeyType": "EMAIL",
"pixKey": "maria@example.com",
"bankName": "Banco do Brasil",
"bankCode": "001",
"taxId": "52998224725",
"nationality": "BR",
"dateOfBirth": "1990-01-01"
}If identity details are missing, the server returns 400 with the fields to fix:
{
"message": "This beneficiary is missing valid Brazil identity details required for a BRL bank account: taxId, nationality",
"error": "IncompleteBrlReceiver",
"invalidFields": ["taxId", "nationality"]
}Errors
| Status | Message | Fix |
|---|---|---|
| 400 | Receiver not found | The receiver is not in your organisation |
| 403 | View-only members cannot modify beneficiaries | Use a user who is not view-only |
| 400 | Currency not found / Bank country not found | Use _id values from the lookups, not ISO codes |
| 400 | In order to associate a bank account to a receiver, the receiver should have all details filled. | Set the receiver's country, address and email |
| 400 | IncompleteBrlReceiver (see above) | Complete the receiver's Brazilian identity details |
| 400 | No payment rails available | This currency and country cannot be paid out |
| 400 | The provided IBAN is not valid — check it for a mistyped character | Fix the IBAN |
| 400 | Bank account iban not provided, Bank account number not provided, Bank account bic/swift not provided, Please provide the Sort Code, Please provide the Routing Number, Please provide a valid IFSC Code | Add the named field |
| 400 | Account number must be between 4 and 17 characters, Please provide a valid Sort Code, Please provide a valid Routing Number | Fix the format |
| 400 | Bank account is not valid | The UK sort code and account number do not match |
| 400 | Address Line 1 not provided, City not provided, Post Code not provided | Complete the receiver's address |
Read, list, update and remove
- Read one receiver's accounts from
GET /receivers/{id}(itsbankAccountsarray). This is the reliable view: it covers every account on the receiver and leaves out removed ones. GET /bank-accounts/{id}returns one account.GET /bank-accounts/metakes onlylimit,offsetandsearchTerm. Filters such asreceiver,currencyorbankCountryreturn 400. It lists only accounts on receivers created by the same user, and it includes removed accounts, markedsoftDeleted: true.PATCH /bank-accounts/{id}changes an account. The same membership rules apply, and it is limited to 20 calls per hour per user.DELETE /bank-accounts/{id}removes the account and returnstrue. Transactions that already reference it are not affected. The same membership rules apply.
What's next
Add a wallet if the transaction has a crypto leg, then create a transaction.