How to submit your first batch
This guide will walk you through submitting your first batch to the Doubleword Batch API. The Doubleword Batch API is fully compatible with the OpenAI batch endpoint, making it seamless to switch between providers.
When you submit a batch file, you're sending multiple requests to be processed in parallel. Each request is formatted as a single line in your batch file, allowing for efficient bulk processing.
Batch processing is ideal for workloads that:
- Contain multiple independent requests that can run simultaneously
- Don't require immediate responses
- Would otherwise exceed rate limits if sent individually
1. Prepare your batch file (.jsonl)
Each batch workload starts with a .jsonl file where each line contains a
single, valid API request1.
Each line in your .jsonl file must include these required fields:
custom_id: Your unique identifier for tracking the request (string, max 64 characters)method: HTTP method, always"POST"url: API endpoint, typically"/v1/chat/completions"body: The actual API request parameters (model, messages, temperature, etc.). This is the same body as your real-time request.
Here's a complete example batch file with 3 requests - including both text-only and multi-modal requests:
{"custom_id": "colorado", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "Qwen/Qwen3-VL-30B-A3B-Instruct-FP8", "messages": [{"role": "user", "content": "What is the capital of Colorado?"}]}}
{"custom_id": "image-boardwalk", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "Qwen/Qwen3-VL-30B-A3B-Instruct-FP8", "messages": [{"role": "user", "content": [{"type": "text", "text": "What is in this image?"}, {"type": "image_url", "image_url": {"url": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg"}}]}]}}
{"custom_id": "python-code", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "Qwen/Qwen3-VL-30B-A3B-Instruct-FP8", "messages": [{"role": "user", "content": "Write a Python function that calculates the fibonacci sequence."}]}}Copy the content into a file named batchinput.jsonl.
2. Upload your batch input file
Simply point the OpenAI base URL to Doubleword and include your API key2:
from openai import OpenAI
client = OpenAI(
api_key="YOUR_API_KEY",
base_url="https://api.doubleword.ai/v1"
)
batch_input_file = client.files.create(
file=open("batchinput.jsonl", "rb"),
purpose="batch"
)
print(batch_input_file)import OpenAI from "openai";
import fs from "fs";
const client = new OpenAI({
apiKey: "YOUR_API_KEY",
baseURL: "https://api.doubleword.ai/v1/"
});
const batchInputFile = await client.files.create({
file: fs.createReadStream("batchinput.jsonl"),
purpose: "batch"
});
console.log(batchInputFile);curl https://api.doubleword.ai/v1/files \
-H "Authorization: Bearer YOUR_API_KEY" \
-F purpose="batch" \
-F file="@batchinput.jsonl"The results should look like:
{"id":"09efc84c-cd4f-4ae9-a2fd-5efbc4213225", "object": "file", "bytes": 899, "created_at": 1766154501, "filename": "batchinput.jsonl", "purpose": "batch", "expires_at": 1768746501}Note the id field - we'll use it later to trigger the batch.
Files can also be uploaded via the Doubleword Console. To do so:
- Navigate to the Batches section
- If you want to dispatch the file for batch processing immediately, click the Create First Batch button. If you want to upload the file for later processing, click the files tab, and click Upload first file.
- Upload your
.jsonlfile
3. Create the Batch
Once you have uploaded the file, you can now create the batch, and set the requests in motion.
from openai import OpenAI
client = OpenAI(
api_key="YOUR_API_KEY",
base_url="https://api.doubleword.ai/v1/v1"
)
batch_input_file_id = batch_input_file.id
result = client.batches.create(
input_file_id=batch_input_file_id,
endpoint="/v1/chat/completions",
completion_window="24h",
metadata={
"description": "daily eval job"
}
)
print(result)import OpenAI from "openai";
const client = new OpenAI({
apiKey: "YOUR_API_KEY",
baseURL: "https://api.doubleword.ai/v1/v1"
});
const batchInputFileId = batchInputFile.id;
const result = await client.batches.create({
input_file_id: batchInputFileId,
endpoint: "/v1/chat/completions",
completion_window: "24h",
metadata: {
description: "daily eval job"
}
});
console.log(result);curl https://api.doubleword.ai/v1/batches \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"input_file_id": $INPUT_FILE_ID,
"endpoint": "/v1/chat/completions",
"completion_window": "24h",
"metadata": {
"description": "daily eval job"
}
}'You can set the completion window to either "24h" or "1h". "24h" gives the best price, but "1hr" means you get the results back quicker.
The API will respond with an object with information about your batch.
{
"id": "29cd13af-5ce9-487e-98ff-4eb6730c12b4",
"object": "batch",
"endpoint": "/v1/chat/completions",
"errors": null,
"input_file_id": "09efc84c-cd4f-4ae9-a2fd-5efbc4213225",
"completion_window": "24h",
"status": "validating",
"output_file_id": "b4213e44-3c85-4689-9cae-e6d986785143",
"error_file_id": "49fdc045-77a8-409b-bb3e-d661df05f9fb",
"created_at": 1714508499,
"in_progress_at": null,
"expires_at": 1714536634,
"completed_at": null,
"failed_at": null,
"expired_at": null,
"request_counts": {
"total": 0,
"completed": 0,
"failed": 0
},
"metadata": null
}The output and error file ids are populated immediately, and allow you to retrieve individual results as they become available.
Note the id, error_file_id, and output_file_id fields - we'll use them to track the progress of the batch, and download the results as they complete.
4. Tracking your batches progress
The Doubleword Console contains tools to track the completion of the requests in your batch in real time. You can view each response as requests complete, see the price of your batch over time, and view the number of completed requests.
5. Retrieving results
When a batch is triggered, the Doubleword Batch engine will create two files, an Error file, and an Output file. The identifiers for these file can be found in the response to the batch creation request. The error file contains details on any request that failed, while the output file contains all the outputs from valid requests.
These files are accessible as soon as the batch is triggered 3. To download all the completed responses for an in-progress batch, download the output or error file. If the batch is still in progress, the response headers will indicate how to resume the download from the last retrieved response.
Make sure to replace the file id with the one returned from the batch creation request!
import requests
# Download file content
url = "https://api.doubleword.ai/v1/files/b4213e44-3c85-4689-9cae-e6d986785143/content"
headers = {
"Authorization": "Bearer YOUR_API_KEY"
}
response = requests.get(url, headers=headers)
# Check if file is incomplete (batch still running)
is_incomplete = response.headers.get("X-Incomplete") == "true"
last_line = response.headers.get("X-Last-Line")
# Save to file
with open("batch-589a3368-d899-450f-8619-343a9292fa18-output.jsonl", "wb") as f:
f.write(response.content)
if is_incomplete:
print(f"Partial file downloaded (up to line {last_line})")
print(f"To resume from this point: add ?offset={last_line} to the URL")
else:
print("Complete file downloaded!")const response = await fetch(
"https://api.doubleword.ai/v1/files/cb4213e44-3c85-4689-9cae-e6d986785143/content",
{
headers: {
"Authorization": "Bearer YOUR_API_KEY"
}
}
);
// Check if file is incomplete (batch still running)
const isIncomplete = response.headers.get("X-Incomplete") === "true";
const lastLine = response.headers.get("X-Last-Line");
// Save to file
const content = await response.text();
await fs.promises.writeFile(
"batch-589a3368-d899-450f-8619-343a9292fa18-output.jsonl",
content
);
if (isIncomplete) {
console.log(`Partial file downloaded (up to line ${lastLine})`);
console.log(`To resume: add ?offset=${lastLine} to the URL`);
} else {
console.log("Complete file downloaded!");
}curl https://api.doubleword.ai/v1/files/b4213e44-3c85-4689-9cae-e6d986785143/content \
-H "Authorization: Bearer YOUR_API_KEY" \
-D headers.txt \
-o batch-output.jsonl
# Check completion status
if grep -q "X-Incomplete: true" headers.txt; then
last_line=$(grep "X-Last-Line:" headers.txt | cut -d' ' -f2 | tr -d '\r')
echo "Partial file downloaded (up to line $last_line)"
echo ""
echo "To resume, run:"
echo "curl 'https://api.doubleword.ai/v1/files/b4213e44-3c85-4689-9cae-e6d98678514/content?offset=$last_line' \\"
echo " -H 'Authorization: Bearer YOUR_API_KEY' >> batch-output.jsonl"
else
echo "Complete file downloaded!"
fi6. Cancel a batch
Batches can be cancelled.
from openai import OpenAI
client = OpenAI(
api_key="YOUR_API_KEY",
base_url="https://api.doubleword.ai/v1"
)
client.batches.cancel("29cd13af-5ce9-487e-98ff-4eb6730c12b4")import OpenAI from "openai";
const client = new OpenAI({
apiKey: "YOUR_API_KEY",
baseURL: "https://api.doubleword.ai/v1"
});
await client.batches.cancel("29cd13af-5ce9-487e-98ff-4eb6730c12b4");curl https://api.doubleword.ai/v1/batches/29cd13af-5ce9-487e-98ff-4eb6730c12b4/cancel \
-H "Authorization: Bearer YOUR_API_KEY" \
-X POSTAll requests that haven't started processing yet are immediately moved to the cancelled state 4. Requests that are successfully cancelled are not charged.
7. Get a list of all batches
You can see all of your batches by calling the list batches endpoint.
from openai import OpenAI
client = OpenAI(
api_key="YOUR_API_KEY",
base_url="https://api.doubleword.ai/v1"
)
client.batches.list(limit=10)import OpenAI from "openai";
const client = new OpenAI({
apiKey: "YOUR_API_KEY",
baseURL: "https://api.doubleword.ai/v1"
});
const list = await openai.batches.list();
for await (const batch of list) {
console.log(batch);
}curl https://api.openai.com/v1/batches?limit=10 \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json"What next?
After reading this guide, you should be able to submit batches to the Doubleword API, track their progress, and download their results.
For any issues you encounter while using the API, please contact us.
Footnotes
-
To understand what a jsonl file is and how to create one, check out our JSONL Files guide. ↩
-
To generate an API key for use with the Doubleword API, navigate to the API keys page in the console. ↩
-
This is different from the openAI API, in which you must wait for your whole batch to complete before you can retrieve your results. ↩
-
Requests in flight are cancelled on a best-effort basis. ↩