Retry a transiently-failed payout
Re-run a payout that failed with a transient cause (e.g. the company
wallet was momentarily underfunded) — check the retryable hint on
GET /payouts/{id} first. The retry re-sends under the SAME rail idempotency
code, so the rail dedupes: exactly-once is preserved and a retry can never
double-pay. A payout that is not failed, or whose failure was permanent
(bad destination, not onboarded, unsupported currency), returns 409.
See the Error & held-reason catalog for the concrete action per statusReason.
Required scope: payouts:write.
Authorization
bearerAuth x8xTimestamp x8xSignature Your client API key. Authorization: Bearer <API key>. The gateway stores
only sha256(key); keys are rotatable and revocable.
In: header
Unix time (seconds) at which the request was signed. Must be within 300s of gateway time.
In: header
Hex HMAC-SHA256(signingSecret, "{timestamp}.{rawBody}") over the exact raw
request body (empty string for GET). Defeats tampering and replay.
In: header
Path Parameters
The gateway transaction id.
uuidResponse Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
import { PayoutClient } from '@8x-payout/sdk';const client = new PayoutClient({ baseUrl: process.env.PAYOUT_BASE_URL!, apiKey: process.env.PAYOUT_API_KEY!, signingSecret: process.env.PAYOUT_SIGNING_SECRET!,});// Only for a failed payout with failureKind 'transient' (see retryable on getPayout).const txn = await client.retryPayout(transactionId);{ "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "source": "string", "payeeId": "79417842-2e1e-4110-a361-89b9f39b36ed", "idempotencyKey": "string", "amountCents": 0, "currency": "string", "status": "requested", "provider": "stripe", "providerRef": "string", "reason": "string", "ref": "string", "failureKind": "transient", "retryable": true, "createdAt": "2019-08-24T14:15:22Z", "updatedAt": "2019-08-24T14:15:22Z", "liftingFeeCents": 0, "claimUrl": "string"}Get one payout GET
Fetch a single transaction by id, scoped to your client, with its full event trail and a `retryable` hint. A transaction owned by another client is reported as `404`. **Required scope:** `payouts:read`.
Release a held payout POST
Re-drive a payout that is `held` — a **recoverable** anomaly hold, not a terminal failure. A payout holds for ordinary, fixable reasons: the payee isn't onboarded yet, a required profile field is missing, the resolved rail isn't in your allow-list, or a per-payee daily cap window hasn't elapsed. Read `statusReason` on `GET /payouts/{id}` (a leading snake_case code — `missing_email`, `not_payable`, `rail_not_allowed`, `cap_exceeded_daily`, …), clear the blocker, then call this. It re-runs routing + operational caps under the SAME transaction id: when the blocker has cleared it advances to `authorized`/`submitted`/`paid`; otherwise it stays `held` with an updated `statusReason`. The re-run reuses the persisted rail idempotency code, so a release can NEVER double-pay. A payout that is not `held` returns `409`. See the Error & held-reason catalog for the concrete action per `statusReason`. **Required scope:** `payouts:write`.