curl --request GET \
--url https://api.infery.ai/v1/workflows/runs/{id} \
--header 'Authorization: <api-key>'import requests
url = "https://api.infery.ai/v1/workflows/runs/{id}"
headers = {"Authorization": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: '<api-key>'}};
fetch('https://api.infery.ai/v1/workflows/runs/{id}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.infery.ai/v1/workflows/runs/{id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.infery.ai/v1/workflows/runs/{id}"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.infery.ai/v1/workflows/runs/{id}")
.header("Authorization", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.infery.ai/v1/workflows/runs/{id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"id": "3c9a7e51-8b24-4f0d-9a17-6e2b5c4d8a03",
"status": "succeeded",
"attempt": 1,
"maxAttempts": 1,
"creditsUsed": 4.128,
"stepRuns": [
{
"id": "summarise",
"type": "model",
"status": "succeeded",
"childRunIds": [],
"creditsUsed": 1.284,
"durationMs": 2143,
"attempt": 1,
"output": "<string>",
"outputRef": "gs://infery-prod-media/workspaces/7d1c.../pipeline-artifacts/9f2b....png",
"error": {
"code": "model_call_failed",
"message": "upstream provider returned 502"
},
"skippedReason": "condition_false"
}
],
"durationMs": 8421,
"createdAt": "2026-05-04T09:15:22.113Z",
"input": {},
"output": {},
"error": {
"code": "model_call_failed",
"message": "upstream provider returned 502",
"stepId": "summarise"
}
}{
"error": {
"message": "Model not found",
"type": "invalid_request_error",
"code": "model_not_found",
"param": "model",
"job_id": "job_1hR9xTPZqK4mVLc2nJ7fY5wB"
}
}{
"error": {
"message": "Model not found",
"type": "invalid_request_error",
"code": "model_not_found",
"param": "model",
"job_id": "job_1hR9xTPZqK4mVLc2nJ7fY5wB"
}
}Retrieve a run
GET /v1/workflows/runs/
curl --request GET \
--url https://api.infery.ai/v1/workflows/runs/{id} \
--header 'Authorization: <api-key>'import requests
url = "https://api.infery.ai/v1/workflows/runs/{id}"
headers = {"Authorization": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: '<api-key>'}};
fetch('https://api.infery.ai/v1/workflows/runs/{id}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.infery.ai/v1/workflows/runs/{id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.infery.ai/v1/workflows/runs/{id}"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.infery.ai/v1/workflows/runs/{id}")
.header("Authorization", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.infery.ai/v1/workflows/runs/{id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"id": "3c9a7e51-8b24-4f0d-9a17-6e2b5c4d8a03",
"status": "succeeded",
"attempt": 1,
"maxAttempts": 1,
"creditsUsed": 4.128,
"stepRuns": [
{
"id": "summarise",
"type": "model",
"status": "succeeded",
"childRunIds": [],
"creditsUsed": 1.284,
"durationMs": 2143,
"attempt": 1,
"output": "<string>",
"outputRef": "gs://infery-prod-media/workspaces/7d1c.../pipeline-artifacts/9f2b....png",
"error": {
"code": "model_call_failed",
"message": "upstream provider returned 502"
},
"skippedReason": "condition_false"
}
],
"durationMs": 8421,
"createdAt": "2026-05-04T09:15:22.113Z",
"input": {},
"output": {},
"error": {
"code": "model_call_failed",
"message": "upstream provider returned 502",
"stepId": "summarise"
}
}{
"error": {
"message": "Model not found",
"type": "invalid_request_error",
"code": "model_not_found",
"param": "model",
"job_id": "job_1hR9xTPZqK4mVLc2nJ7fY5wB"
}
}{
"error": {
"message": "Model not found",
"type": "invalid_request_error",
"code": "model_not_found",
"param": "model",
"job_id": "job_1hR9xTPZqK4mVLc2nJ7fY5wB"
}
}mode: "async". A run that is still going reports queued or running; the step list fills in as it goes, so this doubles as progress.Authorizations
API key in format: Bearer inf_***
Path Parameters
Run UUID.
"3c9a7e51-8b24-4f0d-9a17-6e2b5c4d8a03"
Response
The run, its steps, and what it cost.
Run UUID.
"3c9a7e51-8b24-4f0d-9a17-6e2b5c4d8a03"
Terminal statuses are succeeded, failed and cancelled. queued/running are only ever seen by reading a run that has not finished. partial exists in the enum and no writer in this repo produces it — do not build on it.
queued, running, succeeded, failed, cancelled, partial "succeeded"
Current run-level attempt, 1-based. Only an async run can exceed 1; sync and stream runs never retry at the run level.
1
Run-level attempts configured, from the definition's retry.max_attempts clamped to 1..5. 1 for sync and stream runs.
1
Credits actually settled for this run, summed from the per-step settles. This is real money spent — it is NOT the estimate, and it is not capped by one: POST /v1/workflows/estimate is a quote, and the credits_reserved figure the run row carries is written but read by nothing.
4.128
One entry per step ATTEMPT. Ordered by step id then attempt on GET /v1/workflows/runs/{id} — LEXICOGRAPHIC, not execution order — while a fresh sync run returns them in the order the runner executed them. Reading a run that is still running returns the steps written so far, including ones still running themselves.
Show child attributes
Show child attributes
Wall-clock duration of the run in milliseconds. 0 when the row never recorded one.
8421
ISO-8601 timestamp the run was created.
"2026-05-04T09:15:22.113Z"
The input the run was given, AFTER declared defaults were applied. Returned by GET /v1/workflows/runs/{id} and by an idempotent replay; ABSENT from the response of a fresh sync run, which is built from the runner's result rather than the row. {} is a real answer (the workflow declares inputs and the caller sent none) — the field is omitted, never null, when there is nothing.
The run's output, resolved from the definition's output block against the steps' results. Absent for a run that failed or was cancelled before producing one.
Present only for a failed run. A cancelled run carries no error.
Show child attributes
Show child attributes