POST /v1/batch
Image Batch API
Run multiple independent image jobs in one parent request and return grouped outputs.
Opérations clés
independent child jobs
grouped async dispatch
aggregate output packaging
Cas d’utilisation
convert one file, filter another, OCR another
bulk multi-tool orchestration
group download workflows
Cycle de vie de la tâche async
Tous les endpoints de traitement ImageHQ sont asynchrones. Après un POST réussi, vous recevez une réponse 202 Acceptedavec un job_id. Interrogez l’endpoint de statut jusqu’à ce que l’état atteigne succeeded.
Exemple de requête
import requests
url = "https://api.imagehq.io/v1/batch"
payload = {
"jobs": [
{
"operation": "convert",
"request": {
"input_format": "png",
"output_format": "jpg",
"tool_slug": "png-to-jpg"
}
},
{
"operation": "filter",
"request": {
"filters": [
{
"intensity": 70,
"type": "warm_film"
}
],
"tool_slug": "warm-film-filter"
}
},
{
"operation": "ocr",
"request": {
"operation": "extract_text",
"options": {
"language": "eng"
},
"tool_slug": "image-to-text"
}
}
],
"tool_slug": "batch-mixed-ops"
}
files = [("files[]", open("image.png", "rb"))]
data = {"request": json.dumps(payload)}
response = requests.post(url, files=files, data=data)
print(response.json())const form = new FormData();
form.append("files[]", file);
form.append("request", JSON.stringify({
"jobs": [
{
"operation": "convert",
"request": {
"input_format": "png",
"output_format": "jpg",
"tool_slug": "png-to-jpg"
}
},
{
"operation": "filter",
"request": {
"filters": [
{
"intensity": 70,
"type": "warm_film"
}
],
"tool_slug": "warm-film-filter"
}
},
{
"operation": "ocr",
"request": {
"operation": "extract_text",
"options": {
"language": "eng"
},
"tool_slug": "image-to-text"
}
}
],
"tool_slug": "batch-mixed-ops"
}));
const response = await fetch("https://api.imagehq.io/v1/batch", {
method: "POST",
headers: { "Idempotency-Key": crypto.randomUUID() },
body: form
});
const data = await response.json();
console.log(data);const form = new FormData();
form.append("files[]", file);
form.append("request", JSON.stringify({
"jobs": [
{
"operation": "convert",
"request": {
"input_format": "png",
"output_format": "jpg",
"tool_slug": "png-to-jpg"
}
},
{
"operation": "filter",
"request": {
"filters": [
{
"intensity": 70,
"type": "warm_film"
}
],
"tool_slug": "warm-film-filter"
}
},
{
"operation": "ocr",
"request": {
"operation": "extract_text",
"options": {
"language": "eng"
},
"tool_slug": "image-to-text"
}
}
],
"tool_slug": "batch-mixed-ops"
}));
const response = await fetch("https://api.imagehq.io/v1/batch", {
method: "POST",
headers: { "Idempotency-Key": crypto.randomUUID() },
body: form
});
const data = await response.json();
console.log(data);curl -X POST "https://api.imagehq.io/v1/batch" \
-H "Idempotency-Key: $(uuidgen)" \
-F "files[]=@image.png" \
-F 'request={"jobs":[{"operation":"convert","request":{"input_format":"png","output_format":"jpg","tool_slug":"png-to-jpg"}},{"operation":"filter","request":{"filters":[{"intensity":70,"type":"warm_film"}],"tool_slug":"warm-film-filter"}},{"operation":"ocr","request":{"operation":"extract_text","options":{"language":"eng"},"tool_slug":"image-to-text"}}],"tool_slug":"batch-mixed-ops"}'$client = new GuzzleHttp\Client();
$response = $client->post("https://api.imagehq.io/v1/batch", [
"multipart" => [
["name" => "files[]", "contents" => fopen("image.png", "r")],
["name" => "request", "contents" => '{"jobs":[{"operation":"convert","request":{"input_format":"png","output_format":"jpg","tool_slug":"png-to-jpg"}},{"operation":"filter","request":{"filters":[{"intensity":70,"type":"warm_film"}],"tool_slug":"warm-film-filter"}},{"operation":"ocr","request":{"operation":"extract_text","options":{"language":"eng"},"tool_slug":"image-to-text"}}],"tool_slug":"batch-mixed-ops"}']
]
]);require "faraday"
response = Faraday.post("https://api.imagehq.io/v1/batch") do |req|
req.headers["Idempotency-Key"] = SecureRandom.uuid
req.body = { "files[]" => Faraday::UploadIO.new("image.png", "image/png"), "request" => '{"jobs":[{"operation":"convert","request":{"input_format":"png","output_format":"jpg","tool_slug":"png-to-jpg"}},{"operation":"filter","request":{"filters":[{"intensity":70,"type":"warm_film"}],"tool_slug":"warm-film-filter"}},{"operation":"ocr","request":{"operation":"extract_text","options":{"language":"eng"},"tool_slug":"image-to-text"}}],"tool_slug":"batch-mixed-ops"}' }
endbody := &bytes.Buffer{}
writer := multipart.NewWriter(body)
writer.WriteField("request", `{"jobs":[{"operation":"convert","request":{"input_format":"png","output_format":"jpg","tool_slug":"png-to-jpg"}},{"operation":"filter","request":{"filters":[{"intensity":70,"type":"warm_film"}],"tool_slug":"warm-film-filter"}},{"operation":"ocr","request":{"operation":"extract_text","options":{"language":"eng"},"tool_slug":"image-to-text"}}],"tool_slug":"batch-mixed-ops"}`)
file, _ := writer.CreateFormFile("files[]", "image.png")
_ = file
writer.Close()
http.Post("https://api.imagehq.io/v1/batch", writer.FormDataContentType(), body)HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.imagehq.io/v1/batch"))
.header("Idempotency-Key", UUID.randomUUID().toString())
.POST(HttpRequest.BodyPublishers.ofString("multipart form data"))
.build();using var form = new MultipartFormDataContent();
form.Add(new StringContent('{"jobs":[{"operation":"convert","request":{"input_format":"png","output_format":"jpg","tool_slug":"png-to-jpg"}},{"operation":"filter","request":{"filters":[{"intensity":70,"type":"warm_film"}],"tool_slug":"warm-film-filter"}},{"operation":"ocr","request":{"operation":"extract_text","options":{"language":"eng"},"tool_slug":"image-to-text"}}],"tool_slug":"batch-mixed-ops"}'), "request");
form.Add(new StreamContent(File.OpenRead("image.png")), "files[]", "image.png");
await httpClient.PostAsync("https://api.imagehq.io/v1/batch", form);var request = URLRequest(url: URL(string: "https://api.imagehq.io/v1/batch")!) request.httpMethod = "POST" request.setValue(UUID().uuidString, forHTTPHeaderField: "Idempotency-Key") // Attach multipart files[] and request fields before sending.
Réponse réussie
{
"completed": {
"download_url": "/v1/jobs/job_123/download",
"expires_at": "2026-05-03T00:00:00Z",
"id": "job_123",
"inputs": [
{
"filename": "input.png",
"format": "png",
"mime_type": "image/png",
"size_bytes": 420122
}
],
"outputs": [
{
"filename": "output.jpg",
"format": "jpg",
"id": "0",
"mime_type": "image/jpeg",
"size_bytes": 161002
}
],
"progress": 100,
"retention_policy": {
"clamp": true,
"ttl_hours": 24
},
"stages": [
{
"name": "queued",
"progress": 100,
"status": "succeeded"
},
{
"name": "processing",
"progress": 100,
"status": "succeeded"
}
],
"status": "succeeded",
"warnings": []
},
"queued": {
"client_reference_id": "example-123",
"created_at": "2026-05-02T00:00:00Z",
"current_stage": "queued",
"expires_at": "2026-05-03T00:00:00Z",
"id": "job_123",
"operation": "batch",
"poll_url": "/v1/jobs/job_123",
"progress": 0,
"status": "queued",
"tool_slug": "png-to-jpg"
}
}Questions fréquentes
How is batch different from pipeline?
Batch runs independent child operations, while pipeline chains operations together.
Can I mix endpoint types in batch?
Yes. Convert, filter, OCR, and other supported operations can coexist in a single batch.
Can batch outputs be zipped?
Use output archive options where supported to package grouped outputs.