Create many payouts in one call

POST
/api/v1/payouts/batch

Pay many people in a single signed request — the email + amount contract. Each item identifies a payee by payeeId (one you own) or by email (the gateway resolves-or-creates a payee keyed by that email), plus an amountCents. As always the body carries no destination — each rail is resolved server-side from the payee's KYC-locked method.

The response is 207 Multi-Status with one entry per row, in request order: status: ok carries the created/replayed transaction (inspect its own status — an un-onboarded email row comes back held), status: error carries a stable error code from the closed per-row enum on BatchPayoutResultItem.error. A failing row never aborts the others.

Exactly-once. Each row's idempotency key is its own idempotencyKey when set, else it is derived from the batch key and the row's payee identity (not its array position). So re-sending the same batch key with rows added, removed, or reordered replays the rows already paid and pays only the genuinely new ones — it never double-pays. Two rows targeting the same payee without explicit per-row keys are ambiguous and rejected (400 duplicate_target); give them distinct idempotencyKeys to pay the same payee twice in one batch.

Required scope: payouts:write. Items that use email (which mint a payee identity) additionally require payees:write.

Authorization

bearerAuth x8xTimestamp x8xSignature
AuthorizationBearer <token>

Your client API key. Authorization: Bearer <API key>. The gateway stores only sha256(key); keys are rotatable and revocable.

In: header

x-8x-timestamp<token>

Unix time (seconds) at which the request was signed. Must be within 300s of gateway time.

In: header

x-8x-signature<token>

Hex HMAC-SHA256(signingSecret, "{timestamp}.{rawBody}") over the exact raw request body (empty string for GET). Defeats tampering and replay.

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

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!,});const result = await client.payoutBatch({  idempotencyKey: 'payroll-2026-10',  items: [    { email: 'a@example.com', amountCents: 5000, currency: 'USD', ref: 'row_1' },    { payeeId, amountCents: 1250, currency: 'USD', ref: 'row_2' },  ],});for (const row of result.results) console.log(row.index, row.status);
{  "results": [    {      "index": 0,      "status": "ok",      "transaction": {        "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"      },      "idempotentReplay": true,      "error": "invalid_target"    }  ]}