Skip to main content
POST
/
payouts
Create Payout
curl --request POST \
  --url https://api.zopay.cash/connect/v1/payouts \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "quote_id": "<string>"
}
'
{
  "id": "<string>",
  "quote": {
    "quote_id": "<string>",
    "user_sends": "<string>",
    "recipient_gets": "<string>",
    "fee_total_usd": "<string>",
    "route": {
      "from_network": "<string>",
      "to_network": "<string>",
      "estimated_seconds": 1
    }
  },
  "estimated_delivery_at": "2023-11-07T05:31:56Z",
  "tracking_url": "<string>"
}
Execute a previously-quoted payout. Consumes the quote_id; production atomically marks it used so a second POST with the same quote_id returns 409 quote_already_used. Sandbox skips the consume but mints a deterministic payout id from (org, quote_id) so the same inputs produce the same response. Status returned is always pending at execute time; partners poll GET /payouts/:id (or, in Phase 4, subscribe to the payout.* webhooks) for state changes.

Authorizations

Authorization
string
header
required

Paste your Connect API key (sk_live_… for production, sk_test_… for sandbox) without the Bearer prefix. Mint and rotate keys from the admin panel.

Headers

Idempotency-Key
string | null
authorization
string | null

Body

application/json

Request body for POST /payouts.

Just the quote_id — every other parameter (asset, amount, destination, route) is locked in the quote and we look it up server-side. This is the contract that lets the quote act as a price promise: the partner can't tamper with the inputs between the price they showed the user and what we execute.

quote_id
string
required

From a prior POST /payouts/quote response. Single-use: a second POST /payouts with the same quote_id returns 409 quote_already_used.

Required string length: 1 - 128

Response

Successful Response

Response body for POST /payouts and base for GET /payouts/:id.

Status transitions monotonically forward (pending → broadcast → delivered, or any → failed). Partners can poll this endpoint or subscribe to payout.broadcast / payout.delivered / payout.failed webhooks (Phase 4) for state changes.

id
string
required

Partner-facing payout id (e.g. pay_...). Opaque and stable across the payout's lifetime.

status
enum<string>
required
Available options:
pending,
broadcast,
delivered,
failed
quote
ConnectPayoutQuoteSnapshot · object
required

A condensed copy of the quote, embedded in the execute / detail response so partners can render the executed terms without a separate /payouts/quote lookup.

Notably omits insufficient_funds (only relevant at quote time) and recommendation (advisory, not part of what was executed). Keeps the snapshot focused on what actually happened.

estimated_delivery_at
string<date-time>
required

Server-computed best estimate. Updated as state advances (a quote estimate of 90s shrinks to 20s after the bridge broadcast lands). Partners can drive UI countdowns off this.

tracking_url
string
required

Public URL the partner can share with their user or embed for self-service tracking. The hosted page renders the same timeline as GET /payouts/:id.