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

# Fund Your Account

> Add funds to your business account via bank transfer, ACH direct debit, or crypto

export const ApiExample = ({method = "GET", path, params, body, reference, tenantKey}) => {
  const baseUrl = "https://api.cadanapay.com";
  const query = params ? "?" + Object.entries(params).map(([k, v]) => `${k}=${v}`).join("&") : "";
  const url = `${baseUrl}${path}${query}`;
  const isPlatformPath = (/^\/(v1\/)?platform(\/|$)/).test(path || "");
  const includeTenantKey = tenantKey === undefined ? !isPlatformPath : tenantKey;
  let curl = `curl -X ${method} '${url}' \\\n  -H 'Authorization: Bearer YOUR_API_KEY'`;
  if (includeTenantKey) {
    curl += ` \\\n  -H 'X-MultiTenantKey: YOUR_BUSINESS_TENANT_KEY'`;
  }
  if (body) {
    const formatted = JSON.stringify(body, null, 2);
    curl += ` \\\n  -H 'Content-Type: application/json' \\\n  -d '${formatted}'`;
  }
  return <div>
      <CodeBlock language="bash" filename="bash" wrap>
        {curl}
      </CodeBlock>
      {reference && <div style={{
    marginTop: "-0.5rem",
    marginBottom: "1rem"
  }}>
          <a href={reference} style={{
    fontSize: "0.875rem"
  }}>
            Try it in the playground →
          </a>
        </div>}
    </div>;
};

Before you can run payroll or send payouts, your business account needs funds. Cadana supports three funding methods: bank transfer, ACH direct debit, and crypto deposits.

***

## Check Your Balance

View your current account balances at any time.

<ApiExample method="GET" path="/v1/businesses/8ef9a712-cdae-4110-b1ea-9ba95abbee6e/balances" reference="/api-reference/workforce/treasury/get-balances" />

***

## Sandbox Funding

In sandbox, use the deposit endpoint to add test funds instantly. No bank linking required.

<ApiExample method="POST" path="/v1/sandbox/business-deposits" body={{ value: { amount: 10000000, currency: "USD" }, description: "Test funding for payroll" }} reference="/api-reference/workforce/sandbox/deposit" />

Returns `204` on success. The deposit is processed asynchronously — the balance reflects it within a few seconds.

<Note>
  Amounts are in the **lowest denomination** of the currency. For USD, `10000000` = \$100,000.00.
</Note>

***

## Bank Transfer

Transfer funds from your bank to your Cadana business account using the account details provided by Cadana. Supports domestic ACH, wire (USD), and international SWIFT transfers.

### Get Your Funding Details

