> ## Documentation Index
> Fetch the complete documentation index at: https://docs.infinityapp.in/llms.txt
> Use this file to discover all available pages before exploring further.

# Payee addresses and bank requirements

> Submit a payee's bank account through the API, validate it against each rail's rules, and understand who is liable for the details.

A **payee address** is the bank account a payee is paid into. Submitting it through the API makes the payee `active` immediately, so onboarding happens entirely inside your product and the payee never sees an Infinity page.

## How it works

When you add an address, Infinity validates every field against the rules for its currency and rail, then registers the account with the payout network. If both steps succeed, the address is stored with `status: active` and the payee becomes `active`. If the network rejects the account, nothing is stored, the payee is unchanged, and the request fails with `400 bank_details_invalid`.

* Addresses are available to accounts paying in USD, EUR and GBP. INR payees add their bank details through hosted onboarding.
* A payee has one address in v1.
* The address's currency sets the payee's `currency` if it wasn't set already; if it was, the two must match.

## Rails and required fields

| Currency | `rail` | `account_number` | `routing_code` | `beneficiary_address` |
| - | - | - | - | - |
| `usd` | `ach` or `wire` | Account number | 9-digit ABA routing number (required) | `line1`, `city`, `state`, `postal_code`, `country` |
| `eur` | `sepa` | IBAN | BIC, 8 or 11 characters (optional) | `line1`, `city`, `country` |
| `gbp` | `faster_payments` | 8-digit account number | 6-digit sort code (required) | `line1`, `city`, `country` |

For USD, the rail is your choice and applies to every payout to that address. ACH is the lower-cost rail; wire settles faster.

## Bank requirements

`GET /bank-requirements` returns the same rules the validator applies, field by field, so a form built from it never drifts from the API:

```bash theme={null}
curl "$BASE/bank-requirements?currency=gbp" -H "Authorization: Bearer $INFINITY_KEY"
```

```json Response (abridged) theme={null}
{
  "data": [
    {
      "currency": "gbp",
      "rail": "faster_payments",
      "fields": [
        { "name": "account_number", "required": true, "description": "The 8-digit account number.", "pattern": "^[0-9]{8}$", "max_length": null, "allowed_values": null, "example": "31926819" },
        { "name": "routing_code", "required": true, "description": "The 6-digit sort code.", "pattern": "^[0-9]{6}$", "max_length": null, "allowed_values": null, "example": "200000" },
        { "name": "beneficiary_name", "required": true, "description": "The account holder's name.", "pattern": null, "max_length": 35, "allowed_values": null, "example": "Oliver Smith" },
        { "name": "beneficiary_address.postal_code", "required": false, "description": "The postal code.", "pattern": null, "max_length": null, "allowed_values": null, "example": "SW1A 1AA" }
      ]
    }
  ],
  "has_more": false
}
```

Omit `currency` to get every rail. Nested fields use dotted names (`beneficiary_address.state`). `usd` returns two entries, one for `ach` and one for `wire`, with identical fields.

## Add an address

```bash EUR · SEPA theme={null}
curl "$BASE/payees/payee_c8pnahcrxqzd3z8d/addresses" \
  -H "Authorization: Bearer $INFINITY_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "bank_account",
    "currency": "eur",
    "rail": "sepa",
    "owner_type": "individual",
    "beneficiary_name": "Maria Lopez",
    "bank_name": "ABN AMRO",
    "account_number": "NL91ABNA0417164300",
    "beneficiary_address": { "line1": "Damrak 1", "city": "Amsterdam", "postal_code": "1012", "country": "NL" }
  }'
```

```bash USD · ACH theme={null}
curl "$BASE/payees/payee_x3k7r9mwq2dn8hat/addresses" \
  -H "Authorization: Bearer $INFINITY_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "bank_account",
    "currency": "usd",
    "rail": "ach",
    "owner_type": "business",
    "beneficiary_name": "Northwind Studio LLC",
    "bank_name": "Chase",
    "account_number": "000123456789",
    "routing_code": "021000021",
    "account_type": "checking",
    "beneficiary_address": { "line1": "350 5th Ave", "city": "New York", "state": "NY", "postal_code": "10118", "country": "US" }
  }'
```

