Skip to main content

Overview

A payment batch registers up to 10,000 payments that you have already received from a single request. Each item of the batch is exactly the body you would send to POST /payments/register. gigstack validates every item right away, answers 202 with the batch, and registers the accepted items in the background, with the same automations a single call runs (automation_type, ppd_invoice_id). Use it when you reconcile many payments at once: a day’s bank statement, a settlement file from a processor gigstack does not connect to, or a backlog after an outage. Base path: https://api.gigstack.io/v2/payments/register/batch A batch goes through three steps:
  1. Create. POST /payments/register/batch with an Idempotency-Key header and { "payments": [ … ] }. Items that fail validation are listed in rejected; the rest are accepted.
  2. Follow. Poll GET /payments/register/batch/{id}, or subscribe a webhook to payment_batch.completed, until status is completed.
  3. Read the results. Check result, then page through GET /payments/register/batch/{id}/items for each payment’s payment_id or error.
It works like an income invoice batch: same request shape, same two levels of idempotency, same status and result vocabulary. This guide repeats what you need and points there for the rest.

Key Features

  • Up to 10,000 payments per request - send more requests for more (see Limits)
  • The single endpoint’s rules, unchanged - each item is validated and registered by the same code as POST /payments/register, so it succeeds or fails exactly as a single call would, and triggers the same invoice automations
  • Item-level rejections - an invalid item is rejected with a reason, and the other items still go ahead
  • Safe retries at two levels - the Idempotency-Key header makes a retried request return the same batch, and each item’s idempotency_key makes sure a payment is never registered twice (see Idempotency)
  • Automatic retries - an item that hits a temporary failure is retried by gigstack, up to 6 attempts
  • A clear outcome - a finished batch reports result: completed, partially_completed or failed
  • Polling or webhook - GET /payments/register/batch/{id} at any time, or payment_batch.completed when it finishes

When to Use It

Not supported by batches:
  • File uploads (CSV/XLSX). The batch takes JSON only. For a spreadsheet, see the Google Sheets import in the dashboard.
  • Split payments (transfer_data). The item is rejected with transfer_data_not_supported.
  • Payment requests, refunds and marking a request as paid. Those stay single calls.

Idempotency

A batch uses two keys, and they protect different things.

The batch key (Idempotency-Key header)

8-128 characters from A-Z a-z 0-9 . _ : -. The batch id is derived from your team, the credential’s mode and this key, so:
  • The same key with the same body answers 200 with the batch the first request created. Nothing is created again.
  • The same key with a different body answers 409 idempotency_key_reused. Nothing is created. Use a new key.
  • Bodies are compared as sent, including key order, so resend the exact same JSON.
So if a POST times out or answers 500, send it again unchanged with the same key. An invoice batch created under the same key is a different batch (ibatch_… against pbatch_…); the two never collide.

The payment key (idempotency_key in each item)

This is the same idempotency_key that POST /payments/register accepts, for example your transaction or order id. It must be present in every item and unique within the batch (up to 256 characters; surrounding spaces are trimmed).
  • A payment already registered under the key, by an earlier batch or by a single POST /payments/register, is not registered again. The item ends duplicate, with the existing payment’s payment_id.
  • A failure that keeps the item from being registered (a client that does not resolve, a date in the future) leaves the key free, so you can fix the data and send the payment again under the same key.
This is what makes it safe to send a new batch with the items that failed, or even to resend a whole batch under a new Idempotency-Key: everything already registered comes back as duplicate. Keys are scoped to your team and to the credential’s mode.

Limits

  • 10,000 payments per request. More is 400 too_many_items. For 15,000 payments, send two batches, each with its own Idempotency-Key. There is no limit on the number of batches.
  • Body size. Keep the JSON body under 20 MB. A payment with an embedded client is about 1 KB, so 10,000 of them are a few MB.
  • Throughput. A team’s items run about 10 at a time across all its batches, invoice batches included, so several batches from one team don’t go faster than one. A payment registers in well under a second. After a payment whose automation_type stamps an invoice (or that settles a PPD invoice), the worker pauses about a second so the stamping that follows arrives at a few per second: expect roughly 25,000 such payments an hour, and several times that for automation_type: "none".
  • Credits. Registering a payment consumes no credit. An invoice an item’s automation_type creates is charged as it would be for a single call.

Batch Status

A batch whose items were all rejected up front has nothing to do. It completes at once, usually already in the 202 response, with result: "failed", and still sends payment_batch.completed.

Batch Result

status: "completed" only means there is nothing left to do. To know how it went, read result, not status. It is null while the batch is processing.

Item Status

Endpoints

Create a Batch

Headers: Body: { "payments": [ … ] }, 1 to 10,000 items. Each item is the POST /payments/register body with a required idempotency_key. livemode, team and owner in an item are ignored; they come from the credential.
Response (202):
A retry with the same Idempotency-Key and body answers 200 with the same batch, as it is now.

Rejected items

Each item is checked on its own when the batch is created, with no lookups. A rejected item is never registered, and doesn’t stop the others. index is its position in payments, from 0. What needs the database (a client or service id that doesn’t exist, an exchange rate for the payment date) can’t be known up front. Those items are accepted and end failed.

Get a Batch

Returns the batch in the same shape as the create response. counts fills in as items finish, and result and completed_at are set when the batch completes.
A finished batch in which one payment failed:
A batch of another team, of the other mode (a live batch read with a test key), or an invoice batch (ibatch_…) answers 404 not_found.

List Batch Items

One entry per accepted item, in request order. Rejected items aren’t listed; they are in the batch’s rejected.
Response (200): the array is at data.data and the cursor at data.next.
Pass data.next back as next while data.has_more is true. The cursor is the last index of the page, so pages never overlap or skip items while statuses change.

Item errors

error is set only on failed items. Its code is what POST /payments/register would have answered for the same body (invalid_request_body for a date in the future or a missing exchange rate, validation_failed for a client or service that doesn’t resolve, …). Batches add a few of their own: message is at most 500 characters. Finding the payments. payment_id reads the payment with GET /payments/{id}; the invoice an item’s automation created is on the payment’s invoices. You can also find a payment by your own key with GET /payments/search.

Following Progress

Polling. Poll GET /payments/register/batch/{id} every 30-60 seconds. counts.queued goes down to 0 as items finish; the batch is done when status is completed. Webhook. Subscribe a webhook to payment_batch.completed. It is sent once, when the batch completes, and carries the batch id, its counts and its result:
The delivery is signed with the webhook’s secret (see Verifying Signatures), but it is sent only once and never retried. If your endpoint is down at that moment, you miss it. Use the webhook to react quickly, and keep a slow poll (for example every 10 minutes) as a fallback. Note that data.rejected is a count here, while on the batch object rejected is the list. Each payment the batch registers also sends the usual payment.created and payment.succeeded events, like any other registered payment, and an invoice created by its automation sends invoice.created.

Response Objects

Batch

Item

Error Handling

The batch endpoints use the standardized envelope. Branch on error.code, not on the message. Authentication failures (401, and the 403 for a revoked key or a plan without API access) come from the authentication layer with a raw { "message": … } body; see Authentication errors.