Retrieve the bank account details to send funds to. These are also available in the [Dashboard](https://app.cadanapay.com) under **Business > Account > Top up Account**.

<ApiExample method="GET" path="/v1/businesses/8ef9a712-cdae-4110-b1ea-9ba95abbee6e/funding-details" reference="/api-reference/workforce/treasury/get-funding-details" />

The response returns one or more funding accounts depending on the currencies enabled for your business. Pass the optional `currency` query parameter to filter by a specific currency.

**Example — USD:**

For USD, the response includes three transfer methods: ACH, wire, and SWIFT.

```json theme={null}
{
  "data": [
    {
      "type": "ach",
      "currency": "USD",
      "bankName": "Column NA",
      "bankAddress": "123 Main St, San Francisco, CA 94100",
      "beneficiaryAddress": "442 10th Ave, New York City, NY 10001",
      "accountName": "Cadana Inc",
      "accountNumber": "000000000000000",
      "accountType": "Checking",
      "routingNumber": "000000000"
    },
    {
      "type": "wire",
      "currency": "USD",
      "bankName": "Column NA",
      "bankAddress": "123 Main St, San Francisco, CA 94100",
      "beneficiaryAddress": "442 10th Ave, New York City, NY 10001",
      "accountName": "Cadana Inc",
      "accountNumber": "000000000000000",
      "routingNumber": "000000000"
    },
    {
      "type": "swift",
      "currency": "USD",
      "bankName": "Column NA",
      "bankAddress": "123 Main St, San Francisco, CA 94100",
      "beneficiaryAddress": "442 10th Ave, New York City, NY 10001",
      "accountName": "Cadana Inc",
      "accountNumber": "000000000000000",
      "swiftCode": "XXXXUS00"
    }
  ]
}
```

**Example — EUR:**

```json theme={null}
{
  "data": [
    {
      "type": "iban",
      "currency": "EUR",
      "bankName": "Banking Circle S.A.",
      "branchName": "Copenhagen",
      "bankAddress": "123 Main St, Copenhagen, Denmark",
      "accountName": "Cadana Inc",
      "accountNumber": "DK0000000000000000",
      "swiftCode": "XXXXDKKK",
      "country": "DK"
    }
  ]
}
```

Use these details to initiate a transfer from your bank. Funds are credited to your Cadana balance once the transfer settles.

| Transfer Type | Currency | Typical Settlement            |
| :------------ | :------- | :---------------------------- |
| ACH           | USD      | 1–3 business days             |
| Wire          | USD      | Same day or next business day |
| SWIFT         | Multiple | 1–5 business days             |

***

## ACH Direct Debit (USD only)

Link an external US bank account and pull funds directly into your Cadana account.

### Connect a Bank Account

There are two ways to link a bank account:

**Via Dashboard:** Go to **Settings > Payment Methods > Add payment method** and follow the on-screen flow.

**Via hosted link (for platforms):** Generate a hosted link that opens the bank connection flow. The user completes it in their browser and is redirected to your app.

<ApiExample method="POST" path="/v1/businesses/8ef9a712-cdae-4110-b1ea-9ba95abbee6e/external-accounts/link" body={{ returnURL: "https://yourapp.com/funding/success", refreshURL: "https://yourapp.com/funding/retry" }} reference="/api-reference/workforce/treasury/generate-external-account-link" />

**Response:**

```json theme={null}
{
  "url": "https://app.cadanapay.com/external-accounts/link/..."
}
```

Redirect the user to the returned `url` — this opens Cadana's hosted **link-out experience**, where the user selects their bank and authorizes the connection. When they finish or exit, they're redirected back to your `returnURL` (or `refreshURL` if the link has expired).

The `mode` parameter controls where the hosted flow starts:

| `mode`               | Behavior                                                                                                                                                                                                       |
| :------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `standard` (default) | Shows the entry page with an **Add payment method** button before the bank-selection flow.                                                                                                                     |
| `setup`              | Skips the entry page and opens bank selection directly.                                                                                                                                                        |
| `verification`       | Opens a focused verification view for a single `needs_confirmation` account. Requires `externalAccountId` — see [Resume Verification with a Verification Link](#resume-verification-with-a-verification-link). |

Inside the link-out experience, the user connects their account one of two ways:

* **Instant verification** — the user signs in to their bank and the account is verified immediately. It comes back with status `active` and is ready to use.
* **Manual entry + micro-deposit** — the user types their account and routing numbers. This is also the fallback when instant connection isn't available for their bank or fails. The account is created with status `needs_confirmation` and must be verified with a micro-deposit before it can be used — see [Complete Micro-Deposit Verification](#complete-micro-deposit-verification).

<Warning>
  Your business must have completed KYB verification before you can connect an external bank account. If KYB is not yet verified, the connection will be rejected. See [KYB Requirements](/platform/kyb-requirements) for details.
</Warning>

### Check the Account Status

After the user returns from the link-out experience, list external accounts to check the connection status.

<ApiExample method="GET" path="/v1/businesses/8ef9a712-cdae-4110-b1ea-9ba95abbee6e/external-accounts" reference="/api-reference/workforce/treasury/get-external-accounts" />

Each account carries one of these statuses:

| Status               | Meaning                                                                |
| :------------------- | :--------------------------------------------------------------------- |
| `active`             | Verified and ready to use for [deposits](#create-a-deposit).           |
| `needs_confirmation` | Linked with micro-deposits and awaiting verification — not yet usable. |

**Response:**

```json theme={null}
[
  {
    "id": "d43eaff3-bc75-44f6-ac37-3a305192ead6",
    "last4": "0000",
    "bankName": "Example Bank",
    "status": "active"
  }
]
```

### Complete Micro-Deposit Verification

When an account is linked with micro-deposits, it stays in `needs_confirmation` until the user confirms a small test deposit sent to their bank.

1. One or two small test deposits (about **\$0.01**) are sent to the linked bank account. These can take 1–2 business days to appear. The transaction carries a short **verification code** in its description (for example, `SM1A2B`).
2. The business also receives a [Micro-Deposit Verification Required](/white-label/all-notification-kinds#account) email with the expected arrival date and step-by-step instructions.
3. The user completes verification back in the hosted **link-out experience** — immediately after micro-deposit linking is initiated, the flow redirects them to the link-out page, where they enter the code.
4. Once confirmed, the account transitions to `active` and can be used for deposits.

#### Resume Verification with a Verification Link

The test deposits take 1–2 business days, so users typically leave the flow before they can verify. To bring a user back to finish, generate a link in `verification` mode, scoped to the pending account:

<ApiExample method="POST" path="/v1/businesses/8ef9a712-cdae-4110-b1ea-9ba95abbee6e/external-accounts/link" body={{ returnURL: "https://yourapp.com/funding/success", refreshURL: "https://yourapp.com/funding/retry", mode: "verification", externalAccountId: "1f2e3d4c-5678-9012-cdef-345678901234" }} reference="/api-reference/workforce/treasury/generate-external-account-link" />

Redirect the user to the returned `url`. It opens a focused verification page for that account only — the user can complete verification there but cannot add or remove payment methods, which makes it safe to trigger from an automated flow.

Take `externalAccountId` from [the account list](#check-the-account-status). Generating a verification link requires the account to be awaiting verification: the request fails with `404` for an unknown account and `400` if the account is already `active`.

<Note>
  There is no API endpoint to submit the micro-deposit code — verification is completed in the hosted link-out experience only. Poll [the account status](#check-the-account-status), or subscribe to the [`external-account.added`](/reference/events#external-account-added) event, to detect when the account becomes `active`. Only `active` accounts can be used to [create a deposit](#create-a-deposit).
</Note>

### Remove a Linked Account

Delete an external account that is no longer needed.

<ApiExample method="DELETE" path="/v1/businesses/8ef9a712-cdae-4110-b1ea-9ba95abbee6e/external-accounts/d43eaff3-bc75-44f6-ac37-3a305192ead6" reference="/api-reference/workforce/treasury/delete-external-account" />

A successful deletion returns a `204 No Content` response.

### Create a Deposit

Initiate an ACH debit from the linked bank account. Also available in the Dashboard under **Business > Account > Top up Account > ACH Direct Debit**.

<ApiExample method="POST" path="/v1/businesses/8ef9a712-cdae-4110-b1ea-9ba95abbee6e/deposits" body={{ externalAccountId: "d43eaff3-bc75-44f6-ac37-3a305192ead6", amount: { amount: 10000000, currency: "USD" }, paymentMethod: "ach", idempotencyKey: "b6ae5da9-6342-4a58-bd50-8564d68d3f7e", suppressNotification: false }} reference="/api-reference/workforce/treasury/create-deposit" />

**Response:**

```json theme={null}
{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef0123456789"
}
```

<Info>
  ACH deposits typically take 1–3 business days to settle. Your balance updates once the transfer completes.
</Info>

***

## Crypto Funding

Fund your account by sending USDC or USDT to your Cadana crypto wallet address.

<Note>
  Crypto funding is not enabled by default. Contact your account manager to set it up.
</Note>

### Supported Chains

| Token | Supported Chains                          |
| :---- | :---------------------------------------- |
| USDC  | Ethereum, Solana, Arbitrum, Base, Polygon |
| USDT  | Ethereum, Solana, Tron                    |

### Create a Deposit Address

Deposit addresses are created per currency and chain — they don't exist by default. Create one for each chain you want to receive on:

<ApiExample method="POST" path="/v1/businesses/8ef9a712-cdae-4110-b1ea-9ba95abbee6e/crypto-deposit-addresses" body={{ currency: "USDC", chain: "ethereum" }} reference="/api-reference/workforce/treasury/create-crypto-deposit-address" />

**Response:**

```json theme={null}
{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef0123456789",
  "currency": "USDC",
  "chain": "ethereum",
  "address": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e"
}
```

Creating an address fails with `400` if crypto deposits aren't enabled for the business, or if an address already exists for that currency and chain.

### Get Your Crypto Wallet Address

Once created, call the funding details endpoint with `currency=USDC` or `currency=USDT`. The response includes a `cryptoWallets` array with your addresses for each chain.

**Example response:**

```json theme={null}
{
  "cryptoWallets": [
    {
      "currency": "USDC",
      "address": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
      "chain": "ethereum"
    },
    {
      "currency": "USDC",
      "address": "7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs",
      "chain": "solana"
    }
  ]
}
```

<Warning>
  Always verify the `chain` matches the network you're sending from. Sending tokens on the wrong chain will result in lost funds.
</Warning>

<Note>
  If a `memo` is returned, you **must** include it in your transaction. Deposits without the required memo may not be credited.
</Note>

***

## Webhook Notification

When funds arrive in your business account, Cadana emits a [`transaction.succeeded`](/reference/events#transaction-succeeded) event with `type: "DEPOSIT"`. Subscribe to this event to programmatically detect when your account has been funded.

```json JSON theme={null}
{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "eventType": "transaction.succeeded",
  "version": "1.0",
  "timestamp": "2025-06-15T14:30:00Z",
  "data": {
    "id": "d7e8f9a0-b1c2-3456-def0-123456789abc",
    "amount": {
      "currency": "USD",
      "amount": 500000
    },
    "type": "DEPOSIT",
    "reference": "dep-ref-001",
    "recipientId": "acct-9bd99534-8c7f-4b2a",
    "recipientType": "BUSINESS",
    "tenantKey": "cad95193904"
  }
}
```

See [Webhooks](/reference/webhooks) for setup instructions.

***

## Insufficient Funds During Payroll

If you approve a payroll without sufficient balance, it moves to `awaiting funds` status. Once you fund the account, the payroll proceeds automatically — no need to re-approve. See [Payroll Lifecycle](/workforce/payroll-lifecycle) for details.

***

<Accordion title="Manage Reserves (EOR)">
  Reserves allow you to lock a portion of your business balance for obligations like security deposits, severance, or notice period payments. Locked funds are deducted from your available balance and held until released.

  To view reserve balances, pass `include=reserves`:

  <ApiExample method="GET" path="/v1/businesses/8ef9a712-cdae-4110-b1ea-9ba95abbee6e/balances" params={{ include: "reserves" }} reference="/api-reference/workforce/treasury/get-balances" />

  **Lock reserves:**

  <ApiExample method="POST" path="/v1/businesses/8ef9a712-cdae-4110-b1ea-9ba95abbee6e/reserves" body={{ action: "LOCK", type: "SECURITY_DEPOSIT", personId: "550e8400-e29b-41d4-a716-446655440000", amount: { value: "1000.00", currency: "USD" }, idempotencyKey: "b6ae5da9-6342-4a58-bd50-8564d68d3f7e", description: "Security deposit for new employee" }} reference="/api-reference/workforce/treasury/create-reserve" />

  **Release reserves:**

  <ApiExample method="POST" path="/v1/businesses/8ef9a712-cdae-4110-b1ea-9ba95abbee6e/reserves" body={{ action: "RELEASE", type: "SECURITY_DEPOSIT", personId: "550e8400-e29b-41d4-a716-446655440000", amount: { value: "1000.00", currency: "USD" }, idempotencyKey: "c7bf6eb0-7453-4b69-ae61-9675e79e4c8f", description: "Release security deposit for departing employee" }} reference="/api-reference/workforce/treasury/create-reserve" />

  **Reserve types:** `SECURITY_DEPOSIT`, `SEVERANCE`, `NOTICE_PERIOD`
</Accordion>
