Skip to content

Using Payment Batches

This guide walks you through creating and processing a payment batch — grouping multiple payments into a single unit for rate-limited execution and a single completion notification.

What You'll Learn

  • How to create a payment batch
  • How to add payments to a batch
  • How to submit a batch for processing
  • How to monitor batch progress
  • Handling failures and retries

Prerequisites

Before using payment batches:

Understanding Payment Batches

Payment batches let you group up to 500 payments into a single unit. Instead of executing payments one by one, the batch processor handles rate limiting, quote refreshing, and error isolation automatically. When all payments complete, a single digest notification is sent — not one per payment.

When to Use Batches

  • Payroll: Execute all salary payments in one batch
  • Vendor disbursements: Pay multiple suppliers at once
  • Recurring bulk payments: Monthly rent, subscription, or commission payments
  • High-volume operations: Any scenario with more than a handful of payments

How It Works

YourApplicationTreasuryPathAPI 1. Create batch(POST /payment_batches) Batch created(status: building) 2. Create payment with batch ID(POST /payments) - repeat Payment added to batch 3. Process batch(POST /payment_batches/ID/process_batch) Batch submitted(status: processing) 4. Webhook(PaymentBatchCompletedEvent)
YourApplicationTreasuryPathAPI 1. Create batch(POST /payment_batches) Batch created(status: building) 2. Create payment with batch ID(POST /payments) - repeat Payment added to batch 3. Process batch(POST /payment_batches/ID/process_batch) Batch submitted(status: processing) 4. Webhook(PaymentBatchCompletedEvent)

Step 1: Create a Payment Batch

Create an empty batch that will hold your payment instructions.

curl -X POST "https://api.treasurypath.com/api/v1/companies/{company_id}/payment_batches" \
  -H "Authorization: Bearer {jwt_token}" \
  -H "Content-Type: application/json" \
  -d '{
    "payment_batch": {
      "idempotency_key": "payroll-2026-03",
      "label": "March 2026 Payroll",
      "metadata": {
        "department": "engineering",
        "period": "2026-03"
      }
    }
  }'

Success Response (201 Created)

{
  "data": {
    "id": "Z2lkOi8vd2FsbGV0LWFwcC9QYXltZW50QmF0Y2gvMQ",
    "status": "building",
    "label": "March 2026 Payroll",
    "idempotency_key": "payroll-2026-03",
    "total_count": 0,
    "succeeded_count": 0,
    "failed_count": 0,
    "metadata": {
      "department": "engineering",
      "period": "2026-03"
    },
    "submitted_at": null,
    "completed_at": null,
    "created_at": "2026-03-15T10:00:00.000Z",
    "updated_at": "2026-03-15T10:00:00.000Z"
  }
}

Save the Batch ID

Copy the id from the response — you'll pass it as payment_batch_id when creating each payment.

Idempotency

If you send the same idempotency_key again, the existing batch is returned with a 200 OK instead of creating a duplicate. Use meaningful keys like "payroll-2026-03" or "vendor-disbursement-batch-42".

Step 2: Create Quotes and Add Payments

For each payment in the batch, create a quote and then a payment with the payment_batch_id set.

2a. Create a Quote

curl -X POST "https://api.treasurypath.com/api/v1/companies/{company_id}/quotes" \
  -H "Authorization: Bearer {jwt_token}" \
  -H "Content-Type: application/json" \
  -d '{
    "quote": {
      "from_profile_id": "{from_profile_id}",
      "to_profile_id": "{to_profile_id}",
      "instructed_amount": {
        "amount": 5000.00,
        "currency": "USD"
      }
    }
  }'

2b. Add Payment to Batch

curl -X POST "https://api.treasurypath.com/api/v1/companies/{company_id}/payments" \
  -H "Authorization: Bearer {jwt_token}" \
  -H "Content-Type: application/json" \
  -d '{
    "payment_instruction": {
      "payment_quote_id": "{quote_id}",
      "reason": "wages_salary",
      "idempotency_key": "payroll-2026-03-employee-101",
      "credit_note": "March 2026 salary",
      "payment_batch_id": "Z2lkOi8vd2FsbGV0LWFwcC9QYXltZW50QmF0Y2gvMQ"
    }
  }'

Repeat steps 2a and 2b for each payment in the batch.

Batched Payments Are Not Executed Immediately

When payment_batch_id is set, the payment is held in the batch instead of being executed right away. Execution happens when you process the batch in Step 3.

Expired Quotes Are Refreshed Automatically

