Skip to content
JuicePay

JuicePay documentation

Create account

Documentation

POST

Payouts

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#

bash
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" }
  }'
json
{
  "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#

StatusTerminalMeaning
createdNoAwaiting authorisation.
executingNoLegs broadcast; waiting for finality.
settledYesAll legs final.
failedYesNo leg could be completed.
partially_settledYesSome legs final, others permanently failed.
canceledYesCancelled 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#

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

LimitValue
Legs per batch25,000
Batch payload32 MB
Batch submissions20/min per key
Single payoutSubject to your policy limits

Recipients#

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

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

EventFires when
payout.createdPayout accepted.
payout.leg.broadcastA leg reached the network.
payout.settledAll legs final.
payout.partially_settledSome legs permanently failed.
payout.failedNo legs completed.
payout.batch.completedA batch's legs all reached a terminal state.