Use POST /ingest/batch for bulk writes. Single events can continue to use POST /ingest. Both use your bearer API key; batching requires per-item idempotency keys, not a request-level Idempotency-Key header.
Complete request
POST /ingest/batch
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json{
"items": [
{
"idempotency_key": "create-company-001",
"category": "client",
"data": {
"step": "create", "client_id": "COMPANY-001", "name": "Acme Trading",
"email": "finance@acme.example", "phone": "+15550001031",
"address": "100 Market Street", "country": "US", "is_company": true,
"registration_number": "REG-001", "contact_person": "Jane Smith"
}
},
{
"idempotency_key": "create-company-002",
"category": "client",
"data": {
"step": "create", "client_id": "COMPANY-002", "name": "Example Supply",
"email": "finance@supply.example", "phone": "+15550001032",
"address": "200 Market Street", "country": "US", "is_company": true,
"registration_number": "REG-002", "contact_person": "Alex Smith"
}
}
]
}Rules
- Send 1-100 items, all with the same category, within 1 MiB total UTF-8 body size. Each item may use its own step.
- Each
idempotency_keymust be a nonblank string of at most 255 UTF-8 bytes. Preserve keys and original values for retries. - Every item uses the same category/step payload rules and API-side money rounding as single ingestion.
- Send client batches first, then disbursements, then payments/operations. Parent existence and purchase-client membership are still enforced.
- Extra envelope/item fields are invalid. Do not include caller-generated
content_hashin data.
HTTP 200 does not mean all items succeeded
Items execute sequentially in one transaction with per-item rollback boundaries. A successful item can coexist with a failed item: this is not an all-or-nothing business batch.
results preserves input order. Each result has a status and body matching a single-ingest response. For example, a separate batch containing a client deletion followed by an invalid client item could return:
{
"results": [
{
"status": 201,
"body": {"status": "added", "action": "deleted", "id": "C-1", "idempotency_key": "delete-c1-001", "event_id": 42}
},
{
"status": 400,
"body": {"error": "Payload validation failed", "details": ["Unknown field: content_hash"]}
}
]
}Inspect every item, including 200 unchanged, 201 success, and 400/404/409/500 failures. The outer 200 only indicates that the batch returned results.
Whole-request errors
Malformed envelopes/items, empty arrays, more than 100 items, or mixed categories fail the whole request with 400 before item processing. Authentication (401), oversized body (413), readiness (503 SCHEMA_NOT_READY), or transaction-level failure (500) can also fail the whole request. A mixed-category body does not partially process the valid category.
Retry safely
- Retain item positions, original content, and keys along with the results.
- If the response is lost, resend uncertain items with their original content and keys; already stored results replay exactly.
- Correct terminally recorded failures with new keys. Never change an amount under an old key merely because it rounds to the same cents: that returns an item
409 IDEMPOTENCY_KEY_REUSED. - Split an oversized batch into smaller same-category batches while preserving each item's identity.
- Pause and contact support for readiness errors; do not reset data.
The validator accepts full batch envelopes and reports indexed item errors. It does not call the API or verify database state.
