Chain conversion, transforms, filters, optimization, OCR, metadata, document, and enhancement steps in one async workflow.
chained step execution
cross-operation orchestration
single-job multi-stage output
resize -> cinematic filter -> compress webp
metadata cleanup before OCR
document render then transform
All ImageHQ processing endpoints are asynchronous. Upon a successful POST, you receive a 202 Acceptedresponse with a job_id. Poll the status endpoint until the state reaches succeeded.
Request Example
import requests
url = "https://api.imagehq.io/v1/pipeline"
payload = {
"tool_slug": "pipeline-resize-filter-compress",
"steps": [
{
"operation": "transform",
"request": {
"operations": [
{
"type": "resize",
"width": 1600
}
]
}
},
{
"operation": "filter",
"request": {
"filters": [
{
"type": "cinematic",
"intensity": 72
}
]
}
},
{
"operation": "optimize",
"request": {
"operation": "convert_to_webp",
"input_format": "png"
}
}
]
}
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({
"tool_slug": "pipeline-resize-filter-compress",
"steps": [
{
"operation": "transform",
"request": {
"operations": [
{
"type": "resize",
"width": 1600
}
]
}
},
{
"operation": "filter",
"request": {
"filters": [
{
"type": "cinematic",
"intensity": 72
}
]
}
},
{
"operation": "optimize",
"request": {
"operation": "convert_to_webp",
"input_format": "png"
}
}
]
}));
const response = await fetch("https://api.imagehq.io/v1/pipeline", {
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({
"tool_slug": "pipeline-resize-filter-compress",
"steps": [
{
"operation": "transform",
"request": {
"operations": [
{
"type": "resize",
"width": 1600
}
]
}
},
{
"operation": "filter",
"request": {
"filters": [
{
"type": "cinematic",
"intensity": 72
}
]
}
},
{
"operation": "optimize",
"request": {
"operation": "convert_to_webp",
"input_format": "png"
}
}
]
}));
const response = await fetch("https://api.imagehq.io/v1/pipeline", {
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/pipeline" \
-H "Idempotency-Key: $(uuidgen)" \
-F "files[]=@image.png" \
-F 'request={"tool_slug":"pipeline-resize-filter-compress","steps":[{"operation":"transform","request":{"operations":[{"type":"resize","width":1600}]}},{"operation":"filter","request":{"filters":[{"type":"cinematic","intensity":72}]}},{"operation":"optimize","request":{"operation":"convert_to_webp","input_format":"png"}}]}'$client = new GuzzleHttp\Client();
$response = $client->post("https://api.imagehq.io/v1/pipeline", [
"multipart" => [
["name" => "files[]", "contents" => fopen("image.png", "r")],
["name" => "request", "contents" => '{"tool_slug":"pipeline-resize-filter-compress","steps":[{"operation":"transform","request":{"operations":[{"type":"resize","width":1600}]}},{"operation":"filter","request":{"filters":[{"type":"cinematic","intensity":72}]}},{"operation":"optimize","request":{"operation":"convert_to_webp","input_format":"png"}}]}']
]
]);require "faraday"
response = Faraday.post("https://api.imagehq.io/v1/pipeline") do |req|
req.headers["Idempotency-Key"] = SecureRandom.uuid
req.body = { "files[]" => Faraday::UploadIO.new("image.png", "image/png"), "request" => '{"tool_slug":"pipeline-resize-filter-compress","steps":[{"operation":"transform","request":{"operations":[{"type":"resize","width":1600}]}},{"operation":"filter","request":{"filters":[{"type":"cinematic","intensity":72}]}},{"operation":"optimize","request":{"operation":"convert_to_webp","input_format":"png"}}]}' }
endbody := &bytes.Buffer{}
writer := multipart.NewWriter(body)
writer.WriteField("request", `{"tool_slug":"pipeline-resize-filter-compress","steps":[{"operation":"transform","request":{"operations":[{"type":"resize","width":1600}]}},{"operation":"filter","request":{"filters":[{"type":"cinematic","intensity":72}]}},{"operation":"optimize","request":{"operation":"convert_to_webp","input_format":"png"}}]}`)
file, _ := writer.CreateFormFile("files[]", "image.png")
_ = file
writer.Close()
http.Post("https://api.imagehq.io/v1/pipeline", writer.FormDataContentType(), body)HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.imagehq.io/v1/pipeline"))
.header("Idempotency-Key", UUID.randomUUID().toString())
.POST(HttpRequest.BodyPublishers.ofString("multipart form data"))
.build();using var form = new MultipartFormDataContent();
form.Add(new StringContent('{"tool_slug":"pipeline-resize-filter-compress","steps":[{"operation":"transform","request":{"operations":[{"type":"resize","width":1600}]}},{"operation":"filter","request":{"filters":[{"type":"cinematic","intensity":72}]}},{"operation":"optimize","request":{"operation":"convert_to_webp","input_format":"png"}}]}'), "request");
form.Add(new StreamContent(File.OpenRead("image.png")), "files[]", "image.png");
await httpClient.PostAsync("https://api.imagehq.io/v1/pipeline", form);var request = URLRequest(url: URL(string: "https://api.imagehq.io/v1/pipeline")!) request.httpMethod = "POST" request.setValue(UUID().uuidString, forHTTPHeaderField: "Idempotency-Key") // Attach multipart files[] and request fields before sending.
{
"queued": {
"id": "job_123",
"status": "queued",
"operation": "pipeline",
"tool_slug": "png-to-jpg",
"client_reference_id": "example-123",
"progress": 0,
"current_stage": "queued",
"poll_url": "/v1/jobs/job_123",
"created_at": "2026-05-02T00:00:00Z",
"expires_at": "2026-05-03T00:00:00Z"
},
"completed": {
"id": "job_123",
"status": "succeeded",
"progress": 100,
"inputs": [
{
"filename": "input.png",
"format": "png",
"mime_type": "image/png",
"size_bytes": 420122
}
],
"outputs": [
{
"id": "0",
"filename": "output.jpg",
"format": "jpg",
"mime_type": "image/jpeg",
"size_bytes": 161002
}
],
"warnings": [],
"stages": [
{
"name": "queued",
"status": "succeeded",
"progress": 100
},
{
"name": "processing",
"status": "succeeded",
"progress": 100
}
],
"download_url": "/v1/jobs/job_123/download",
"retention_policy": {
"ttl_hours": 24,
"clamp": true
},
"expires_at": "2026-05-03T00:00:00Z"
}
}Pipeline applies ordered steps on the same job context; batch groups independent jobs.
Yes. Pipeline supports mixed operation types with nested request payloads.
Yes. Job responses expose stage-oriented progress states.