---
title: "Pay creators with one card payment"
method: POST
path: "/v1/creator-campaigns/{campaignId}/payout-batches"
tags: ["Creator Campaigns"]
---

# Pay creators with one card payment

`POST /v1/creator-campaigns/{campaignId}/payout-batches`

## Request

- Base URL: `https://zernio.com/api`
- URL: `https://zernio.com/api/v1/creator-campaigns/{campaignId}/payout-batches`
- Auth: HTTP bearer

Pays exactly what is owed to the creators of a `treasury` campaign by charging the billing owner's saved card, with no redirect.

### How it works

1. Every payable creator who finished payout setup (or only `participantIds`, minus `excludeParticipantIds`) is held in `settling`.
2. The saved card (the default one, or `paymentMethodId`) is charged the total plus the fee (4% per creator, 50 cent minimum) while the payer is present.
3. Once the charge succeeds, each creator gets a transfer funded by it, and the batch ends `paid` or `partially_failed`.

A creator whose payouts were disabled before the payment landed is skipped and stays payable.

### 3D Secure

`payment.status: requires_action` means the bank asked the payer to confirm. Complete it with Stripe.js `handleNextAction({ clientSecret })`, then call `POST /v1/payout-batches/{batchId}/confirm`.

One left unfinished is cancelled after 30 minutes and every amount is payable again. Cancel it sooner with `POST /v1/payout-batches/{batchId}/cancel`.

### Limits and errors

- 402 `payment_required`: no saved card. Nothing is held.
- 402 `card_declined`: the bank's reason; every amount is payable again.
- 402: card payouts are limited to $10,000.00 gross per rolling 30 days by default. Over it the call answers "Over your instant payout limit. Top up your balance to pay more this month, or contact support to raise the limit."
- 400: nothing payable ("Nothing is payable.").

### Access and retries

Needs an owner, admin or billing admin, signed in or through a full-access key they created.

Send an `Idempotency-Key` so a retry never opens a second batch.

## Headers

- `Idempotency-Key` string

## Request body

- object
  - `participantIds` string[]: Pay only these participants. Defaults to every payable participant who is ready.
  - `excludeParticipantIds` string[]: Leave these participants out.
  - `paymentMethodId` string: A saved card of the billing owner's (`pm_...`). Defaults to the default payment method.

## Response `201`

Batch created and the card charged, or the bank asked for 3D Secure.

- object
  - `batch` PayoutBatch, required
    - `id` string, required
    - `campaignId` string, nullable, required
    - `status` 'awaiting_payment' | 'paying' | 'paid' | 'partially_failed' | 'failed' | 'expired', required: `awaiting_payment` until the card charge succeeds (3D Secure included); `paying` while transfers go out; then `paid`, `partially_failed` (some items failed or were skipped), `failed` (the card was declined, or none paid) or `expired` (the payment was cancelled unpaid, every amount is payable again).
    - `method` 'card', required
    - `amountCents` integer, required: Total the creators receive.
    - `feeCents` integer, required: Total Zernio fee.
    - `totalCents` integer, required: The card charge: amountCents plus feeCents.
    - `items` PayoutBatchItem[], required
      - `id` string, required
      - `participantId` string, required
      - `creator` object, required
        - `displayName` string, required
      - `amountCents` integer, required: What the creator receives, in full.
      - `feeCents` integer, required: Zernio fee on top: 4% with a 50 cent minimum.
      - `totalCents` integer, required: amountCents plus feeCents.
      - `status` 'pending' | 'paid' | 'failed' | 'skipped', required: `skipped`: not paid because payout setup was not finished, or the card payment never completed; the amount is payable again. `failed`: Stripe refused the transfer; the amount is payable again.
      - `failureReason` string, nullable, required: Why the item was not paid, in plain words.
      - `transferId` string, nullable, required: The treasury transfer that paid this item.
    - `paidAt` string, date-time, nullable, required
    - `finishedAt` string, date-time, nullable, required
    - `createdAt` string, date-time, required
  - `payment` object, required
    - `status` 'succeeded' | 'processing' | 'requires_action', required
    - `clientSecret` string, nullable, required: PaymentIntent client secret for Stripe.js handleNextAction; set only when status is requires_action

## Other responses

- `400`: Invalid request
- `401`: Missing or invalid API key. `code` is `missing_credentials` when no Authorization header was sent and `invalid_credentials` when the key is unknown, revoked or expired.
- `402`: Over the instant payout limit or no saved card (code `payment_required`), or the bank declined the charge (code `card_declined`).
- `403`: Refused (`insufficient_permissions`). One of: - A restricted API key without the `money` resource group. - A profile-scoped API key. Money leaves the whole team's balance, so moving it needs a full-access key or a signed-in session ("Moving money needs a full-access key or a signed-in session."). - A member or viewer, signed in or through a key they created. Only an owner, admin or billing admin moves money.
- `404`: The campaign, participant or submission does not exist, belongs to another team, or sits in a profile this key cannot reach (code `resource_not_found`).
- `409`: The campaign, participant or submission is not in a state that allows this action (code `invalid_resource_state`); the message names the current state. Also returned while the same `Idempotency-Key` is still processing.

## Changes

- **2026-10-29** `dbfaa35515ac`: 1 breaking, 2 info
  - removed the required property `url` from the response with the `201` status
  - added the new optional request property `paymentMethodId`
  - added the required property `payment` to the response with the `201` status
- **2026-10-28** `8f2c44dd7550`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/zernio/apis/zernio-api/changes/v1/creator-campaigns/:campaignId/payout-batches/post.md)

---

[API](https://skmtc.dev/zernio/apis/zernio-api.md) - [All operations](https://skmtc.dev/zernio/apis/zernio-api/llms.txt) - [OpenAPI document](https://skmtc.dev/zernio/apis/zernio-api/revisions/c319eb5d95b6?raw)
