Transfer funds to a seller
Pay sellers on your own schedule with the Transfers API, independently of any order.
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 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
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. |
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.
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
Create the transfer
Send the direction, the seller ID, the amount, and your own reference.
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"
}'{
"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:
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:
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-seller4471The 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.
| 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.
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.
{
"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.
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{
"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.
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.
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"
}'{
"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.
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.
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
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.