Skip to content

Proceed with the valid lines of a held run.

POST

Path parameters

  • orgIdstringRequired

    The opaque organization id issued to you, normally CUID-shaped (for example cmsx…). It is not an org_-prefixed alias. Pass it unchanged in every organization-scoped path.

  • batchIdstringRequired

    From the 202 that accepted the run, or the batch list.

Headers

  • Idempotency-KeystringRequired

    A unique value per logical operation, 1-255 chars of A-Z a-z 0-9 _ . : -.

    More

    Reuse it to retry. Same key with the same body replays the stored response; same key with a different body is a 409, because answering with the first call's result would hand you a receipt for a payout you did not request. A 4xx releases the key, so you can fix the body and reuse it.

    Reuse it; do not generate one per attempt. A key minted per attempt defeats replay entirely: every retry looks like a new request, so every retry pays. We also watch for an identical body arriving under a different key within 15 minutes and refuse it with DUPLICATE_REQUEST_DETECTED.

    Records are kept for 7 days. That is a retention window only: there is no path where an expired key is re-executed.

Behavior

Only legal while the batch is awaiting_confirmation. The valid lines go to creation; invalid lines stay refused. Correct them and resubmit as a new batch. Confirming a batch that already moved on answers 409 PAYOUT_BATCH_NOT_CONFIRMABLE naming where it actually is.

When your organization requires approval on API payouts, the run is held at awaiting_confirmation whatever autoCommit said, and the first confirm answers 202 with one approval for the whole run, never one per line. A repeat confirm returns the same approval; once your approvers reach quorum the run is released within a minute. If an approver rejected it, confirm answers 409 PAYOUT_BATCH_AWAITING_APPROVAL.

Responses

200The batch, now creating.

Body · PayoutBatch

  • batchIdstringRequired
  • externalReferenceIdstring | nullRequired

    Your own run id, echoed back.

  • statusstringRequired

    A batch moves received -> validating -> either creating (autoCommit, zero errors) or awaiting_confirmation (anything else) -> creating -> completed. canceled is reachable until creation starts; failed means the run broke, not a line. The batch tracks creation; payouts settle on their own lifecycle afterwards.

    Allowed values:receivedvalidatingawaiting_confirmationcreating
    Show 3 more valuescompletedcanceledfailed
  • autoCommitbooleanRequired
  • countsobjectRequired

    Lines by status. The values sum to the number of lines submitted.

    Show 8 properties
    • receivedintegerRequired
    • invalidintegerRequired
    • validatedintegerRequired
    • creatingintegerRequired
    • createdintegerRequired
    • create_failedintegerRequired
    • canceledintegerRequired
    • requires_reviewintegerRequired
  • estimatedSourceTotalstring | nullRequired

    Advisory. What the valid lines will draw from your balance, set when validation finishes; null while validation is running and when any line locks the destination side (no rate is consulted at validation time). Compare against GET /balance before confirming. Half a paid payroll is worse than none.

  • errorobjectOptional

    Present only when status is failed, with the run-level reason.

  • createdAtstring<date-time>Required
  • updatedAtstring<date-time>Required
  • completedAtstring<date-time> | nullRequired
202Held for your approvers. One approval covers the run; nothing is created until it is approved.

Body · PendingApproval

  • statusstringRequired
  • approvalIdstringRequired

    Read it at GET /payouts/approvals/{approvalId}; payout_approval.executed names the payout.

  • approvalRequestIdstringOptional

    Same value as approvalId; kept for the dashboard client.

  • requiredApprovalsintegerRequired
  • expiresAtstring<date-time>Required

