# Transfer funds to a seller

> Pay sellers on your own schedule with the Transfers API, independently of any order.

Source: https://help.boltapp.com/api-reference/guides/transfers

The Transfers API moves funds between your marketplace account and a seller's, without tying the
movement to an order or a payment. Use it to pay sellers after fulfilment, after a returns window,
or on a weekly payout run.

Sellers are identified by the seller ID you registered with Bolt when you onboarded them, the same
value you pass as `X-Bolt-Connect-Seller-Id` and in `seller_splits`.

For the full endpoint reference, see [Create a transfer](/api-reference/transfers/transfers/createtransfer)
and the rest of the Transfers reference.

## When to use Transfers [#when-to-use-transfers]

Bolt offers two ways to move money to a seller. They differ in what triggers the movement.

|             | Seller splits at checkout                | Transfers API                                        |
| ----------- | ---------------------------------------- | ---------------------------------------------------- |
| Trigger     | A shopper payment                        | Your own API call, at any time                       |
| Amount      | Fixed at authorization, tied to one cart | Any amount within the seller's per-transfer limit    |
| Timing      | Follows the order's capture              | Whenever you decide to pay                           |
| Use it when | The split is part of paying for a cart   | The payment to the seller is independent of any cart |

Use seller splits when a seller's share is decided at checkout. Use Transfers when you decide later
what a seller is owed.

## Before you begin [#before-you-begin]

Three things must be true before a transfer is accepted. All three are checked on every create, and
none are self-serve.

| Requirement                       | What you need                                                                                                                                                                                                                                    |
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Transfers enabled for the seller  | Enable transfers for each seller in the Bolt Merchant Dashboard, with an optional per-transfer limit. Permissions are **directional**: enabling payouts to a seller does not enable collections from that seller. Ask for both if you need both. |
| Both accounts set up for payments | An account Bolt cannot pay out cannot receive a transfer.                                                                                                                                                                                        |
| A shared settlement currency      | There is no currency conversion. A transfer must be in a currency both sides settle in.                                                                                                                                                          |

<Note>
  Enabling transfers for a new seller is a Bolt-side step with a lead time. Raise the sellers you need
  early. You can build and test the integration while provisioning is in progress.
</Note>

## Choose a direction [#choose-a-direction]

Your marketplace account is always one side of a transfer. The `direction` field says which way the
money moves.

| `direction`  | Money moves                     | Use it for                                             |
| ------------ | ------------------------------- | ------------------------------------------------------ |
| `payout`     | From your account to the seller | Paying a seller what they are owed                     |
| `collection` | From the seller to your account | Recovering an overpayment or a chargeback you absorbed |

`direction` is required and has no default. An implied direction on a money movement is a costly
thing to get wrong, so the API asks you to say it every time.

## Pay a seller [#pay-a-seller]

