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

# Primary & Backup Funding 

Every Fluz account funds transactions from a **default funding source** built on two roles — a **primary** bank account and a **backup** card. The primary is charged first; the backup steps in when the primary can't be. This page covers how funding works and how to read and change both roles, over the API or in the app.

| Role        | Shown in app as   | Must be a                            | Purpose                                                          |
| ----------- | ----------------- | ------------------------------------ | ---------------------------------------------------------------- |
| **Primary** | Preferred account | Bank account (ACH)                   | The default funding source, charged first for every transaction. |
| **Backup**  | Backup card       | Bank card (debit / credit / prepaid) | Charged if the primary funding source can't be.                  |

Each account has exactly **one primary and one backup** at a time. Selecting a new funding source for a role replaces the previous one.

***

## How funding works

When a user makes a purchase, funds a virtual card, or deposits to their Fluz balance, Fluz charges the **primary** funding source first — by default, the preferred bank account over ACH.

Because ACH can take several days to settle (and can fail), the **backup card** acts as a safety net:

1. When a user pays via ACH, a temporary **hold** may be placed on the backup card for the transaction amount.
2. If the ACH payment **clears**, the hold is released within **1–7 business days**.
3. If the ACH payment **does not clear**, the **backup card is charged** instead.

```mermaid theme={null}
flowchart TD
  A([Transaction initiated]) --> B{Charge primary<br/>bank account via ACH}
  B -->|ACH accepted| C[Temporary hold placed<br/>on backup card]
  C --> D{ACH clears?}
  D -->|Yes| E([Hold released in<br/>1–7 business days])
  D -->|No| F([Backup card charged])
  B -->|Primary can't be charged| F
```

> ❗️ A backup card must be on file before a transaction can complete
>
> Fluz requires a valid bank card as the backup so a transaction can still settle if the primary funding source fails. Without one, transactions that depend on ACH **cannot be started**.

***

## Configuring primary & backup

Primary and backup selection can be managed **via the API** or **in the Fluz app / web portal**. Selecting a new funding source for a role replaces the previous one for that account.

### Via the API

> 📘 Authentication & scopes
>
> These operations require a **user access token**. Reads (`getDefaultFundingSource`) use the `LIST_PAYMENT` scope; changes (`setPrimaryFundingSource`, `setBackupFundingSource`) use `MANAGE_PAYMENT`.

#### Read the current default funding source

Returns both roles for the account. `primary` is `null` when no primary bank account is set; `backup` is `null` when no backup card is set.

```graphql Query theme={null}
query {
  getDefaultFundingSource {
    primary { bankAccountId accountName status lastFour }
    backup  { bankCardId lastFourDigits cardType cardStatus }
  }
}
```

```json Response theme={null}
{
  "data": {
    "getDefaultFundingSource": {
      "primary": {
        "bankAccountId": "d290f1ee-6c54-4b01-90e6-d701748f0851",
        "accountName": "Chase Total Checking",
        "status": "ENABLED",
        "lastFour": "6789"
      },
      "backup": {
        "bankCardId": "16fd2706-8baf-433b-82eb-8c7fada847da",
        "lastFourDigits": "4242",
        "cardType": "CREDIT",
        "cardStatus": "ACTIVE"
      }
    }
  }
}
```

**Response fields**

| Field                   | Type           | Description                                         |
| ----------------------- | -------------- | --------------------------------------------------- |
| `primary`               | object \| null | The primary bank account, or `null` if none is set. |
| `primary.bankAccountId` | ID             | UUID of the linked bank account.                    |
| `primary.accountName`   | string         | Display name of the bank account.                   |
| `primary.status`        | enum           | Bank account status (e.g. `ENABLED`).               |
| `primary.lastFour`      | string         | Last four digits of the account number.             |
| `backup`                | object \| null | The backup bank card, or `null` if none is set.     |
| `backup.bankCardId`     | ID             | UUID of the bank card.                              |
| `backup.lastFourDigits` | string         | Last four digits of the card.                       |
| `backup.cardType`       | enum           | Card type — `DEBIT`, `CREDIT`, or `PREPAID`.        |
| `backup.cardStatus`     | enum           | Card status (e.g. `ACTIVE`).                        |

> 👍 One call, two reads
>
> The same `DefaultFundingSource` object is also returned inside `getWallet { defaultFundingSource { … } }` — so you can read the current selection in the same call you use to list wallet contents.

#### Set the primary funding source (a bank account)

```graphql Mutation theme={null}
mutation {
  setPrimaryFundingSource(input: { bankAccountId: "d290f1ee-6c54-4b01-90e6-d701748f0851" }) {
    primary { bankAccountId accountName }
    backup  { bankCardId lastFourDigits }
  }
}
```

```json Response theme={null}
{
  "data": {
    "setPrimaryFundingSource": {
      "primary": {
        "bankAccountId": "d290f1ee-6c54-4b01-90e6-d701748f0851",
        "accountName": "Chase Total Checking"
      },
      "backup": {
        "bankCardId": "16fd2706-8baf-433b-82eb-8c7fada847da",
        "lastFourDigits": "4242"
      }
    }
  }
}
```