Errors

  • 400

    Missing (IDEMPOTENCY_KEY_REQUIRED) or malformed (IDEMPOTENCY_KEY_INVALID) Idempotency-Key.

  • 401

    The key was refused. Nothing ran.

    • UNAUTHORIZED: missing, invalid or revoked, or a key on a route that does not accept one.
    • KEY_EXPIRED: the key passed the expiry it was issued with. Issue a new one; an expired key cannot be rotated.
    • KEY_IP_NOT_ALLOWED: the key is pinned to source addresses and this request came from another.
  • 403

    A valid key that may not make this write. Nothing was changed.

    • MASS_PAYOUTS_DISABLED: batch submission is off for your organization. GET /policy lists mass_payouts in features when it is on; contact support to enable it.
    • FORBIDDEN, ACCOUNT_BLOCKED, LIVE_KEY_ORG_NOT_APPROVED, INSUFFICIENT_SCOPE: as on every write (ForbiddenWrite).
  • 404

    BATCH_NOT_FOUND: no such batch in this organization.

  • 409

    PAYOUT_BATCH_NOT_CONFIRMABLE: the batch is not awaiting confirmation. PAYOUT_BATCH_AWAITING_APPROVAL: an approver rejected the run; the approval id is in detail (there is no approvalId field). Or an idempotency conflict (IDEMPOTENCY_KEY_CONFLICT, IDEMPOTENCY_KEY_REQUEST_IN_PROGRESS).

  • 429

    Too many requests. The default ceiling is 100 requests per minute per API credential on a 60-second window. High-volume payout and reconciliation routes declare a 600/minute override, and batch submission a 30/minute ceiling. A separate 2,000/minute per-source-IP abuse ceiling always applies.

    Obey Retry-After; it is in seconds and is authoritative. A 429 means the request was refused before the handler ran. Retry reads normally; retry an idempotent mutation with its same Idempotency-Key.

Error body · Error
  • typestringRequired

    Stable machine-readable code.

  • detailstringRequired

    What went wrong, in a sentence. Always a string, so detail.toLowerCase() is safe.

    More

    This is the field to read on BAD_REQUEST and PROVIDER_REJECTED, where the type alone does not name the condition.

  • messagestringRequired

    The same text as detail, kept for integrations written before detail existed. Read detail.

  • resolutionstringOptional

    What to do about it, when there is a specific answer. It is not on every error (it is absent on BAD_REQUEST, NOT_FOUND, PAYOUT_NOT_CANCELABLE and DESTINATION_ACCOUNT_NOT_FOUND), so treat it as optional and fall back to detail.

  • statusintegerRequired

    HTTP status, repeated in the body.

  • statusCodeintegerRequired

    The same value as status, kept for integrations written before status existed. Read status.

  • requestIdstringRequired

    Quote this to support and we can find the exact request. Also sent as the x-request-id response header, which is the only place it appears on a successful response. Success bodies do not carry it. Send your own x-request-id on the request and we use it, so your trace and ours share one identifier; otherwise we mint one.

  • errorsarray of stringOptional

    Present on VALIDATION_ERROR; names each field that failed.

  • originalIdempotencyKeystringOptional

    On DUPLICATE_REQUEST_DETECTED only. Send the request again with this to receive the original payout instead of making a second one. Without it there is no way to recover except by risking a double payment.

  • originalPayoutIdstringOptional

    On DUPLICATE_REQUEST_DETECTED only. The payout the first request created.

  • originalBatchIdstringOptional

    On a batch DUPLICATE_REQUEST_DETECTED. The run the first request created.

  • originalRequestIdstringOptional

    On a 409 PAYOUT_OUTCOME_UNKNOWN replay. The requestId of the call whose outcome is unknown; quote it to support.

  • existingRecipientIdstringOptional

    On BANK_ACCOUNT_ALREADY_LINKED. The recipient in your organization that already holds this account.

  • existingMethodIdstringOptional

    On BANK_ACCOUNT_ALREADY_LINKED. The payment method on that recipient.

Branch on type, never on the status or the message. Every error type is listed with what to do about it.

Avvio Partner Payouts · Payout batches · operation confirmPayoutBatch

Try it: Confirm a payout batch

POST https://api.avvio.xyz/business/api/v1/payments/organizations/{orgId}/payouts/batches/{batchId}/confirm

Test keys only. Sent as x-api-key through this site's proxy to the Avvio API, never saved, and cleared when you close this dialog.

Was this page helpful?