<Steps>
  <Step title="Create the transfer">
    Send the direction, the seller ID, the amount, and your own `reference`.

    ```bash title="Request"
    curl -X POST https://api-sandbox.boltapp.com/v3/transfers \
      -H "X-API-Key: $BOLT_API_KEY" \
      -H "X-Publishable-Key: $BOLT_PUBLISHABLE_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "direction": "payout",
        "seller_id": "seller_4471",
        "amount": { "units": 4000, "currency": "USD" },
        "reference": "payout-2026-10-14-seller4471",
        "transfer_group": "PAYOUT_2026_10_W2",
        "description": "October payout, orders 95 to 112"
      }'
    ```

    ```json title="Response"
    {
      "id": "trf_9f8e7d6c5b",
      "created_at": "2026-10-14T17:32:28Z",
      "updated_at": "2026-10-14T17:32:28Z",
      "status": "pending",
      "direction": "payout",
      "seller_id": "seller_4471",
      "reference": "payout-2026-10-14-seller4471",
      "amount": { "units": 4000, "currency": "USD" },
      "amount_reversed": { "units": 0, "currency": "USD" },
      "reversed": false,
      "description": "October payout, orders 95 to 112",
      "transfer_group": "PAYOUT_2026_10_W2",
      "payout_reference": null,
      "failure_reason": null,
      "reversals": [],
      "metadata": {}
    }
    ```

    **Expected result:** a `200` with `status: "pending"`. The funds are committed against your balance
    and are waiting for the seller's next payout. The seller does not have the money yet.
  </Step>

  <Step title="Always send a reference">
    `reference` is required, and it is what stops a retry from paying a seller twice. Reusing a
    `reference` returns the transfer you already created instead of creating a second one, and that
    protection does not expire.

    Derive it from something stable in your own system, such as the payout run and the seller:

    ```javascript title="Node.js"
    const reference = `payout-${payoutRunId}-${sellerId}`
    ```

    If a request times out and you do not know whether it landed, retry with the same `reference`, or
    look the transfer up:

    ```bash title="Terminal"
    curl -G https://api-sandbox.boltapp.com/v3/transfers \
      -H "X-API-Key: $BOLT_API_KEY" \
      -H "X-Publishable-Key: $BOLT_PUBLISHABLE_KEY" \
      -d reference=payout-2026-10-14-seller4471
    ```

    The `Idempotency-Key` header also works on every `POST` and `PATCH`, but it expires after 24 hours.
    Use `reference` as the real safeguard.
  </Step>

  <Step title="Follow the transfer to paid">
    A transfer passes through these states.

    | Status       | What it means                                                                    | Can cancel | Can reverse |
    | ------------ | -------------------------------------------------------------------------------- | ---------- | ----------- |
    | `pending`    | Accepted and committed against your balance, waiting for the next payout.        | Yes        | No          |
    | `in_transit` | Included in a payout and sent to the bank.                                       | No         | No          |
    | `paid`       | The funds have arrived.                                                          | No         | Yes         |
    | `failed`     | The bank rejected the payout and the funds were returned to your balance. Final. | No         | No          |
    | `cancelled`  | Withdrawn before it was sent. Final.                                             | No         | No          |

    Subscribe to webhooks rather than polling. Payout timing follows the **seller's** payout cycle, not
    yours, so do not assume a fixed delay.

    | Event                | Fires when                                           |
    | -------------------- | ---------------------------------------------------- |
    | `transfer_created`   | A transfer is created.                               |
    | `transfer_paid`      | The funds have arrived.                              |
    | `transfer_failed`    | The payout was rejected and the funds were returned. |
    | `transfer_cancelled` | A transfer is cancelled before it is sent.           |
    | `transfer_reversed`  | A reversal is created, full or partial.              |
    | `transfer_updated`   | The `description` or `metadata` changed.             |

    **Expected result:** a `transfer_paid` delivery carrying the transfer with `status: "paid"` and a
    `payout_reference` you can reconcile against your statement.

    <Warning>
      A `200` on create means the transfer was accepted, not that the seller was paid. Marking a seller
      paid on the create response will overstate what you have sent them. Wait for `transfer_paid`.
    </Warning>
  </Step>

  <Step title="Handle a failed payout">
    A transfer can reach `failed` if the bank rejects the payout, for example when the seller's account
    has been closed. The funds return to your balance and `failure_reason` says what happened.

    ```json title="Response"
    {
      "id": "trf_9f8e7d6c5b",
      "status": "failed",
      "direction": "payout",
      "seller_id": "seller_4471",
      "amount": { "units": 4000, "currency": "USD" },
      "payout_reference": "po_20261015_0031",
      "failure_reason": "account_closed"
    }
    ```

    `failed` is final. There is nothing to reverse, because nothing reached the seller. Once the
    underlying problem is resolved, create a new transfer with a new `reference`. Reusing the old
    `reference` returns the failed transfer rather than creating a new one.

    Treat the set of `failure_reason` values as open, and handle an unrecognized value as a generic
    failure.

    **Expected result:** a `transfer_failed` delivery, and your balance restored by the transfer amount.
  </Step>
</Steps>

## Group a payout run [#group-a-payout-run]

Set the same `transfer_group` on every transfer in a run, then retrieve the whole run in one call.
`transfer_group` cannot be changed after creation.

```bash title="Request"
curl -G https://api-sandbox.boltapp.com/v3/transfers \
  -H "X-API-Key: $BOLT_API_KEY" \
  -H "X-Publishable-Key: $BOLT_PUBLISHABLE_KEY" \
  -d transfer_group=PAYOUT_2026_10_W2 \
  -d page_size=100
```

```json title="Response"
{
  "transfers": [
    { "id": "trf_9f8e7d6c5b", "status": "paid", "seller_id": "seller_4471" },
    { "id": "trf_1c2d3e4f5a", "status": "pending", "seller_id": "seller_5512" }
  ],
  "pagination": { "page": 1, "page_size": 100, "total_count": 2 }
}
```

Each entry is a complete transfer object. The response above is shortened for readability.

Create one transfer per seller. There is no batch create endpoint.

## Take money back [#take-money-back]

How you undo a transfer depends on where it is in its lifecycle.

### Cancel a transfer that has not been sent [#cancel-a-transfer-that-has-not-been-sent]

While a transfer is `pending`, cancel it. This releases the hold on your balance and nothing ever
reaches the seller.

```bash title="Request"
curl -X POST https://api-sandbox.boltapp.com/v3/transfers/trf_1c2d3e4f5a/cancel \
  -H "X-API-Key: $BOLT_API_KEY" \
  -H "X-Publishable-Key: $BOLT_PUBLISHABLE_KEY"
```

**Expected result:** a `200` with `status: "cancelled"`.