| Argument              | Type      | Required | Description                                                                                     |
| --------------------- | --------- | -------- | ----------------------------------------------------------------------------------------------- |
| `input.bankAccountId` | ID (UUID) | Yes      | A bank account linked to the account and **enabled**. Becomes the funding source charged first. |

#### Set the backup funding source (a bank card)

```graphql Mutation theme={null}
mutation {
  setBackupFundingSource(input: { bankCardId: "16fd2706-8baf-433b-82eb-8c7fada847da" }) {
    primary { bankAccountId accountName }
    backup  { bankCardId lastFourDigits }
  }
}
```

```json Response theme={null}
{
  "data": {
    "setBackupFundingSource": {
      "primary": {
        "bankAccountId": "d290f1ee-6c54-4b01-90e6-d701748f0851",
        "accountName": "Chase Total Checking"
      },
      "backup": {
        "bankCardId": "16fd2706-8baf-433b-82eb-8c7fada847da",
        "lastFourDigits": "4242"
      }
    }
  }
}
```

| Argument           | Type      | Required | Description                                                                         |
| ------------------ | --------- | -------- | ----------------------------------------------------------------------------------- |
| `input.bankCardId` | ID (UUID) | Yes      | A bank card on the account that is **active**. Becomes the fallback funding source. |

> 📘 Both mutations return the account's full `DefaultFundingSource`
>
> Each mutation returns **primary + backup** after the change — so a single call updates one role and confirms the resulting state.

#### Validation rules

* The `bankAccountId` must be a bank account **linked to the account and enabled**; the `bankCardId` must be a bank card **on the account and active**.
* The primary must be a **bank account** and the backup a **bank card** — a mismatch is rejected.
* Setting a role **replaces** the account's previous selection (one primary, one backup at a time).

#### Errors

| Situation                                        | `errorName`          | `code`     | `statusCode` | `message`                                                                             |
| ------------------------------------------------ | -------------------- | ---------- | ------------ | ------------------------------------------------------------------------------------- |
| Bank account not found / not owned / not enabled | `InvalidBankAccount` | `BA-0001`  | 400          | Please verify that your account is active and up-to-date and try again.               |
| Bank card not found / not owned / not active     | `InvalidBankCard`    | `BC-0001`  | 400          | Looks like this bank card is not a valid card, please select a new card and try again |
| Malformed input (e.g. not a UUID)                | `InvalidArguments`   | `ARG-0001` | 422          | Invalid arguments received *(not user-friendly)*                                      |

```json Example error theme={null}
{
  "errors": [
    {
      "message": "Please verify that your account is active and up-to-date and try again.",
      "extensions": {
        "errorName": "InvalidBankAccount",
        "code": "BA-0001",
        "statusCode": 400,
        "userFriendly": true
      }
    }
  ],
  "data": {
    "setPrimaryFundingSource": null
  }
}
```

The structured error lives under `extensions`, keyed off `code` / `errorName`. `statusCode` is a *semantic* status (e.g. `400`, `422`) carried inside `extensions` — the GraphQL transport itself returns **HTTP 200 even for errors**, with the failure in the `errors` array and `data.<field>` set to `null`. **Detect failures by checking for an `errors` array, not the HTTP status.** Some errors also carry optional `codeNumber` and `notificationDetails` keys, and `userFriendly` indicates whether `message` is safe to surface directly to end users.

### In the app / web

**On the web**

1. Open **Accounts and Cards** from the account menu (or go to `/accounts-and-cards`).
2. In the **Default funding source** section at the top of the page:
   * Select **Manage preferred account** to choose the bank account used as the default funding source.
   * Select **Manage backup card** to choose the bank card charged if the preferred account can't be.
3. Your selection is saved immediately.

**On mobile**

1. Open the menu and tap **Accounts and Cards**.
2. Under **Default funding source**, tap **Manage preferred account** or **Manage backup card**.
3. Choose from your linked funding sources. Your selection is saved immediately.

If you don't yet have an eligible funding source, the app prompts you to add one first — a bank account for the preferred account, or a bank card for the backup.

***

## What can be done via API vs. app / web

| Task                                         | API | App / Web |
| -------------------------------------------- | :-: | :-------: |
| Add, update, or delete a bank card           |  ✓  |     ✓     |
| Link or remove a bank account (Plaid)        |  ✓  |     ✓     |
| Set which funding source is primary / backup |  ✓  |     ✓     |

See [Bank Cards](doc:bank-cards) and [Bank Accounts](doc:bank-accounts) for the underlying funding-source operations available through the API.

***

## Eligibility & notes

* The primary payment method must be a **linked bank account**; the backup must be a **bank card**.
* Business accounts must complete **KYB verification** before funding sources — and therefore the default funding source — can be set.
* Some funding sources may be restricted for specific merchants or by account limits and won't be selectable as a default.

> 📘 Want to learn more? [Speak with our experts](doc:contact) for more info or to request a demo.
