Changelog
Versioned changes to the 8x Payout Gateway public API.
The public API (/api/v1) is versioned. Within a version, changes are additive only (new optional fields, new endpoints); anything breaking gets a new version path.
v1.2.0 2026-09-24
Additive: a version 2 payout status vocabulary. No breaking changes. New clients default to version 2; existing clients stay on status version 1 (every v1 request and response is unchanged) and migrate to v2 per-source when their consumer is ready.
- A payout's
statusnow follows your client's status version, on thepayout.statuswebhook and on every REST payout response (POSTandGET /api/v1/payouts,GET /api/v1/payouts/{id},POST /api/v1/payouts/{id}/release,POST /api/v1/payouts/{id}/retry,POST /api/v1/payouts/batch). The webhook and REST always use the same version. - Version 1 (legacy — existing clients):
requested,authorized,submitted,paid,failed,returned,held. - Version 2 is the default for new clients (existing clients opt in via 8x ops):
owed,sent,awaiting_withdraw,paid,failed,returned,held. The map from version 1 is in Status versions. - New
PayoutStatusV2schema in the OpenAPI spec. Thestatusproperties onTransaction,TransactionEventandPayoutStatusEventaccept either vocabulary. Thestatusfilter onGET /api/v1/payoutsstill takes version 1 words only.
v1.1.0 2026-06-28
Additive: bulk payouts (the "email + amount" contract) and the owed/withdraw endpoints. No breaking changes — every v1.0.0 request and response is unchanged. Endpoints:
POST /api/v1/payouts/batch— create up to 100 payouts in one signed call. Each item names a payee bypayeeId(one you own) or byemail(the gateway resolves-or-creates the payee). Returns207 Multi-Statuswith one result per row; a failing row never aborts the others. Each row is idempotent on its ownidempotencyKey, or the batch key + the row's payee identity when omitted — so re-sending a batch with rows added/removed/reordered under the same key never double-pays. Requirespayouts:write(andpayees:writefor anyemailitem).POST /api/v1/payouts/{id}/retry— re-drive afailed+transientpayout under the same key.POST /api/v1/payouts/{id}/release— re-run routing/caps on aheldpayout after you clear its blocker.POST /api/v1/disbursements— push owed/IOU rows (the pull/wallet model), idempotent per(source, externalRef); returns207 Multi-Status.POST /api/v1/payees/{id}/methods— adopt an already-KYC'd Stripe or Tipalti account as the payee's payout method (verified live).POST /api/v1/payees/{id}/portal-link— email the payee a signed, single-use hosted-wallet sign-in link.POST /api/v1/payees/{id}/withdraw— consolidate a payee's owed rows into a single payout.GET /api/v1/payees/{id}/balance— the payee's owed balance.
v1.0.0 2026-06-24
Initial public contract. Endpoints:
POST /api/v1/payees— create / idempotently re-fetch a payee.GET /api/v1/payees— list payees (filter bykyc,payable; cursor-paginated).GET /api/v1/payees/{id}— fetch one payee.POST /api/v1/payees/{id}/onboarding-link— gateway-hosted, rail-agnostic onboarding link.GET /api/v1/payees/{id}/readiness— payout readiness + blockers.POST /api/v1/payouts— create a payout, idempotent on(client, idempotencyKey).GET /api/v1/payouts— list payouts (filter bystatus; cursor-paginated).GET /api/v1/payouts/{id}— fetch one transaction with its event trail andretryablehint.
Webhooks (signed, gateway → customer):
payee.updated— onboarding/payability changed.payout.status— payout state changed.
Auth: bearer API key + HMAC request signing (x-8x-timestamp / x-8x-signature, 5-minute window, replay-protected mutations) + per-route scopes. Test mode routes everything through the mock provider.