bolt.com is getting a new home → boltapp.com. Click here to transition smoothly to boltapp.com.

Skip to content

Transfer funds to a seller

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

View As MarkdownMCP

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 and the rest of the Transfers reference.

When to use Transfers

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

Seller splits at checkoutTransfers API
TriggerA shopper paymentYour own API call, at any time
AmountFixed at authorization, tied to one cartAny amount within the seller's per-transfer limit
TimingFollows the order's captureWhenever you decide to pay
Use it whenThe split is part of paying for a cartThe 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

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

RequirementWhat you need
Transfers enabled for the sellerEnable 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 paymentsAn account Bolt cannot pay out cannot receive a transfer.
A shared settlement currencyThere is no currency conversion. A transfer must be in a currency both sides settle in.

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.

Choose a direction

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

directionMoney movesUse it for
payoutFrom your account to the sellerPaying a seller what they are owed
collectionFrom the seller to your accountRecovering 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

Create the transfer

Send the direction, the seller ID, the amount, and your own reference.

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"
  }'
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.

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:

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:

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.

Follow the transfer to paid

A transfer passes through these states.

StatusWhat it meansCan cancelCan reverse
pendingAccepted and committed against your balance, waiting for the next payout.YesNo
in_transitIncluded in a payout and sent to the bank.NoNo
paidThe funds have arrived.NoYes
failedThe bank rejected the payout and the funds were returned to your balance. Final.NoNo
cancelledWithdrawn before it was sent. Final.NoNo

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

EventFires when
transfer_createdA transfer is created.
transfer_paidThe funds have arrived.
transfer_failedThe payout was rejected and the funds were returned.
transfer_cancelledA transfer is cancelled before it is sent.
transfer_reversedA reversal is created, full or partial.
transfer_updatedThe 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.

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.

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.

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.

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.

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

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

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.

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

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.

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"
  }'
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.

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.

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.

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

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

fieldWhat to fix
transfer_permissionsTransfers are not enabled for this seller in this direction. Enable them in the Bolt Merchant Dashboard.
seller_idThe seller is not one of yours, cannot be paid out, or does not settle in the currency.
directionMissing, or not payout or collection.
amountThe amount is not greater than zero, or is above the per-transfer limit set for the seller.
amount.currencyThe currency is not supported, or is not one both sides settle in.
referenceMissing, or longer than 255 characters.

State errors use their own tags.

.tagWhat it means
transfer_not_cancelableThe transfer is past pending. Reverse it instead once it is paid.
transfer_not_reversibleThe transfer is not paid. Cancel it, or wait. A failed transfer has nothing to reverse.
transfer_already_reversedThe transfer has been reversed in full.
reversal_amount_exceeds_remainingThe 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

Every endpoint, field, and error in the Transfers API.

Onboard a seller and take your first marketplace payment.

How the Idempotency-Key header behaves across Bolt APIs.

Check the X-Bolt-Hmac-Sha256 signature before acting on a delivery.

On this page