Documentation
POSTPayouts
Send single and batched outbound transfers.
Payouts move value out. A payout is a single transfer; a batch is many legs under one authorisation and one idempotency key.
Create a payout#
curl -s -X POST "$JUICEPAY_URL/v1/payouts" \
-H "Authorization: Bearer $JUICEPAY_KEY" \
-H "Idempotency-Key: contractor:ctr_44:2026-08" \
-d '{
"amount": "2000.00",
"asset": "USDC",
"recipient": "rcp_2xN8",
"reference": "INV-2291-settlement",
"routing": { "prefer_chains": ["base"], "max_network_fee": "1.25" }
}'{
"id": "po_4bW9xK",
"object": "payout",
"status": "executing",
"amount": "2000.00",
"asset": "USDC",
"recipient": "rcp_2xN8",
"legs": [
{
"chain": "base",
"status": "broadcast",
"tx_hash": "0x8f2a…c71d",
"confirmations": 1,
"finality": "included"
}
],
"created": "2026-08-19T09:14:02Z"
}Payout statuses#
| Status | Terminal | Meaning |
|---|---|---|
created | No | Awaiting authorisation. |
executing | No | Legs broadcast; waiting for finality. |
settled | Yes | All legs final. |
failed | Yes | No leg could be completed. |
partially_settled | Yes | Some legs final, others permanently failed. |
canceled | Yes | Cancelled before broadcast. |
Multi-leg payouts exist because routing may split a transfer across chains when a single chain cannot source the full amount at acceptable cost. Treat legs as authoritative and never assume exactly one.
Batch create#
curl -s -X POST "$JUICEPAY_URL/v1/payouts/batches" \
-H "Authorization: Bearer $JUICEPAY_KEY" \
-H "Idempotency-Key: payroll:2026-08" \
-d '{
"reference": "payroll-2026-08",
"funding": { "asset": "USDC", "source": "auto" },
"legs": [
{ "row": 0, "amount": "2000.00", "recipient": "rcp_2xN8", "reference": "payroll-2026-08-001" },
{ "row": 1, "amount": "1850.00", "recipient": "rcp_5tQ1", "reference": "payroll-2026-08-002" }
]
}'Add ?dry_run=true to validate without moving value. Dry runs return the same validation errors as a real submission, which makes them safe to run in CI.
Limits#
| Limit | Value |
|---|---|
| Legs per batch | 25,000 |
| Batch payload | 32 MB |
| Batch submissions | 20/min per key |
| Single payout | Subject to your policy limits |
Recipients#
curl -s -X POST "$JUICEPAY_URL/v1/recipients" \
-H "Authorization: Bearer $JUICEPAY_KEY" \
-d '{
"name": "Kudzu Logistics",
"chain_addresses": {
"base": "0x7f4a…4a1c",
"solana": "9xQe…7bZ2"
},
"screening": true
}'Register recipients rather than passing addresses inline. You then get screening once, an allowlist entry, and a stable ID that makes policy rules readable.
Retrieve, list, cancel#
curl -s "$JUICEPAY_URL/v1/payouts/po_4bW9xK?expand[]=ledger_entries" \
-H "Authorization: Bearer $JUICEPAY_KEY"
curl -s "$JUICEPAY_URL/v1/payouts?status=settled&limit=100" \
-H "Authorization: Bearer $JUICEPAY_KEY"
curl -s -X POST "$JUICEPAY_URL/v1/payouts/po_4bW9xK/cancel" \
-H "Authorization: Bearer $JUICEPAY_KEY"Cancellation only succeeds while the payout is created. Once a leg is broadcast it cannot be recalled — reversal requires the recipient to send funds back, which is a conversation rather than an API call.
Events#
| Event | Fires when |
|---|---|
payout.created | Payout accepted. |
payout.leg.broadcast | A leg reached the network. |
payout.settled | All legs final. |
payout.partially_settled | Some legs permanently failed. |
payout.failed | No legs completed. |
payout.batch.completed | A batch's legs all reached a terminal state. |