If the transfer has already moved on, you get `transfer_not_cancelable` and the message names the
current status. Once a transfer is `paid`, reverse it instead.

### Reverse a transfer that has been paid [#reverse-a-transfer-that-has-been-paid]

Once a transfer is `paid`, create a reversal. Omit `amount` to reverse the full remaining amount, or
supply one to reverse part of it. You can reverse in several steps, up to the transfer's unreversed
remainder.

```bash title="Request"
curl -X POST https://api-sandbox.boltapp.com/v3/transfers/trf_9f8e7d6c5b/reversals \
  -H "X-API-Key: $BOLT_API_KEY" \
  -H "X-Publishable-Key: $BOLT_PUBLISHABLE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": { "units": 1500, "currency": "USD" },
    "reference": "reversal-return-8831",
    "description": "Partial return, 1 of 3 items"
  }'
```

```json title="Response"
{
  "id": "trr_4a3b2c1d0e",
  "created_at": "2026-10-20T11:02:44Z",
  "transfer_id": "trf_9f8e7d6c5b",
  "status": "pending",
  "amount": { "units": 1500, "currency": "USD" },
  "reference": "reversal-return-8831",
  "description": "Partial return, 1 of 3 items",
  "payout_reference": null,
  "metadata": {}
}
```

**Expected result:** a `200` with the reversal in `pending`. A reversal is a money movement in its
own right: it goes out on a payout and settles like any transfer, so it is not instantaneous.

A transfer in `in_transit` can be neither cancelled nor reversed. Wait for `paid`.

<Warning>
  A reversal moves money between you and the seller. It does not refund the shopper. Refunding a
  shopper is a credit against the original transaction, and the two are separate operations. A
  customer return usually needs both.
</Warning>

## Collect from a seller [#collect-from-a-seller]

To bring funds back from a seller outside of a specific transfer, for example to recover an
overpayment, create a transfer with `direction` set to `collection`.

```bash title="Request"
curl -X POST https://api-sandbox.boltapp.com/v3/transfers \
  -H "X-API-Key: $BOLT_API_KEY" \
  -H "X-Publishable-Key: $BOLT_PUBLISHABLE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "direction": "collection",
    "seller_id": "seller_4471",
    "amount": { "units": 2500, "currency": "USD" },
    "reference": "recovery-2026-10-14-seller4471"
  }'
```

A collection follows the same lifecycle as a payout, in the opposite direction.

Collections need their own permission. Enabling payouts to a seller does not enable collections from
that seller.

## Handle errors [#handle-errors]

Validation failures return `invalid_input_parameter` with a `field` naming the problem. Branch on
`.tag` and `field`, not on the message text.

| `field`                | What to fix                                                                                              |
| ---------------------- | -------------------------------------------------------------------------------------------------------- |
| `transfer_permissions` | Transfers are not enabled for this seller in this direction. Enable them in the Bolt Merchant Dashboard. |
| `seller_id`            | The seller is not one of yours, cannot be paid out, or does not settle in the currency.                  |
| `direction`            | Missing, or not `payout` or `collection`.                                                                |
| `amount`               | The amount is not greater than zero, or is above the per-transfer limit set for the seller.              |
| `amount.currency`      | The currency is not supported, or is not one both sides settle in.                                       |
| `reference`            | Missing, or longer than 255 characters.                                                                  |

State errors use their own tags.

| `.tag`                              | What it means                                                                               |
| ----------------------------------- | ------------------------------------------------------------------------------------------- |
| `transfer_not_cancelable`           | The transfer is past `pending`. Reverse it instead once it is `paid`.                       |
| `transfer_not_reversible`           | The transfer is not `paid`. Cancel it, or wait. A `failed` transfer has nothing to reverse. |
| `transfer_already_reversed`         | The transfer has been reversed in full.                                                     |
| `reversal_amount_exceeds_remaining` | The reversal is larger than the unreversed remainder.                                       |

**Retry only `409`, `429`, and `5xx`**, with backoff and the original `reference`. Every `400`,
`401`, `403`, `404`, and `422` is deterministic: an identical retry fails in exactly the same way.

## Next steps [#next-steps]

<CardGroup cols="2">
  <Card title="Transfers API reference" icon="braces" href="/api-reference/transfers/transfers/createtransfer">
    Every endpoint, field, and error in the Transfers API.
  </Card>

  <Card title="Marketplace Connect quickstart" icon="store" href="/products/connect">
    Onboard a seller and take your first marketplace payment.
  </Card>

  <Card title="Idempotency" icon="repeat" href="/api-reference/guides/idempotency">
    How the `Idempotency-Key` header behaves across Bolt APIs.
  </Card>

  <Card title="Verify webhooks" icon="shield-check" href="/api-reference/guides/verify-webhooks">
    Check the `X-Bolt-Hmac-Sha256` signature before acting on a delivery.
  </Card>
</CardGroup>
