Batch Jobs¶
The batch API allows users to group multiple API requests into a single atomic job. If any request in the job fails, all changes made by the job are rolled back, ensuring the application is never left in a partial state.
Request Format¶
Batch jobs are submitted as a JSON object with a single top-level job key whose value describes the job to execute.
The job's actions list is used to define the HTTP requests to be processed in bulk by the API.
The following example demonstrates a job used to create two separate Grant records.
{
"job": {
"actions": [
{
"method": "POST",
"path": "/research/grants/",
"payload": {
"title": "First New Grant",
"team": 1
}
},
{
"method": "POST",
"path": "/research/grants/",
"payload": {
"title": "Second New Grant",
"team": 1
}
}
]
}
}
Entries in the actions list support the following fields:
| Field | Required | Description |
|---|---|---|
method |
Yes | The HTTP method to use (GET, POST, PUT, PATCH, DELETE). |
path |
Yes | The API endpoint path to call. |
payload |
No | A JSON object to send as the request body. |
query_params |
No | A JSON object of query parameters to append to the request URL. |
ref |
No | An alias used to reference the action's response in subsequent actions. |
Referencing Previous Actions¶
Actions can reference the response body of any previously executed requests using a reference token. This allows the output of one action — such as a newly created record's ID — to be passed as input to a later action.
To use a reference, assign a ref alias to the action whose output you want to capture.
Then use the @ref{alias.dotpath} syntax in any subsequent path, payload, or query_params value.
References support both dictionary key access and integer list indexing, allowing deep traversal into nested objects.
In the following example, a grant is created in the first step and its id is injected into the path of the second
step:
{
"job": {
"actions": [
{
"ref": "new_grant",
"method": "POST",
"path": "/research/grants/",
"payload": {
"title": "My Grant",
"team": 1
}
},
{
"method": "PATCH",
"path": "/research/grants/@ref{new_grant.id}/",
"payload": {
"title": "Updated Title"
}
}
]
}
}
Note
Actions are executed following the order in which they are defined. An action can only reference the output of previous steps in the execution order. Forward references are not supported.
Uploading Files¶
Actions can include file attachments by submitting the job as a multipart/form-data request instead of JSON.
Include the job definition as a JSON string in the job form field, and attach each file as a separate form field.
File parts can be referenced using the @file{name} syntax, where name is the multipart field name of the uploaded
file.
POST /batch/
Content-Type: multipart/form-data
job = {
"actions": [
{
"method": "POST",
"path": "/allocations/attachments/",
"payload": {
"file": "@file{upload}"
}
}
]
}
upload = <binary file content>
Dry Runs¶
Setting dry_run to true executes all actions in a job and returns their results without persisting any database
changes.
This is useful for validating a job before committing it.
{
"job": {
"dry_run": true,
"actions": [
{
"method": "POST",
"path": "/research/grants/",
"payload": {
"title": "My Grant",
"team": 1
}
}
]
}
}
Response Format¶
A successful job returns a 200 status code with a results array containing one entry per executed step.
For example:
{
"results": [
{
"ref": "new_grant",
"index": 1,
"method": "POST",
"path": "/research/grants/",
"status": 201,
"body": {
"id": 42,
"title": "My Grant",
"team": 1
}
}
]
}
Each result contains the following fields:
| Field | Description |
|---|---|
ref |
The actions's alias, or null if none was provided. |
index |
The one-based position of the step within the job. |
method |
The HTTP method executed. |
path |
The resolved path that was called, after any @ref tokens were substituted. |
status |
The HTTP status code returned by the step. |
body |
The response body returned by the step. |
Step Failure¶
If any action encounters an error, the job halts immediately and all changes are rolled back.
In this case the API will return a 422 error along with a description of the failing step.
For example:
{
"detail": "Step #2 (POST /research/grants/) failed with status 400",
"step": 2,
"status": 400,
"body": {
"title": [
"This field is required."
]
}
}
Reference Resolution Failure¶
If a @ref or @file token cannot be resolved — for example because the alias is undefined, the dotpath is
invalid, or a referenced file part was not uploaded — the job halts and a 422 error is returned:
{
"detail": "Cannot resolve reference \"@ref{missing_alias.id}\": Alias \"missing_alias\" has not been defined by a previous step",
"token": "@ref{missing_alias.id}"
}