> ## 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.

# Manage Transfers

This page covers each query and mutation for [Bank Account Transfers](https://docs.confidolegal.com/docs/bank-account-transfers/overview.md). All of them need a Firm API token. See the [GraphQL Playground](https://api.sandbox.gravity-legal.com/) for every field.

Each mutation returns a result object with a `bankAccountTransfer` field.

## Create a Transfer

Use the `bankAccountTransferCreate` mutation to create a transfer. It needs the `TRANSFER_DRAFT` permission.

**Input**

```typescript theme={"system"}
type BankAccountTransferCreateInput = {
  amount: number; // in cents
  clientId?: string;
  fromBankAccountId: string;
  matterId?: string;
  memo?: string;
  status?: DRAFT | APPROVED;
  toBankAccountId: string;
};
```

**amount** must be greater than 0 and no more than the Firm's `maxTransferAmount`.

**fromBankAccountId** and **toBankAccountId** must be two different bank accounts of the same Firm.

**clientId** and **matterId** are optional. They must belong to the Firm. If you pass both, the matter must belong to the client.

**status** defaults to `DRAFT`. Pass `APPROVED` to create and approve in one step. That needs the `TRANSFER_APPROVE` permission, and it is not allowed when dual control is on.

```graphql theme={"system"}
mutation {
  bankAccountTransferCreate(
    input: {
      amount: 250000
      fromBankAccountId: "trust_bank_account_id"
      memo: "Earned fees for March"
      toBankAccountId: "operating_bank_account_id"
    }
  ) {
    bankAccountTransfer {
      id
      amount
      status
      createdBy
    }
  }
}
```

**Example response:**

```json theme={"system"}
{
  "data": {
    "bankAccountTransferCreate": {
      "bankAccountTransfer": {
        "id": "3f1c2a54-8d7e-4a0b-9c61-2f5e8b7d4a10",
        "amount": 250000,
        "status": "DRAFT",
        "createdBy": "My Integration Token"
      }
    }
  }
}
```

## Approve a Transfer

Use the `bankAccountTransferApprove` mutation to approve a `DRAFT` transfer. It needs the `TRANSFER_APPROVE` permission. When dual control is on, the approver must be different from the creator.

```graphql theme={"system"}
mutation {
  bankAccountTransferApprove(id: "transfer_id") {
    bankAccountTransfer {
      id
      status
      approvedBy
    }
  }
}
```

The transfer moves to `APPROVED`. Approving a transfer does not start it.

## Start a Transfer

Use the `bankAccountTransferInitiateTxn` mutation to send an `APPROVED` transfer to the processor. Anyone who can read the transfer can start it. Only one start can run for a transfer at a time.

```graphql theme={"system"}
mutation {
  bankAccountTransferInitiateTxn(id: "transfer_id") {
    bankAccountTransfer {
      id
      status
      errorMessage
      paymentTxns {
        id
        amountProcessed
        type
      }
    }
  }
}
```

Before it sends the transfer, Confido checks that transfers are activated, that the Firm is active, that the amount is within `maxTransferAmount` and the Firm's transfer limits, and that both bank accounts are ready.

Check `status` on the result:

`IN_TRANSIT` or `COMPLETED` means the processor accepted the transfer. `paymentTxns` now holds a `transfer_out` and a `transfer_in` transaction.

`FAILED` with `errorMessage` set means a check failed before the transfer was sent, or the processor rejected it. No money moved.

`REQUEST_PENDING` with no `errorMessage` means the transfer was sent but Confido could not record the result. See below.

### When the result is unknown

If the result is `REQUEST_PENDING`, the transfer may have been sent. Do not create a new transfer for the same funds. Do not call `bankAccountTransferInitiateTxn` again; it returns an error while a request is pending. Read the transfer later with `bankAccountTransferGet`, and contact **support\@confidolegal.com** if it stays `REQUEST_PENDING`.

## Get a Transfer

Use the `bankAccountTransferGet` query to read one transfer.

```graphql theme={"system"}
query {
  bankAccountTransferGet(id: "transfer_id") {
    bankAccountTransfer {
      id
      amount
      status
      errorMessage
      fromBankAccount {
        id
      }
      toBankAccount {
        id
      }
    }
  }
}
```

## List Transfers

Use the `bankAccountTransfersList` query to list the Firm's transfers. It returns `transfers` and `total`, the number of transfers that match the filters.

```graphql theme={"system"}
query {
  bankAccountTransfersList(
    statuses: [APPROVED]
    orderBy: [createdOn]
    orderDir: [DESC]
    limit: 50
  ) {
    total
    transfers {
      id
      amount
      status
      createdOn
    }
  }
}
```

**Arguments**

**amount** filters by amount in cents with `eq`, `gt`, `gte`, `lt`, or `lte`.

**createdOn** filters by creation date with `gt` or `lt`.

**clientIds**, **matterIds**, **fromBankAccountIds**, and **toBankAccountIds** return transfers that match any id in the list.

**statuses** returns transfers in any of the listed statuses.

**search** matches client name, matter name, and memo. It is case-insensitive and needs at least 3 characters.

**orderBy** sorts by `amount` or `createdOn`. **orderDir** sets `ASC` or `DESC` for each `orderBy` field, by position, and defaults to `ASC`. With no `orderBy`, results are sorted by `createdOn` newest first.

**limit** defaults to 100 and must be between 1 and 1000. Use **offset** to page through results.

## Update a Transfer

Use the `bankAccountTransferUpdate` mutation to change a `DRAFT` or `APPROVED` transfer. It needs the `TRANSFER_DRAFT` permission. Updating an `APPROVED` transfer also needs `TRANSFER_APPROVE`, and it is not allowed when dual control is on. Transfers in any other status cannot be updated.

**Input**

```typescript theme={"system"}
type BankAccountTransferUpdateInput = {
  amount?: number; // in cents
  clientId?: string | null;
  fromBankAccountId?: string;
  id: string;
  matterId?: string | null;
  memo?: string | null;
  toBankAccountId?: string;
};
```

Fields you leave out are not changed. Pass `null` for `clientId`, `matterId`, or `memo` to clear it. The same rules as create apply to the new values.

```graphql theme={"system"}
mutation {
  bankAccountTransferUpdate(input: { id: "transfer_id", amount: 300000 }) {
    bankAccountTransfer {
      id
      amount
      status
    }
  }
}
```

An update that changes a field adds an `UPDATED` event. An `APPROVED` transfer stays `APPROVED` after the update.

## Return a Transfer to Draft

Use the `bankAccountTransferReturnToDraft` mutation to move an `APPROVED` transfer back to `DRAFT`. It needs the `TRANSFER_DRAFT` permission. It clears `approvedBy`, and the transfer must be approved again before it can start.

```graphql theme={"system"}
mutation {
  bankAccountTransferReturnToDraft(id: "transfer_id") {
    bankAccountTransfer {
      id
      status
    }
  }
}
```

## Delete a Transfer

Use the `bankAccountTransferDelete` mutation to delete a `DRAFT` or `APPROVED` transfer. It needs the `TRANSFER_DRAFT` permission. Transfers that have been started cannot be deleted.

```graphql theme={"system"}
mutation {
  bankAccountTransferDelete(id: "transfer_id") {
    bankAccountTransfer {
      id
    }
  }
}
```

The result holds the transfer as it was before it was deleted.

## List Transfer Events

Use the `bankAccountTransferEventsList` query to read a transfer's history. See [Transfer Events](https://docs.confidolegal.com/docs/bank-account-transfers/overview.md#transfer-events) for each event type.

```graphql theme={"system"}
query {
  bankAccountTransferEventsList(id: "transfer_id") {
    events {
      id
      type
      creator
      occurredAt
      data
    }
  }
}
```


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