The payout ledger
Payouts are the last leg: measured performance becomes reward grants, grants become immutable ledger rows, and rows are batched onto a rail that actually moves money.
This page is the ledger. For the money model — how a entity earns, how money leaves, and what to configure first — start at Getting entities paid.
The chain
Section titled “The chain”performance event → reward grant → payout row → batch → railEach arrow is guarded. A grant claims budget exactly once; a payout row is immutable once written; a row lives in at most one live batch.
await boomin.payouts.run({ periodStart: "2026-08-01", periodEnd: "2026-09-01" });
const accepted = await boomin.payouts.exportCsv({ periodStart: "2026-08-01", periodEnd: "2026-09-01",});await boomin.operations.wait(accepted.operation, { timeout: 120000 });
const batch = await boomin.payouts.batches.retrieve(accepted.batch);console.log(batch.downloadUrl);Full parameter reference: payouts.
const result = await boomin.payouts.run({ periodStart: "2026-08-01", periodEnd: "2026-09-01",});console.log(result.outcome, result.payoutsCreated);Recomputes the period’s rows. Idempotent — running it twice over the same period converges instead of duplicating.
periodStart must be strictly before periodEnd, or invalid_period (400).
Both are YYYY-MM-DD.
A brand with no active payout rule and no active content split throws
PayoutRulesRequiredError (409) instead of answering zero; a brand that is
configured but had a quiet month succeeds with
outcome: "no_eligible_activity". The two used to be the same silent zero —
the distinction.
Statuses
Section titled “Statuses”| Status | Meaning |
|---|---|
pending | Owed, ready to batch |
awaiting_account | Owed, but the recipient has no usable payout destination |
processing | On a rail, in flight |
paid | Settled |
failed | The rail rejected it |
for await (const payout of boomin.payouts.list({ status: "awaiting_account" })) { console.log(payout.id, payout.amountCents);}A row lands pending only when its recipient already has an active,
payouts-enabled payout account. Since entity Connect onboarding is not yet
available, awaiting_account is the normal status — money is owed and
nothing is wrong except that nobody told you where to send it. The csv_batch
rail batches those rows anyway, which is exactly what it is for.
Eligibility
Section titled “Eligibility”A row is eligible for a batch when its status is pending or
awaiting_account and it is not brand-bridged. Rows destined for another
brand’s wallet settle on the wallet rail instead — never both, never twice.
A stripe_connect batch takes pending rows only.
The csv_batch rail
Section titled “The csv_batch rail”exportCsv is the zero-onboarding disbursement path, and it does two things in
one call: builds a csv_batch over the eligible rows, then requests the export.
It answers 202 with id strings and an operation:
{ "batch": "pob_...", "status": "exporting", "operation": "op_...", "items": [ … ], "skipped": 0}skipped is a count of otherwise-eligible rows dropped for want of a
recipient email — they stay eligible for a later batch. If every row is skipped,
the call answers payout_batch_empty (409).
The download URL is not in this response. Poll the operation, then read the batch — the presigned URL is re-minted on every read rather than expiring inside a stored response body.
You pay the CSV out of band, then confirm to record what the rail actually did.
Omit both period fields to sweep every eligible row regardless of period.
Readiness
Section titled “Readiness”const status = await boomin.payouts.connectStatus();{ "object": "payouts.connect_status", "rails": [ { "rail": "csv_batch", "status": "active", "isDefault": true } ], "stripe": { "configured": true, "entityAccounts": 42, "entityAccountsPayoutsEnabled": 0 }}Check this before a run rather than discovering the gap after a build. Rail
entries carry identity and state only — never config, which is a
payout_rails:read surface.
Batches
Section titled “Batches”const { data } = await boomin.payouts.batches.list();const batch = await boomin.payouts.batches.retrieve("pob_...");console.log(batch.items, batch.downloadUrl);batches.retrieve returns the bare batch plus its items and downloadUrl.
The full lifecycle — build, export, confirm, cancel — is on
payouts.batches.
Watching settlement
Section titled “Watching settlement”await boomin.webhooks.endpoints.create({ url: "https://your-app.com/webhooks/boomin", enabledEvents: ["payout.created", "payout.settled", "payout.failed"],});From the CLI
Section titled “From the CLI”npx @boomin/cli payout connectnpx @boomin/cli payout run --period-start 2026-08-01 --period-end 2026-09-01npx @boomin/cli payout export --period-start 2026-08-01 --period-end 2026-09-01 --out payouts.csvnpx @boomin/cli payout list --status awaiting_accountpayout export --out polls the export operation, reads the batch, and downloads
the CSV straight to a file.