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

# Bank Accounts: Link and Verify Your Funding Sources

> Learn how Cleo Pay bank accounts work, including manual linking, micro-deposit verification, and the verification lifecycle states.

Bank accounts in Cleo Pay represent your business's funding sources for outbound ACH payments. Before you can send a payment, you must link at least one bank account and verify that you own it. Cleo Pay supports two ways to connect an account: manually via the API (by supplying account and routing numbers), or through Plaid via the dashboard. The API only creates manual connections.

## Connection types

| Type     | How it's created | Description                                                                                               |
| -------- | ---------------- | --------------------------------------------------------------------------------------------------------- |
| `manual` | API or dashboard | You supply the full account number and routing number directly. Ownership is verified via micro-deposits. |
| `plaid`  | Dashboard only   | Connected through Plaid's bank linking flow. Not available via the REST API.                              |

## Account types

Bank accounts can be either `checking` or `savings`. Most business payment accounts are `checking`.

## Verification lifecycle

When you create a bank account via the API, it enters the `pending_verification` status immediately. You must complete micro-deposit verification before the account can fund any payments.

| Status                 | Meaning                                                                                                                      |
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `pending_verification` | The account has been created. Micro-deposits have been initiated and are on their way to the account. Awaiting verification. |
| `verified`             | Micro-deposit amounts were submitted correctly. The account is ready to fund payments.                                       |
| `unverified`           | All 3 verification attempts were exhausted with incorrect amounts. The account cannot be verified and must be re-added.      |
| `removed`              | The account has been removed and is no longer available.                                                                     |

The standard path is: `pending_verification` → **`verified`**

If verification attempts are exhausted: `pending_verification` → **`unverified`**

## Micro-deposit verification flow

Micro-deposits are two small credits (each typically under \$0.10) sent to your bank account to confirm ownership.

1. **Link the account** — call `POST /v1/bank-accounts` with the full account and routing numbers. The account status becomes `pending_verification` and `microDepositsInitiatedAt` is set.
2. **Wait for deposits** — check your bank statement. The two deposits typically arrive within 1–2 business days.
3. **Submit the amounts** — call `POST /v1/bank-accounts/{id}/verify-micro-deposits` with both deposit amounts as decimal dollar strings.
4. **Confirmed** — on success, `status` changes to `verified` and `microDepositsCompletedAt` is set.

### Verification request format

Amounts are submitted as decimal dollar strings — **not cents**:

```bash theme={null}
curl --request POST \
  --url https://api.cleo-pay.com/v1/bank-accounts/{id}/verify-micro-deposits \
  --header "Authorization: Bearer $CLEO_TOKEN" \
  --header "Content-Type: application/json" \
  --data '{
    "amount1": "0.05",
    "amount2": "0.08"
  }'
```

<Warning>
  You have a maximum of **3 verification attempts** (`verificationAttempts` field). After 3 failed attempts, the account moves to `unverified` and can no longer be verified. You will need to create a new bank account entry and restart the process.
</Warning>

## Security: write-only account numbers

Full account and routing numbers are **write-only**. You submit them when creating a bank account, but they are never returned in any API response. Responses include only the last 4 digits of each:

```json theme={null}
{
  "accountNumberLast4": "9012",
  "routingNumberLast4": "0021"
}
```

<Warning>
  Store full account numbers securely before submitting them to the API. Cleo Pay does not provide a way to retrieve them after creation.
</Warning>

## Default bank account

The `isDefault` flag marks one bank account as the default funding source. When you create a payment without specifying a `bankAccountId`, Cleo Pay uses the default account automatically.

You can have only one default account at a time. Marking a new account as default will un-mark the previous default.

## Bank account fields reference

| Field                      | Type     | Description                                                                    |
| -------------------------- | -------- | ------------------------------------------------------------------------------ |
| `id`                       | string   | Unique identifier for the bank account.                                        |
| `status`                   | string   | `pending_verification`, `verified`, `unverified`, or `removed`.                |
| `type`                     | string   | `checking` or `savings`.                                                       |
| `connectionType`           | string   | `manual` or `plaid`.                                                           |
| `name`                     | string   | Your label for the account (e.g. `"Acme Main Checking"`). Nullable.            |
| `institutionName`          | string   | Bank name, if available (typically populated for Plaid connections). Nullable. |
| `accountNumberLast4`       | string   | Last 4 digits of the account number. Nullable.                                 |
| `routingNumberLast4`       | string   | Last 4 digits of the routing number. Nullable.                                 |
| `isDefault`                | boolean  | Whether this is the default funding account.                                   |
| `microDepositsInitiatedAt` | datetime | When micro-deposits were sent. Nullable.                                       |
| `microDepositsCompletedAt` | datetime | When verification was successfully completed. `null` until verified.           |
| `verificationAttempts`     | integer  | Number of verification attempts made so far. Maximum is 3.                     |

## Example bank account object

```json theme={null}
{
  "id": "ba_01hq2k5r8e4vabc123",
  "status": "verified",
  "type": "checking",
  "connectionType": "manual",
  "name": "Acme Main Checking",
  "institutionName": null,
  "accountNumberLast4": "9012",
  "routingNumberLast4": "0021",
  "isDefault": true,
  "microDepositsInitiatedAt": "2025-03-15T14:00:00Z",
  "microDepositsCompletedAt": "2025-03-17T10:22:00Z",
  "verificationAttempts": 1
}
```

## Next steps

* [Quickstart](/quickstart) — see the full bank account linking and verification flow in context.
* [Payments](/concepts/payments) — use your verified bank account to fund ACH payments.
