Payouts API
Create payouts to a recipient’s bank card, read them and cancel them. The method field selects the payout method; today there is one method: card. A card payout returns payout_url: the recipient opens it and enters the card on a MAXFI page. Step by step: Card payouts.
MAXFI enables live card payouts for your account; until then POST /v2/payouts with a live key returns 403 card_payouts_not_enabled. Test keys work for every account and never reach a bank.
Keys and permissions
Use the same secret keys as for payments: Authorization: Bearer sk_live_… or sk_test_…. Restricted keys need payouts:read for GET requests and payouts:write for POST requests; payouts:write includes read. A key bound to a channel sees only the payouts of its channel. A test key sees only test payouts, a live key only live ones.
reference: a repeat with the same reference, amount and currency returns the existing payout instead of creating a second one; the same reference with a different amount or currency gets 409 reference_already_used. Or send an Idempotency-Key header with POST /v2/payouts and POST /v2/payouts/{id}/cancel: a successful response is stored for 24 hours and returned for a repeat with the same key, with the idempotent-replay: true header.Create a payout
/v2/payoutsCreates a payout and returns it with 201. A card payout starts in status pending with a payout_url for the recipient. In live mode the amount is held on your available balance (see Money and limits). The body is strict: a field that is not in the table below is rejected with 400 VALIDATION_ERROR, so card numbers cannot be sent.
| Field | Type | Description |
|---|---|---|
| method (required) | string | "card" — the only payout method today. |
| amount (required) | integer | Amount in minor units: 1500 = 15.00. A positive integer. |
| currency (required) | string(3) | Three-letter currency code. Card payouts accept only AZN; another currency gets 400 unsupported_currency. |
| reference | string(64) | Your payout ID: 1–64 characters — letters, digits and _ . : -. A repeat with the same reference, amount and currency returns the existing payout. |
| description | string(255) | Your note, up to 255 characters. Not shown to the recipient. |
| metadata | object | Your key–value data: up to 20 keys and up to 4000 characters of JSON. Returned in the payout and in webhook events. |
| expires_in | integer | Link lifetime in seconds. Values outside 900–604800 (15 minutes to 7 days) are moved to the nearest bound. If omitted, your account setting applies (24 hours by default). |
Response: 201 with the payout object.
List payouts
/v2/payoutsReturns your payouts, newest first, as {"object": "list", "data": [...], "has_more": true | false}. has_more is true when there are more payouts after this page.
| Parameter | Type | Description |
|---|---|---|
| limit | integer | Page size, 1–100. Default 20. |
| offset | integer | Number of payouts to skip. Default 0. |
| status | string | Only payouts with this status: pending, processing, succeeded, failed, canceled, expired or reversed. Another value gets 400 invalid_status. |
curl "https://maxfi-api.exezine.az/v2/payouts?status=pending&limit=20" \ -H "Authorization: Bearer sk_test_…"
{
"object": "list",
"data": [
{
"id": "po_3f9c2a7b1d4e5f60718293ab",
"object": "payout",
"method": "card",
"status": "pending",
"amount": 1500,
"currency": "AZN",
"description": "Payout for order 1042",
"reference": "order-1042",
"metadata": { "order_id": "1042" },
"payout_url": "https://maxfi-api.exezine.az/payout/<token>",
"expires_at": "2026-11-14T12:00:00.000Z",
"card": null,
"recipient": null,
"failure_code": null,
"failure_message": null,
"livemode": false,
"created_at": "2026-11-13T12:00:00.000Z",
"completed_at": null
}
],
"has_more": false
}Get a payout
/v2/payouts/{id}Returns the payout object. A payout of another account, of the other mode or, for a channel-bound key, of another channel returns 404 payout_not_found.
Path parameter
| Parameter | Description |
|---|---|
| {id} | Payout ID: po_ and 24 hexadecimal characters. |
curl https://maxfi-api.exezine.az/v2/payouts/po_3f9c2a7b1d4e5f60718293ab \ -H "Authorization: Bearer sk_test_…"
Cancel a payout
/v2/payouts/{id}/cancelCancels a payout that is still waiting for the recipient (pending) and returns it with status canceled and failure_code: "canceled". In live mode the held amount is released. A payout in any other status returns 409 payout_not_cancelable. MAXFI sends payout.canceled.
Path parameter
| Parameter | Description |
|---|---|
| {id} | Payout ID: po_ and 24 hexadecimal characters. |
curl -X POST https://maxfi-api.exezine.az/v2/payouts/po_3f9c2a7b1d4e5f60718293ab/cancel \ -H "Authorization: Bearer sk_test_…" \ -H "Idempotency-Key: cancel-order-1042"
The payout object
Every endpoint above returns it. Webhook events carry the same object without payout_url.
| Field | Type | Description |
|---|---|---|
| id | string | po_ and 24 hexadecimal characters. |
| object | string | Always "payout". |
| method | string | "card". |
| status | string | pending, processing, succeeded, failed, canceled, expired or reversed — see Statuses. |
| amount | integer | Amount in minor units. |
| currency | string | "AZN". |
| description | string | null | Your note, or null. |
| reference | string | null | Your payout ID, or null. |
| metadata | object | Your metadata; {} if you sent none. |
| payout_url | string | null | Link for the recipient. Filled while the status is pending, otherwise null. Whoever opens it can direct the payout to their own card: send it only to the recipient. |
| expires_at | datetime | When the link expires. |
| card | object | null | { "bin": "424242", "last4": "4242" } — the first 6 and last 4 digits of the card once the recipient has entered it; before that null. |
| recipient | object | null | { "name": "…" } — the name on the card once the recipient has entered it; before that null. |
| failure_code | string | null | Reason code when the status is failed, canceled or expired — see Failure codes; otherwise null. |
| failure_message | string | null | Short explanation of failure_code in English, or null. |
| livemode | boolean | false for test payouts. |
| created_at | datetime | When the payout was created (UTC). |
| completed_at | datetime | null | When the payout reached a final status, or null. |
{
"id": "po_3f9c2a7b1d4e5f60718293ab",
"object": "payout",
"method": "card",
"status": "succeeded",
"amount": 1500,
"currency": "AZN",
"description": "Payout for order 1042",
"reference": "order-1042",
"metadata": { "order_id": "1042" },
"payout_url": null,
"expires_at": "2026-11-14T12:00:00.000Z",
"card": { "bin": "424242", "last4": "4242" },
"recipient": { "name": "Test Recipient" },
"failure_code": null,
"failure_message": null,
"livemode": false,
"created_at": "2026-11-13T12:00:00.000Z",
"completed_at": "2026-11-13T12:03:41.198Z"
}Errors
Errors have the same shape as in the rest of the API: {"error": {"code": "…", "message": "…", "request_id": "…"}}.
| HTTP | Code | Reason |
|---|---|---|
| 400 | VALIDATION_ERROR | The body or the query does not match the description above: a required field is missing, a value has the wrong type or range, or the body has an unknown field. |
| 400 | invalid_reference | reference has characters other than letters, digits and _ . : -. |
| 400 | unsupported_currency | The currency is not AZN. |
| 400 | invalid_metadata | metadata has more than 20 keys or more than 4000 characters. |
| 400 | amount_too_large | The amount exceeds the limit for one payout set for your account. |
| 400 | daily_count_exceeded | Live mode: your account has reached its daily number of payouts. |
| 400 | daily_amount_exceeded | Live mode: this payout would exceed the daily total for your account. |
| 400 | invalid_status | GET /v2/payouts: status is not a payout status. |
| 401 | UNAUTHORIZED | Missing or invalid API key. |
| 402 | insufficient_balance | Live mode: your available balance does not cover the payout. Nothing was held; retry later, with the same reference if you like. |
| 403 | FORBIDDEN | A live key before live mode is enabled for your account, or a restricted key without payouts:read / payouts:write. |
| 403 | card_payouts_not_enabled | Live card payouts are not enabled for your account. |
| 404 | payout_not_found | No payout with this ID in your account and mode. |
| 409 | reference_already_used | A payout with this reference already exists with a different amount or currency. |
| 409 | payout_not_cancelable | The payout is no longer pending. |
| 409 | IDEMPOTENCY_IN_PROGRESS | A request with the same Idempotency-Key is still being processed. |
| 429 | RATE_LIMIT_EXCEEDED | More than 100 requests in 60 seconds from your IP address. |
| 503 | payouts_unavailable | Payouts are temporarily unavailable. Nothing was held; retry later. |
Webhooks
MAXFI sends payout.processing, payout.succeeded, payout.failed, payout.canceled, payout.expired and payout.reversed to your webhook URL — see Webhooks.
