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 toPOST /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:
- Create.
POST /payments/register/batchwith anIdempotency-Keyheader and{ "payments": [ … ] }. Items that fail validation are listed inrejected; the rest are accepted. - Follow. Poll
GET /payments/register/batch/{id}, or subscribe a webhook topayment_batch.completed, untilstatusiscompleted. - Read the results. Check
result, then page throughGET /payments/register/batch/{id}/itemsfor each payment’spayment_idorerror.
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-Keyheader makes a retried request return the same batch, and each item’sidempotency_keymakes 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_completedorfailed - Polling or webhook -
GET /payments/register/batch/{id}at any time, orpayment_batch.completedwhen 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 withtransfer_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
200with 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.
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 endsduplicate, with the existing payment’spayment_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.
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 ownIdempotency-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_typestamps 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 forautomation_type: "none". - Credits. Registering a payment consumes no credit. An invoice an item’s
automation_typecreates 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
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.
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
counts fills in as items finish, and result and completed_at are set when the batch completes.
ibatch_…) answers 404 not_found.
List Batch Items
rejected.
data.data and the cursor at data.next.
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. PollGET /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:
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 onerror.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.
Related Resources
- Payments API - the single
POST /payments/register, and reading payments - Invoice Batches API - the same mechanism for income invoices
- Webhooks API -
payment_batch.completed