Don't worry if quotes expire before you process the batch. The batch processor automatically refreshes expired quotes during execution.

Batch Validation Errors

If the batch is full or not in building status:

{
  "errors": [
    {
      "field": "payment_batch_id",
      "message": "Payment batch has reached the maximum of 500 payments"
    }
  ]
}

Step 3: Process the Batch

Once all payments have been added, submit the batch for processing.

curl -X POST "https://api.treasurypath.com/api/v1/companies/{company_id}/payment_batches/Z2lkOi8vd2FsbGV0LWFwcC9QYXltZW50QmF0Y2gvMQ/process_batch" \
  -H "Authorization: Bearer {jwt_token}"

Success Response (202 Accepted)

{
  "data": {
    "id": "Z2lkOi8vd2FsbGV0LWFwcC9QYXltZW50QmF0Y2gvMQ",
    "status": "processing",
    "label": "March 2026 Payroll",
    "total_count": 25,
    "succeeded_count": 0,
    "failed_count": 0,
    "submitted_at": "2026-03-15T11:00:00.000Z",
    "completed_at": null
  }
}

Processing Is Asynchronous

The 202 Accepted response means the batch has been queued for processing. Payments are executed in the background with rate-limited concurrency. Monitor progress via polling or webhooks.

Common Process Errors

Status Code Error Cause
422 Batch is not in building status Batch was already processed or expired
422 Batch has no payment instructions No payments were added to the batch
422 Batch exceeds maximum of 500 payments Too many payments in the batch
409 Batch is already being processed Concurrent processing request

Step 4: Monitor Batch Progress

When all payments in a batch finish processing, a PaymentBatchCompletedEvent webhook is sent:

{
  "event": "PaymentBatchCompletedEvent",
  "timestamp": "2026-03-15T11:05:30.000Z",
  "company_id": "Z2lkOi8vYXBwL0NvbXBhbnkvMTIz",
  "resource_id": "Z2lkOi8vd2FsbGV0LWFwcC9QYXltZW50QmF0Y2gvMQ",
  "actor_id": null
}

Suppressed Individual Notifications

Individual payment webhooks (CompletedEvent, FailedEvent, DebitInitiatedEvent) are suppressed for batched payments. You receive only the batch-level notification.

Option B: Poll the Batch Status

curl -X GET "https://api.treasurypath.com/api/v1/companies/{company_id}/payment_batches/Z2lkOi8vd2FsbGV0LWFwcC9QYXltZW50QmF0Y2gvMQ" \
  -H "Authorization: Bearer {jwt_token}"

Watch the succeeded_count and failed_count fields to track progress. The batch reaches a terminal status when all payments have been processed:

Terminal Status Meaning
completed All payments succeeded
completed_with_failures Some payments succeeded, some failed
failed All payments failed

Handling Failures

When a batch completes with completed_with_failures status, some payments failed while others succeeded. To identify which payments failed:

  1. List all payments for the batch by querying the payments endpoint
  2. Check individual payment statuses to find the failed ones
  3. Create a new batch with only the failed payments to retry

Failure Isolation

Each payment in a batch is processed independently. A single payment failure does not affect other payments in the batch.

Batch Expiry

Batches left in building status for more than 7 days are automatically expired by the system. Once expired, the batch cannot be processed.

To avoid expiry:

  • ✅ Process batches promptly after adding all payments
  • ✅ Use the status filter on the list endpoint to find stale batches
  • ✅ Set up monitoring to alert on batches stuck in building status

Best Practices

Batch Organization

  • ✅ Use meaningful labels (e.g., "March 2026 Payroll", "Vendor Payments Q1")
  • ✅ Use idempotency keys to prevent duplicate batches on retries
  • ✅ Store metadata for your own tracking (department, period, run ID)

Payment Management

  • ✅ Use unique idempotency keys per payment (e.g., "payroll-2026-03-employee-{id}")
  • ✅ Verify all recipients and profiles are active before creating the batch
  • ✅ Keep batches under 500 payments — split larger sets into multiple batches

Error Handling

  • ✅ Always check the 202 Accepted response before assuming processing started
  • ✅ Handle 409 Conflict gracefully — it means a concurrent request is already processing
  • ✅ Implement retry logic for failed payments in a new batch
  • ✅ Monitor batch completion via webhooks rather than polling

API Reference

For complete endpoint documentation, see:

Need Help?

  • Check the FAQ for common questions
  • Contact support at support@treasurypath.com