POST /v1/pipeline
Image Pipeline API
Chain conversion, transforms, filters, optimization, OCR, metadata, document, and enhancement steps in one async workflow.
Opérations clés
chained step execution
cross-operation orchestration
single-job multi-stage output
Cas d’utilisation
resize -> cinematic filter -> compress webp
metadata cleanup before OCR
document render then transform
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/pipeline"
payload = {
"steps": [
{
"operation": "transform",
"request": {
"operations": [
{
"type": "resize",
"width": 1600
}
]
}
},
{
"operation": "filter",
"request": {
"filters": [
{
"intensity": 72,
"type": "cinematic"
}
]
}
},
{
"operation": "optimize",
"request": {
"input_format": "png",
"operation": "convert_to_webp"
}
}
],
"tool_slug": "pipeline-resize-filter-compress"
}
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({
"steps": [
{
"operation": "transform",
"request": {
"operations": [
{
"type": "resize",
"width": 1600
}
]
}
},
{
"operation": "filter",
"request": {
"filters": [
{
"intensity": 72,
"type": "cinematic"
}
]
}
},
{
"operation": "optimize",
"request": {
"input_format": "png",
"operation": "convert_to_webp"
}
}
],
"tool_slug": "pipeline-resize-filter-compress"
}));
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({
"steps": [
{
"operation": "transform",
"request": {
"operations": [
{
"type": "resize",
"width": 1600
}
]
}
},
{
"operation": "filter",
"request": {
"filters": [
{
"intensity": 72,
"type": "cinematic"
}
]
}
},
{
"operation": "optimize",
"request": {
"input_format": "png",
"operation": "convert_to_webp"
}
}
],
"tool_slug": "pipeline-resize-filter-compress"
}));
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={"steps":[{"operation":"transform","request":{"operations":[{"type":"resize","width":1600}]}},{"operation":"filter","request":{"filters":[{"intensity":72,"type":"cinematic"}]}},{"operation":"optimize","request":{"input_format":"png","operation":"convert_to_webp"}}],"tool_slug":"pipeline-resize-filter-compress"}'$client = new GuzzleHttp\Client();
$response = $client->post("https://api.imagehq.io/v1/pipeline", [
"multipart" => [
["name" => "files[]", "contents" => fopen("image.png", "r")],
["name" => "request", "contents" => '{"steps":[{"operation":"transform","request":{"operations":[{"type":"resize","width":1600}]}},{"operation":"filter","request":{"filters":[{"intensity":72,"type":"cinematic"}]}},{"operation":"optimize","request":{"input_format":"png","operation":"convert_to_webp"}}],"tool_slug":"pipeline-resize-filter-compress"}']
]
]);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" => '{"steps":[{"operation":"transform","request":{"operations":[{"type":"resize","width":1600}]}},{"operation":"filter","request":{"filters":[{"intensity":72,"type":"cinematic"}]}},{"operation":"optimize","request":{"input_format":"png","operation":"convert_to_webp"}}],"tool_slug":"pipeline-resize-filter-compress"}' }
endbody := &bytes.Buffer{}
writer := multipart.NewWriter(body)
writer.WriteField("request", `{"steps":[{"operation":"transform","request":{"operations":[{"type":"resize","width":1600}]}},{"operation":"filter","request":{"filters":[{"intensity":72,"type":"cinematic"}]}},{"operation":"optimize","request":{"input_format":"png","operation":"convert_to_webp"}}],"tool_slug":"pipeline-resize-filter-compress"}`)
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('{"steps":[{"operation":"transform","request":{"operations":[{"type":"resize","width":1600}]}},{"operation":"filter","request":{"filters":[{"intensity":72,"type":"cinematic"}]}},{"operation":"optimize","request":{"input_format":"png","operation":"convert_to_webp"}}],"tool_slug":"pipeline-resize-filter-compress"}'), "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.
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": "pipeline",
"poll_url": "/v1/jobs/job_123",
"progress": 0,
"status": "queued",
"tool_slug": "png-to-jpg"
}
}Questions fréquentes
How is pipeline different from batch?
Pipeline applies ordered steps on the same job context; batch groups independent jobs.
Can pipeline include OCR and metadata?
Yes. Pipeline supports mixed operation types with nested request payloads.
Do pipeline jobs emit stage progress?
Yes. Job responses expose stage-oriented progress states.