Skip to main content
Batch payouts let you create multiple payouts in a single request, ideal for payroll, affiliate payments, or any scenario requiring many transfers at once. This guide covers best practices and implementation details.
Examples in this guide target the Sandbox (https://api.sandbox.zuba.com). Swap in https://api.zuba.com for production.

Why Use Batch Payouts

  • Efficiency: Create hundreds of payouts with a single API call, reducing API overhead
  • Per-payout results: Each item in the batch is processed independently. Failures are returned inline as { error, clientRef } objects in the 201 response array, alongside the successful payout objects
  • Up-front validation: Request-level validation is all-or-nothing. One malformed item rejects the entire batch with a 400 before anything is created

Single API Call for Multiple Payouts

The Zuba API accepts both single payout objects and arrays of payout objects at the same endpoint. Currency Fields: inputCurrency is the currency from your account you’ll be paying from, while currency is what the beneficiary will receive (automatic conversion if different):
senderInfo is only needed when paying out on behalf of a third party. When omitted, your workspace is used as the business originator. Business originators use type: "business" with companyName, registrationNumber, and country.
For the live routes and destination currencies each rail supports, see Payment Routes or call GET /v1/payouts/available-rails.

Preparing Beneficiaries

Before creating batch payouts, ensure all beneficiaries exist. Here’s how to bulk create them:
Account data fields differ per destination. For example, iban accounts (EUR/GBP) require iban and accountHolderName, with bic optional. Use GET /v1/payouts/requirements to check the required fields for a currency, and see Account Types for every shape.

CSV Import Example

Process payroll data from a CSV file:

Monitoring Batch Progress

Webhooks are the primary mechanism for tracking payout status: subscribe once and receive an event every time a payout in the batch transitions (for example to processing, paid, or failed), with no polling. If you do need to poll, prefer GET /v1/payouts (the list endpoint) over per-ID requests. For a small batch, per-ID polling looks like this:

Error Handling in Batches

Batch creation is not atomic. There are two distinct failure modes:
  1. Validation failure (400): if any payout in the array fails request validation, the entire batch is rejected before anything is created. details contains per-field errors ({ field, message }) for the first invalid payout.
  2. Per-payout failure (inside a 201): once validation passes, each payout is processed independently. A payout that cannot be created (for example, insufficient balance or a duplicate clientRef) is returned as an inline { error, clientRef } element in the response array; the other payouts succeed normally.
Handle both:

Retries and Idempotency

clientRef is unique per workspace, which makes retries safe by construction:
  • A single-payout request that reuses a clientRef is rejected with 400 Payout with this client reference already exists.
  • In a batch, a duplicate clientRef surfaces as an inline { error, clientRef } element in the 201 response array; the other rows are unaffected.
  • Re-submitting a partially failed batch is therefore safe: rows that were already created come back as duplicate errors, and only the previously failed rows create payouts.
The endpoint also supports an optional Idempotency-Key header for transport-level retries: a repeat with the same key and the same body replays the original response without creating new payouts; the same key with a different body is rejected with 422; a repeat while the original request is still in flight returns a retryable 409. Keys expire 24 hours after the original request completes.

Best Practices

1. Batch Size Limits

Keep batch sizes reasonable to avoid timeouts:

2. Validation Before Submission

Validate all payout data before submission. The lists below cover the live destination currencies and routes; prefer GET /v1/payouts/available-rails and GET /v1/payouts/requirements to check availability dynamically:

3. Progress Reporting

Implement progress tracking for large batches:

Complete Batch Payout Example

Here’s a complete implementation:

Next Steps

  • Set up webhooks to receive real-time status updates for your batch payouts
  • Learn about error handling strategies for production batch processing
  • Explore the API reference for advanced payout options