Upload a Batch
Upload a batch file (CSV or XLSX) containing many payout rows. The file
is stored, hashed for duplicate detection, and queued for asynchronous
validation. The response returns the batch in uploaded status; the
status transitions to validating, then validated (or
validation_failed) via webhook.
After validated, review GET /v1/batches/{id} and the summary, then
call POST /v1/batches/{id}/confirm to actually create the payouts.
Confirmation expires — see expires_at on the batch record.
Maximum file size: 32 MB. Maximum rows per batch: check current limits with support.
Authorizations
OAuth 2.0 client_credentials grant (RFC 6749 §4.4) bound to a DPoP keypair (RFC 9449).
Flow (every authenticated /v1 call requires both an access token AND a fresh per-request DPoP proof):
- Register a credential via the merchant portal. Anton issues a
client_id(ant_oc_<env>_<32hex>) and aclient_secret(ant_ocs_<env>_<48hex>, shown ONCE). The portal generates an ES256 or Ed25519 DPoP keypair in your browser; you store the private half. - Mint an access token:
POST /oauth/tokenwithAuthorization: Basic <client_id:client_secret>andContent-Type: application/x-www-form-urlencoded. Body:grant_type=client_credentials. ADPoPheader carrying a proof signed for the token endpoint is required (noathclaim on this proof). - Use the token: send
Authorization: DPoP <access_token>plus a freshDPoP: <proof>header on every/v1request. The proof JWT MUST carryhtm(request method),htu(request URL, no query/fragment),iat(within ±60s),jti(unique within 5 min), andath(SHA-256 of the access token, base64url).
Tokens expire in 1 hour in production / staging and 8 hours in sandbox. There are no refresh tokens — call /oauth/token again with your secret. Anton's public signing key is published at /.well-known/jwks.json.
OpenAPI 3.0 has no native DPoP scheme; this declaration plus dpopHeader together convey both the access-token Authorization and the per-request proof header.
Per-request DPoP proof JWT (RFC 9449). MUST accompany the Authorization: DPoP <access_token> header on every protected operation. The proof is signed by the merchant's private DPoP key and carries htm, htu, iat, jti, and ath claims.
Body
CSV or XLSX file. Filename is preserved.
Response
Batch accepted and queued for validation.
A batch upload. Moves through uploaded -> validating -> validated -> confirmed -> processing -> completed | partial | failed. Can be
cancelled from any pre-processing state.
^bat_[a-zA-Z0-9]+$"bat_01HX8Z9K0M2N3P4Q5R6S7T8UBT"
^mer_[a-zA-Z0-9]+$User ID of the operator who uploaded this batch.
uploaded, validating, validated, validation_failed, confirmed, processing, completed, partial, failed, cancelled "payroll_2026_04_15.csv"
csv, xlsx Bytes.
RFC 3339 / ISO 8601 timestamp in UTC.
"2026-04-15T14:30:00Z"
RFC 3339 / ISO 8601 timestamp in UTC.
"2026-04-15T14:30:00Z"
Validation summary the merchant reviews before confirming.
Default funding currency used for rows that don't specify their own. Set at confirmation.
^[A-Z]{3}$"USD"
Aggregate destination-side amount across every valid row, populated
during validation when all rows share a single destination currency.
Absent for mixed-currency batches and legacy batches uploaded before
the aggregate was materialized — callers should fall back to the
per-currency breakdown in summary.estimated_debits.
"12345.67"
Currency of total_amount. Absent for mixed-currency batches.
^[A-Z]{3}$"USD"
Resumability checkpoint — highest row index successfully processed.
Deadline for confirming a validated batch.
"2026-04-15T14:30:00Z"
RFC 3339 / ISO 8601 timestamp in UTC.
"2026-04-15T14:30:00Z"
RFC 3339 / ISO 8601 timestamp in UTC.
"2026-04-15T14:30:00Z"
RFC 3339 / ISO 8601 timestamp in UTC.
"2026-04-15T14:30:00Z"
RFC 3339 / ISO 8601 timestamp in UTC.
"2026-04-15T14:30:00Z"