Batches
Bulk/related document generation jobs
How relations work
relations is an object keyed by the field name to set on the child document. Each value is either:
- a plain string
"<parentAlias>.<dotted.field.path>"— resolves against the parent's single document. Only valid when the parent'scountis1; using it against a parent withcount > 1is rejected withAMBIGUOUS_RELATIONat submit time. - or an object
{ "from": "<parentAlias>.<dotted.field.path>", "strategy": "round-robin" }— required when the parent'scount > 1; each child document is matched to a parent document by index, wrapping around (childIndex % parentCount).round-robinis the only supportedstrategyvalue today — anything else is rejected withUNSUPPORTED_STRATEGY.
Example: one customer and 3 order documents, each stamped with that customer's id:
{
"documents": [
{ "templateId": "<customerTemplateId>", "alias": "customer", "count": 1 },
{
"templateId": "<orderTemplateId>",
"alias": "order",
"count": 3,
"relations": { "customerId": { "from": "customer.id", "strategy": "round-robin" } }
}
]
}The child template body never calls a function to fetch the relation value — the batch engine injects customerId onto each generated order document after generation (overwriting it if already present).
| Method | Path | Summary |
|---|---|---|
| POST | /v1/batches | Create a batch generation job |
| GET | /v1/batches/{batchId} | Get batch status and documents |
POST
/v1/batchesCreate a batch generation job
Small batches may be executed synchronously (200 with results), larger batches are queued and executed asynchronously (202).
Request body — BatchSpec
{
"seed": 42424242,
"sequenceNamespace": "batch-2026-07-23",
"variableNamespace": "batch-2026-07-23",
"documents": [
{
"templateId": "tpl_9f3a1c2e",
"alias": "order",
"count": 3,
"params": {
"name": "Jane Doe"
}
}
]
}Responses
200Batch executed synchronously (small batches)
object
{
"batchId": "batch_7d2e4f10",
"status": "completed",
"seed": 42424242,
"results": [
{
"batchId": "batch_7d2e4f10",
"alias": "order",
"seqNo": 0,
"templateId": "tpl_9f3a1c2e",
"status": "completed",
"result": "Hello Jane Doe, order #1001",
"documentSeed": 123456789
}
]
}202Batch accepted for async processing
object
{
"batchId": "batch_7d2e4f10",
"status": "queued",
"seed": 42424242
}400Validation or template/generation error
ErrorEnvelope
{
"error": {
"code": "VALIDATION_ERROR",
"message": "\"name\" is required",
"details": {
"field": "name"
}
}
}401Missing, malformed, or invalid API key
ErrorEnvelope
{
"error": {
"code": "UNAUTHORIZED",
"message": "Missing or invalid API key",
"details": {}
}
}GET
/v1/batches/{batchId}Get batch status and documents
| Param | In | Type | Required | Description |
|---|---|---|---|---|
| batchId | path | string | Yes | — |
Responses
200Batch details
object
{
"batchId": "batch_7d2e4f10",
"tenantId": "tenant-acme-01",
"seed": 42424242,
"status": "completed",
"spec": {
"seed": 42424242,
"sequenceNamespace": "batch-2026-07-23",
"variableNamespace": "batch-2026-07-23",
"documents": [
{
"templateId": "tpl_9f3a1c2e",
"alias": "order",
"count": 3,
"params": {
"name": "Jane Doe"
}
}
]
},
"documents": [
{
"batchId": "batch_7d2e4f10",
"alias": "order",
"seqNo": 0,
"templateId": "tpl_9f3a1c2e",
"status": "completed",
"result": "Hello Jane Doe, order #1001",
"documentSeed": 123456789
}
]
}401Missing, malformed, or invalid API key
ErrorEnvelope
{
"error": {
"code": "UNAUTHORIZED",
"message": "Missing or invalid API key",
"details": {}
}
}404Resource does not exist
ErrorEnvelope
{
"error": {
"code": "NOT_FOUND",
"message": "Template tpl_missing not found",
"details": {}
}
}