API005 - Mass Pay API (Batch Transfer) – Technical Overview

Last updated: September 1, 2026

The Mass Pay API allows your application to disburse funds to multiple recipients in a single HTTP request. Designed with a wallet-first architecture, this asynchronous API ensures funds are securely routed to a recipient's wallet or through to external rails (banks, cards, etc.), ensuring zero fund loss during provider failure.

1. How it works (the lifecycle)

The API operates asynchronously to handle high volumes efficiently.

  1. Submit — your system POSTs a batch of transactions.

  2. Validation — we perform a lightweight synchronous check (schema, format, auth) and immediately return a 202 Accepted.

  3. Processing — we process items in the background (checking bank accounts, executing external transfers).

  4. Notification — we send webhooks to your system as items transition to Success or Failed.

2. Integration fundamentals

Feature

Specification

Endpoint

POST /API/v4/Fund/BatchTransfer

Format

JSON (UTF-8)

Authentication

Bearer token (OAuth2 / API key), scoped to issuer account

Security

TLS 1.2+ required. Webhooks signed via HMAC-SHA256 (X-Signature)

Throughput

Default 1,000 items per batch (hard max 5,000). Max payload 10 MiB

3. Key developer features

A. Wallet-first reliability (no "lost" funds)

Unlike traditional fire-and-forget APIs, our system routes funds to a recipient wallet first.

  • Happy path: funds credit the wallet → funds push to destination (e.g., bank) → item marked Success.

  • Provider failure: if the external bank/provider declines the transfer, the funds are not reversed or lost. The item state becomes RetainedInWallet — the money sits safely in the recipient's wallet, ready for a retry or manual cashout.

B. Smart defaults and auto-creation

You don't need to manage complex wallet logic on your end.

  • Auto-create: if a recipient doesn't have a wallet, we auto-create one in the batch currency.

  • Smart routing: if you omit specific destination IDs (like WalletId), we automatically select the recipient's default wallet or bank account.

C. Bring your own IDs (idempotency)

You can supply your own CustomerBatchId and CustomerTransactionId for easy reconciliation with your internal ledgers.

  • IDs are echoed back in all responses and webhooks.

  • If you omit them, we generate high-entropy, collision-resistant IDs for you.

4. Supported payment methods

The API supports mixed-method batches. You define the method via SendMethodId.

  • Bank Transfer (XTR94500) — direct-to-bank. Supports fallback to the recipient's default bank if BeneficiaryBankID is omitted.

  • Wallets (XTR94502/XTR94504) — transfer to individual or company wallets.

  • Cards — prepaid virtual debit cards (XTR94503) and digital gift cards (XTR94505).

  • Rapid Transfer (XTR94508) — push-to-card functionality.

  • Physical Check (XTR94507) — mailed checks (US only).

5. Observability and status checks

You're never in the dark about a payment's status.

  • Real-time webhooks: we emit events for Batch.Started, Batch.Item.Completed, and Batch.Item.Failed. All payloads include the specific ErrorCode if a failure occurs.

    • Action required: to enable these notifications, provide a destination URL endpoint to your Account Manager, Customer Success Manager, or by emailing apisupport@xtrm.com.

  • Status endpoint: call GET /API/v4/Fund/BatchTransfer/{BatchId} to see the aggregate status of a batch, or drill down into specific items.

  • History: retrieve a full attempt history (audit trail) for every transaction, including timestamps and results of retries.

6. Quick FAQ for engineering

What if I send a duplicate request? If you reuse a CustomerTransactionId within the same batch, we flag it immediately. If you reuse it across batches, we return a 409 Conflict to prevent double-spending.

How do I handle errors? We provide a closed catalog of error codes (e.g., INSUFFICIENT_FUNDS_RUNTIME, RECIPIENT_NOT_FOUND) so you can programmatically react to failures.

Can I retry a failed item? Yes — you can resubmit the batch with the same IDs. If an item failed previously, we create a new AttemptNo (preserving the history). If it succeeded previously, we return ALREADY_COMPLETED.