```bash GBP · Faster Payments theme={null}
curl "$BASE/payees/payee_x3k7r9mwq2dn8hat/addresses" \
  -H "Authorization: Bearer $INFINITY_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "bank_account",
    "currency": "gbp",
    "rail": "faster_payments",
    "owner_type": "individual",
    "beneficiary_name": "Oliver Smith",
    "bank_name": "Barclays",
    "account_number": "31926819",
    "routing_code": "200000",
    "beneficiary_address": { "line1": "10 Downing St", "city": "London", "country": "GB" }
  }'
```

```json Response theme={null}
{
  "id": "address_7m3kq9xwd2hr5tna",
  "payee_id": "payee_c8pnahcrxqzd3z8d",
  "type": "bank_account",
  "currency": "eur",
  "rail": "sepa",
  "owner_type": "individual",
  "beneficiary_name": "Maria Lopez",
  "bank_name": "ABN AMRO",
  "account_number_last4": "4300",
  "routing_code": null,
  "account_type": null,
  "beneficiary_address": { "line1": "Damrak 1", "city": "Amsterdam", "state": null, "postal_code": "1012", "country": "NL" },
  "status": "active",
  "created_at": "2026-10-26T10:01:00Z"
}
```

The full account number is never returned after creation; reads expose `account_number_last4` only.

## Field reference

| Field | Rules |
| - | - |
| `type` | `bank_account`. |
| `currency` | `usd`, `eur` or `gbp`. Must equal the payee's `currency` if it's already set. |
| `rail` | As in the table above. |
| `owner_type` | `individual` or `business`. For `business`, `beneficiary_name` is also sent to the bank as the company name. |
| `beneficiary_name` | The account holder's legal name, up to 35 characters (the limit most clearing systems enforce). |
| `bank_name` | Required, up to 100 characters. |
| `account_number` | For `sepa`, an IBAN; spaces are removed and letters uppercased before validation. For `faster_payments`, 8 digits; separators are removed. |
| `routing_code` | See the rails table. |
| `account_type` | `checking` or `savings`, on `ach` and `wire` only. |
| `beneficiary_address.line1` | Street and building number, up to 35 characters. It must contain a building number. |
| `beneficiary_address.state` | On `ach` and `wire`: an ISO 3166-2 subdivision code, such as `CA`. |
| `beneficiary_address.country` | ISO 3166-1 alpha-2, uppercase. |

## Changing a payee's bank account

A second address for the same payee fails with `409 address_exists`, and addresses can't be updated or replaced through the API in v1.

If a payee changes bank, or their bank rejects a payout to the stored account, contact your Infinity team with the payee's ID.

## Liability for bank details

You're responsible for the accuracy of the bank details you submit. Infinity validates the format and the payout network checks the account when it's registered, but some errors can't be detected before funds move: a valid account that belongs to someone else, for example, or a name that doesn't match the account. Payouts to such accounts end as `failed` or `returned` with `failure_code: returned_by_bank`, and a payout credited to a valid account belonging to the wrong person can't be recalled.

## Errors

| HTTP | `code` | Cause |
| - | - | - |
| 400 | `bank_details_invalid` | A field breaks a rail rule (`param` names it), or the network rejected the account (`param: null`). |
| 400 | `invalid_payee_request` | `currency` doesn't match the payee's currency. |
| 400 | `kyc_required` | The payee is an INR payee and must use hosted onboarding. |
| 404 | `payee_not_found` | No payee with that ID in your account. |
| 409 | `address_exists` | The payee already has an address. |

## In the sandbox

An account number ending in `0000` passes format validation and is then rejected as if by the bank. See [Sandbox](https://docs.infinityapp.in/guides/sandbox.md#simulating-a-rejected-bank-account).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.