v1

latestOpenAPI 3.1.02026-07-241653251.3 MB
Payouts

Submit or validate a payout

Single endpoint that drives the full payout lifecycle. The optional validate body field switches between two modes:

  • validate: true — runs the full pre-flight pipeline (schema, business-logic, and address-validity checks) with no side effects. Returns 200 OK with body {} on success, 400 Bad Request with errors[] on any validation failure, or 422 Unprocessable Entity with errors[] if the payout asset is currently depegged. Nothing is persisted; no beneficiary, external account, or payment is created. The Idempotency-Key header is not required and is ignored if supplied.

  • validate: false or omitted (submit) — runs the same validation pipeline then executes the payout. Requires the Idempotency-Key header. On success returns 202 Accepted with a slim { idempotency_key, payout_id, status } body; full resource state is retrieved via GET /payouts or observed on payout.status_updated webhooks. The (platform_code, Idempotency-Key) pair is unique: replaying the same key with the canonical-JSON-equivalent body returns the original 202 echo-back; replaying with a different body returns 400.

post/payouts

Headers

X-SCX-SIGNEDstring required

HMAC-SHA256 signature of the request, base64-encoded. See the Authentication guide for the exact signing formula.

X-SCX-TIMESTAMPstring required
Example:1678901234

Current Unix timestamp in seconds. Must be within 60 seconds of server time or the request is rejected.

Idempotency-Keystring
Example:client-supplied-idempotency-key

Caller-supplied idempotency key (stable across retries of the same logical operation). Required when validate is omitted or false. Ignored in validate mode. zerohash stores a SHA-256 hash of the canonicalized JSON body alongside this key; a replay with the same key but a different body returns HTTP 400.

Request body

validateboolean

When true, runs the full validation pipeline with no side effects (nothing persisted, no downstream resource creation). When omitted or false, zerohash executes the payout.

account_model'omnibus' | 'fully_disclosed' required

Compliance setup applied to this payout. Required. Determines which party is treated as zerohash's legal customer for this transaction and which signed_agreements coverage is required:

  • omnibus — the top-level Payor is the legal customer. The Payor's onboarded signed_agreements must include user_agreement.
  • fully_disclosed — the Ultimate Payor (nested payor.payor) is the legal customer. The inline payor.payor.info.signed_agreements must include user_agreement.

Validated on submission (schema and signed-agreements checks). Echoed on GET /payouts. Immutable per payout — replays of the same Idempotency-Key with a different value return HTTP 400 payload-mismatch.

metadataPayoutMetadata

Caller-supplied free-form key-value pairs attached to the payout, supplied on the POST /payouts request body. Write-only: metadata is NOT returned on the POST /payouts response, NOT returned on GET /payouts, and NOT included on any payout.status_updated webhook. It is retained internally and is part of the idempotency body hash — replays with the same Idempotency-Key but different metadata return HTTP 400 payload-mismatch.

Limits: maximum 50 keys per object; each key 1–40 UTF-8 characters; each value 0–500 UTF-8 characters; strings only (no nested objects, arrays, numbers, booleans, or null values).

Caller responsibility — NO PII: Do NOT place sensitive data — government IDs, full names tied to financial data, account numbers, dates of birth, home addresses, crypto addresses, or any other PII — in metadata values. zerohash treats metadata as opaque.

Example request

{
  "payor": {
    "participant_code": "PAYOR1",
    "payor": {
      "participant_code": "ORIG01"
    }
  },
  "beneficiary": {
    "participant_code": "BENE01",
    "external_account": {
      "external_account_id": "ea_3b1d8e4a"
    }
  },
  "payment": {
    "asset": "USDC",
    "quoted_asset": "USD",
    "total": "100.00",
    "description": "Monthly payout"
  },
  "account_model": "omnibus",
  "metadata": {
    "client_ref": "order-9182",
    "region": "us-west",
    "campaign": "weekly-payout"
  }
}

Response

Validate-mode success (only returned when validate: true). All three validation tiers passed. Body is intentionally empty.

object required

Empty acknowledgement.

Example response

{}