Skip to content

Payouts ​

A payout records a USDC transfer you sent to a user. You report it, and Zay confirms it — see How payouts work.

New to the API? Start with Get started.

EndpointOperation
POST /merchants/v1/payouts/reportReport a payout
GET /merchants/v1/payouts/{id}Retrieve payout
GET /merchants/v1/payoutsList payouts

Events: payout.received, payout.expired

The Payout object ​

json
{
  "payout": {
    "id": "60eb2155-c3b4-43d7-9451-0fe1cc009d85",
    "user_id": "e0554f00-e094-4fba-ba22-bc1ffbb7c7be",
    "amount": "12.3",
    "currency_code": "USDC",
    "status": "pending",
    "transaction_hash": "0xabc123",
    "reason": null,
    "custom_metadata": {},
    "created_at": "2025-12-05T12:05:49Z"
  }
}
FieldTypeDescription
idstring (uuid)
user_idstring (uuid)
amountstringDecimal amount serialised as a string. Must be greater than 0 and at most 10 000.
statusstringPayout status One of pending, received, expired.
created_atstring (date-time)Creation date and time (ISO-8601)
currency_codestringCurrency code One of USDC.
transaction_hashstringOn-chain transaction hash of the transfer the merchant broadcast, supplied when reporting the payout.
reasonstring | nullFree-text reason set by Zay when a payout is expired. Null otherwise.
custom_metadataobjectFree-form JSON bag the merchant attaches to the payout at creation.

Payout statuses ​

StatusMeaningTerminal
pendingReported, not yet confirmed by Zayno
receivedZay confirmed the transfer; payout.received was sentyes
expiredZay could not confirm the transfer; payout.expired was sent with a reasonyes

A payout never leaves received or expired.

Report a payout ​

Report a USDC transfer you have already sent on-chain, passing its transaction_hash. The payout is created in pending; Zay then confirms it and moves it to received or expired.

POST /merchants/v1/payouts/report

Request body

FieldTypeDescription
user_idrequiredstring (uuid)
payoutrequiredobject
payout.amountrequiredstringDecimal amount serialised as a string. Must be greater than 0 and at most 10 000.
payout.transaction_hashrequiredstringOn-chain transaction hash of the transfer the merchant broadcast, supplied when reporting the payout.
payout.currency_codestringCurrency code One of USDC.
payout.custom_metadataobjectFree-form JSON bag the merchant attaches to the payout at creation.

user_id is the user's id as returned by Create user — not your own external_id.

Always send a unique Idempotency-Key here, so a network blip never records the same payout twice — see Idempotency.

Returns 201 Created with a wrapped payout object in pending.

Errors:

  • 401 — invalid signature.
  • 404 — user_id does not match a user under this merchant.
  • 422 — missing or blank transaction_hash, invalid amount (≤ 0 or > 10,000), or unsupported currency.
  • 429 — rate limit exceeded.

Examples ​

cURL ​

bash
curl -X POST "https://api-connect.zay.me/merchants/v1/payouts/report" \
  -H "Content-Type: application/json" \
  -H "zay-api-key: $ZAY_API_KEY" \
  -H "zay-timestamp: $TS" \
  -H "zay-signature: $SIG" \
  -H 'Idempotency-Key: "60eb2155-c3b4-43d7-9451-0fe1cc009d85"' \
  -d '{
    "user_id": "2c9596e6-7c48-4fe9-b957-738bd2e04adc",
    "payout": {
      "amount": "1.23",
      "currency_code": "USDC",
      "transaction_hash": "0xabc123",
      "custom_metadata": {"invoice_ref": "INV-42"}
    }
  }'

Python ​

python
import json
import uuid

import requests

body = json.dumps({
    "user_id": user_id,
    "payout": {"amount": "1.23", "currency_code": "USDC", "transaction_hash": "0xabc123", "custom_metadata": {"invoice_ref": "INV-42"}},
})
url = "https://api-connect.zay.me/merchants/v1/payouts/report"
r = requests.post(url, data=body, headers={
    "Content-Type": "application/json",
    "zay-api-key": ZAY_API_KEY,
    "Idempotency-Key": f'"{uuid.uuid4()}"',
    **merchant_headers("POST", url, ZAY_PRIVATE_KEY, body),
})
payout = r.json()["payout"]

Node.js ​

javascript
const url = "https://api-connect.zay.me/merchants/v1/payouts/report";
const body = JSON.stringify({
  user_id: userId,
  payout: { amount: "1.23", currency_code: "USDC", transaction_hash: "0xabc123", custom_metadata: { invoice_ref: "INV-42" } },
});
const res = await fetch(url, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "zay-api-key": ZAY_API_KEY,
    "Idempotency-Key": `"${crypto.randomUUID()}"`,
    ...merchantHeaders("POST", url, ZAY_PRIVATE_KEY, body),
  },
  body,
});
const { payout } = await res.json();

Response ​

