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

# Bank Account Transfers

Move money between two bank accounts that belong to the same Firm with Bank Account Transfers. For example, a Firm can move earned funds from its trust account to its operating account.

To send money to a Client instead, see [Disbursements](https://docs.confidolegal.com/docs/send-money/disbursements.md).

### Prerequisites

Firms must be **`ACTIVE`**, and transfers must be activated for the Firm. Activation is completed by Confido operations; it does not turn on when `firm.status` becomes `ACTIVE`. Use `bankAccountTransferSettingsGet` to check `activated`. Contact **support\@confidolegal.com** to activate transfers for a Firm.

Both bank accounts must belong to the Firm and must be ready to send and receive transfers. If an account is not ready, the transfer fails when you start it.

**1. Create a transfer**

Create a transfer with an amount, a from bank account, and a to bank
account. It starts as a `DRAFT` unless you create it as `APPROVED`.

**2. Approve the transfer**

Someone with the `TRANSFER_APPROVE` permission approves the transfer. When
dual control is on, the approver must be different from the creator.

**3. Start the transfer**

Start the approved transfer with `bankAccountTransferInitiateTxn`. Confido
sends it to the processor.

**4. Funds move**

Funds leave the from bank account and arrive in the to bank account.

## Permissions

Transfers use two permissions. A Firm admin grants them to users and Firm API tokens in the Confido Legal app.

`TRANSFER_DRAFT` lets the holder create, update, return to draft, and delete transfers.

`TRANSFER_APPROVE` lets the holder approve transfers. It is also needed to create a transfer as `APPROVED`, to update an `APPROVED` transfer, and to change the `dualControl` setting.

Starting a transfer, reading transfers, and listing their events need no extra permission.

> [!NOTE]
>
> Each Firm API token counts as one person. When dual control is on, a token
> that created a transfer cannot approve it. A different user or a different
> token must approve it.

## Transfer Settings

Each Firm has one `BankAccountTransferSettings` object.

```typescript theme={"system"}
type BankAccountTransferSettings = {
  activated: boolean;
  dualControl: boolean;
  firm: Firm;
  id: string;
  maxTransferAmount?: Int;
};
```

**activated: Boolean**

Indicates whether transfers are enabled for the Firm. Only Confido operations can change it. A transfer cannot start while this is `false`.

**dualControl: Boolean**

When `true`, a transfer must be approved by someone other than its creator. While dual control is on, you cannot create a transfer as `APPROVED`, and you cannot update an `APPROVED` transfer.

**maxTransferAmount: Int**

The largest transfer amount allowed, in cents. `null` means there is no limit. Confido checks this limit when a transfer is created, when it is updated, and when it is started.

### Get the settings

Use the `bankAccountTransferSettingsGet` query to read the Firm's settings.

```graphql theme={"system"}
query {
  bankAccountTransferSettingsGet {
    id
    activated
    dualControl
    maxTransferAmount
  }
}
```

### Update the settings

Use the `bankAccountTransferSettingsUpdate` mutation to change `dualControl` or `maxTransferAmount`. This mutation needs a Firm admin user or a Firm API token. Changing `dualControl` also needs the `TRANSFER_APPROVE` permission.

```graphql theme={"system"}
mutation {
  bankAccountTransferSettingsUpdate(
    input: { dualControl: true, maxTransferAmount: 5000000 }
  ) {
    id
    dualControl
    maxTransferAmount
  }
}
```

Pass `maxTransferAmount: null` to remove the limit. Fields you leave out are not changed.

## The Bank Account Transfer Object

For complete details of all available fields, see the BankAccountTransfer object in our [GraphQL Playground](https://api.sandbox.gravity-legal.com/).

```typescript theme={"system"}
type BankAccountTransfer = {
  amount: Int;
  approvedBy?: string;
  client?: Client;
  createdBy: string;
  createdOn: Date;
  errorMessage?: string;
  firm: Firm;
  fromBankAccount: BankAccount;
  id: string;
  matter?: Matter;
  memo?: string;
  paymentTxns: Transaction[];
  status: BankAccountTransferStatus;
  toBankAccount: BankAccount;
  updatedOn: Date;
};
```

**amount: Int**

The amount in cents to move from `fromBankAccount` to `toBankAccount`. It must be greater than 0.

**approvedBy: String**

The display name of who approved the transfer. It is `null` until the transfer is approved, and is cleared when the transfer returns to `DRAFT`.

**client**

The client the transfer is associated with. This is optional.

**createdBy: String**

The display name of who created the transfer.

**errorMessage: String**

Details of the failure when the transfer is `FAILED`.

**fromBankAccount**

The bank account the funds are pulled from.

**id**

Unique identifier for the transfer. UUID format.

**matter**

The matter the transfer is associated with. This is optional. If both a client and a matter are set, the matter must belong to that client.

**memo: String**

A note for the Firm's own records. Confido does not send the memo to the bank.

**paymentTxns: Transaction\[]**

The transactions the transfer created. A transfer has no transactions until the processor accepts it. Then it has two transactions for the same amount: a `transfer_out` transaction on the from bank account and a `transfer_in` transaction on the to bank account.

**status**

`DRAFT` The transfer has been created but not approved. It can be updated, approved, or deleted.

`APPROVED` The transfer is approved and ready to start. It can still be updated, returned to `DRAFT`, or deleted.

`REQUEST_PENDING` Confido is sending the transfer to the processor. See [When the result is unknown](https://docs.confidolegal.com/docs/bank-account-transfers/manage-transfers.md#when-the-result-is-unknown).

`IN_TRANSIT` The processor accepted the transfer and the funds are on their way.

`COMPLETED` The funds have arrived in the to bank account.

`FAILED` The transfer could not be started or the processor rejected it. `errorMessage` says why. A failed transfer cannot be started again. Fix the cause and create a new transfer.

**toBankAccount**

The bank account the funds are sent to. It must be different from `fromBankAccount`.

## Transfer Events

Each transfer keeps a history of events. Read it with [`bankAccountTransferEventsList`](https://docs.confidolegal.com/docs/bank-account-transfers/manage-transfers#list-transfer-events).

```typescript theme={"system"}
type BankAccountTransferEvent = {
  creator?: string;
  data: JSON;
  id: string;
  occurredAt: Date;
  type: BankAccountTransferEventType;
};
```

**creator: String**

The display name of who caused the event.

**type**

`CREATED` The transfer was created.

`UPDATED` The transfer was updated.

`APPROVED` The transfer was approved.

`UNAPPROVED` The transfer was returned to `DRAFT`.

`IN_TRANSIT` The processor accepted the transfer.

`COMPLETED` The funds arrived.

`FAILED` The transfer failed.

**data: JSON**

`CREATED`, `APPROVED`, `UNAPPROVED`, `IN_TRANSIT`, and `COMPLETED` events have an empty object.

`UPDATED` events have `oldProps` and `newProps`. They contain only the fields that changed, from `amount`, `clientId`, `fromBankAccountId`, `matterId`, `memo`, and `toBankAccountId`.

```json theme={"system"}
{
  "oldProps": { "amount": 250000 },
  "newProps": { "amount": 300000 }
}
```

`FAILED` events have `failureMessage`.

```json theme={"system"}
{
  "failureMessage": "amount exceeds maximum transfer amount of 5000000"
}
```

> [!NOTE]
>
> Bank account transfers do not send webhooks. To follow a transfer, read it
> with `bankAccountTransferGet` or list its events.


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