json
{
  "payout": {
    "id": "eac4cfcc-97ee-4509-bb10-c6953bf30f9d",
    "user_id": "9ee859c4-844a-49bf-9e68-965ea01004fe",
    "amount": "1.23",
    "currency_code": "USDC",
    "status": "pending",
    "transaction_hash": "0xabc123",
    "reason": null,
    "custom_metadata": {
      "invoice_ref": "INV-42"
    },
    "created_at": "2025-12-05T12:05:49Z"
  }
}

Retrieve payout ​

Retrieve a payout by its id, including its current status.

GET /merchants/v1/payouts/{id}

Parameters

ParameterTypeDescription
idrequiredstring (uuid), pathPayout ID

Errors:

  • 401 — invalid signature.
  • 404 — payout does not exist under this merchant.
  • 429 — rate limit exceeded.

Example ​

bash
curl "https://api-connect.zay.me/merchants/v1/payouts/$PAYOUT_ID" \
  -H "zay-api-key: $ZAY_API_KEY" \
  -H "zay-timestamp: $TS" \
  -H "zay-signature: $SIG"

Response ​

json
{
  "payout": {
    "id": "60eb2155-c3b4-43d7-9451-0fe1cc009d85",
    "user_id": "e0554f00-e094-4fba-ba22-bc1ffbb7c7be",
    "amount": "12.3",
    "currency_code": "USDC",
    "status": "pending",
    "transaction_hash": "0xabc123",
    "reason": null,
    "custom_metadata": {},
    "created_at": "2025-12-05T12:05:49Z"
  }
}

List payouts ​

List payouts under your merchant with cursor pagination and optional filters. Results are ordered by descending creation time.

GET /merchants/v1/payouts

Parameters

ParameterTypeDescription
user_idstring (uuid), queryFilter by user ID
page_sizeinteger, queryPage size
page_cursorstring, queryPage identifier
statusstring, queryPayout status to search by
created_fromstring (date), queryReturn payouts created on or after this date (inclusive)
created_tostring (date), queryReturn payouts created on or before this date (inclusive)

Pass the previous response's next_cursor as page_cursor to get the next page. When next_cursor is null or absent, the list is exhausted. page_size ranges 1..1000 and defaults to 1000.

Errors:

  • 401 — invalid signature.
  • 429 — rate limit exceeded.

Examples ​

cURL ​

bash
curl "https://api-connect.zay.me/merchants/v1/payouts?user_id=$USER_ID&status=pending&page_size=20" \
  -H "zay-api-key: $ZAY_API_KEY" \
  -H "zay-timestamp: $TS" \
  -H "zay-signature: $SIG"

Python ​

python
url = "https://api-connect.zay.me/merchants/v1/payouts"
params = {"user_id": user_id, "status": "pending", "page_size": 20}
r = requests.get(url, params=params, headers={
    "zay-api-key": ZAY_API_KEY,
    **merchant_headers("GET", url, ZAY_PRIVATE_KEY),
})
data = r.json()
payouts = data["payouts"]
next_cursor = data.get("next_cursor")

Node.js ​

javascript
const url = new URL("https://api-connect.zay.me/merchants/v1/payouts");
url.searchParams.set("user_id", userId);
url.searchParams.set("status", "pending");
url.searchParams.set("page_size", "20");
const res = await fetch(url, {
  headers: {
    "zay-api-key": ZAY_API_KEY,
    ...merchantHeaders("GET", url.toString(), ZAY_PRIVATE_KEY),
  },
});
const { payouts, next_cursor: nextCursor } = await res.json();

Response ​

json
{
  "payouts": [
    {
      "id": "bc3d4323-5b62-4bda-ac62-79f76e7942cd",
      "user_id": "48434864-8c35-4a04-abcd-476e5a89457f",
      "amount": "100.0",
      "currency_code": "USDC",
      "status": "pending",
      "transaction_hash": "0xabc123",
      "reason": null,
      "custom_metadata": {},
      "created_at": "2025-12-05T12:05:49Z"
    },
    {
      "id": "abb8ba5a-ba29-4500-8da1-844225707bb5",
      "user_id": "48434864-8c35-4a04-abcd-476e5a89457f",
      "amount": "200.0",
      "currency_code": "USDC",
      "status": "pending",
      "transaction_hash": "0xabc123",
      "reason": null,
      "custom_metadata": {},
      "created_at": "2025-12-05T12:05:49Z"
    },
    {
      "id": "9a0aef2d-8730-48dd-ae80-7c616370bc07",
      "user_id": "48434864-8c35-4a04-abcd-476e5a89457f",
      "amount": "200.0",
      "currency_code": "USDC",
      "status": "pending",
      "transaction_hash": "0xabc123",
      "reason": null,
      "custom_metadata": {},
      "created_at": "2025-12-05T12:05:49Z"
    }
  ],
  "next_cursor": "Ijk0ZjZhYjA1LTIxZTEtNDMxYS1hMzY4LWU2MmY1NDc1M2RmZiI=--f0aba3c8e2f7b8970dff0121c4626caaaa1985ba"
}