curl "https://api.u1.archetypeai.app/v0.5/batch/jobs/job_2abc3def4ghi5jkl6mno7pqr/inputs/progress?status=processing&status=pending&order=desc&limit=20" \
-H "Authorization: Bearer $ATAI_API_KEY"
import requests
import os
api_key = os.environ.get("ATAI_API_KEY")
job_id = "job_2abc3def4ghi5jkl6mno7pqr"
response = requests.get(
f"https://api.u1.archetypeai.app/v0.5/batch/jobs/{job_id}/inputs/progress",
headers={"Authorization": f"Bearer {api_key}"},
params=[
("status", "processing"),
("status", "pending"),
("order", "desc"),
("limit", 20),
],
)
data = response.json()
for item in data["data"]:
inp = item["input"]
progress = item.get("latest_progress")
pct = progress["metrics"].get("percent_complete") if progress else None
print(f" {inp['id']} [{inp['status']}] step={item.get('step')} progress={pct}")
# Pass the cursor back verbatim as `after` to fetch the next page.
if data["has_more"]:
print(f"Next page cursor: {data['next_cursor']}")
const jobId = 'job_2abc3def4ghi5jkl6mno7pqr';
const params = new URLSearchParams();
params.append('status', 'processing');
params.append('status', 'pending');
params.append('order', 'desc');
params.append('limit', '20');
const response = await fetch(`https://api.u1.archetypeai.app/v0.5/batch/jobs/${jobId}/inputs/progress?${params}`, {
headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` }
});
const data = await response.json();
data.data.forEach(({ input, latest_progress, step }) => {
const pct = latest_progress?.metrics?.percent_complete ?? null;
console.log(` ${input.id} [${input.status}] step=${step} progress=${pct}`);
});
if (data.has_more) {
console.log(`Next page cursor: ${data.next_cursor}`);
}
{
"job_id": "job_2abc3def4ghi5jkl6mno7pqr",
"data": [
{
"input": {
"id": "inp_abc123def456",
"job_id": "job_2abc3def4ghi5jkl6mno7pqr",
"port_name": "worker.inference",
"file_id": "file_abc123",
"data": {
"ref": "https://storage.example.com/files/tep_inference.csv",
"filename": "tep_inference.csv",
"file_type": "text/csv",
"file_extension": ".csv",
"num_bytes": 245760,
"metadata": {}
},
"status": "processing",
"error_message": null,
"created_at": "2026-04-14T10:00:00Z",
"completed_at": null
},
"latest_progress": {
"id": 502,
"kind": "inference",
"step": 5,
"metrics": {
"percent_complete": 50,
"items_processed": 5,
"items_total": 10
},
"payload": {},
"input_id": "inp_abc123def456",
"index": 0,
"message": "Processing input 5 of 10",
"created_at": "2026-04-14T10:06:00Z"
},
"step": null
}
],
"has_more": true,
"next_cursor": "<opaque-cursor>",
"prev_cursor": null
}
{
"code": "...",
"message": "...",
"error_uid": "err_abc123"
}
{
"code": "NOT_FOUND",
"message": "Job not found",
"error_uid": "err_abc123"
}
{
"detail": "Invalid access with key: api_key_not_found"
}
I/O
List Inputs With Progress
Tracked inputs paired with their latest progress entry
GET
/
batch
/
jobs
/
{id}
/
inputs
/
progress
curl "https://api.u1.archetypeai.app/v0.5/batch/jobs/job_2abc3def4ghi5jkl6mno7pqr/inputs/progress?status=processing&status=pending&order=desc&limit=20" \
-H "Authorization: Bearer $ATAI_API_KEY"
import requests
import os
api_key = os.environ.get("ATAI_API_KEY")
job_id = "job_2abc3def4ghi5jkl6mno7pqr"
response = requests.get(
f"https://api.u1.archetypeai.app/v0.5/batch/jobs/{job_id}/inputs/progress",
headers={"Authorization": f"Bearer {api_key}"},
params=[
("status", "processing"),
("status", "pending"),
("order", "desc"),
("limit", 20),
],
)
data = response.json()
for item in data["data"]:
inp = item["input"]
progress = item.get("latest_progress")
pct = progress["metrics"].get("percent_complete") if progress else None
print(f" {inp['id']} [{inp['status']}] step={item.get('step')} progress={pct}")
# Pass the cursor back verbatim as `after` to fetch the next page.
if data["has_more"]:
print(f"Next page cursor: {data['next_cursor']}")
const jobId = 'job_2abc3def4ghi5jkl6mno7pqr';
const params = new URLSearchParams();
params.append('status', 'processing');
params.append('status', 'pending');
params.append('order', 'desc');
params.append('limit', '20');
const response = await fetch(`https://api.u1.archetypeai.app/v0.5/batch/jobs/${jobId}/inputs/progress?${params}`, {
headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` }
});
const data = await response.json();
data.data.forEach(({ input, latest_progress, step }) => {
const pct = latest_progress?.metrics?.percent_complete ?? null;
console.log(` ${input.id} [${input.status}] step=${step} progress=${pct}`);
});
if (data.has_more) {
console.log(`Next page cursor: ${data.next_cursor}`);
}
{
"job_id": "job_2abc3def4ghi5jkl6mno7pqr",
"data": [
{
"input": {
"id": "inp_abc123def456",
"job_id": "job_2abc3def4ghi5jkl6mno7pqr",
"port_name": "worker.inference",
"file_id": "file_abc123",
"data": {
"ref": "https://storage.example.com/files/tep_inference.csv",
"filename": "tep_inference.csv",
"file_type": "text/csv",
"file_extension": ".csv",
"num_bytes": 245760,
"metadata": {}
},
"status": "processing",
"error_message": null,
"created_at": "2026-04-14T10:00:00Z",
"completed_at": null
},
"latest_progress": {
"id": 502,
"kind": "inference",
"step": 5,
"metrics": {
"percent_complete": 50,
"items_processed": 5,
"items_total": 10
},
"payload": {},
"input_id": "inp_abc123def456",
"index": 0,
"message": "Processing input 5 of 10",
"created_at": "2026-04-14T10:06:00Z"
},
"step": null
}
],
"has_more": true,
"next_cursor": "<opaque-cursor>",
"prev_cursor": null
}
{
"code": "...",
"message": "...",
"error_uid": "err_abc123"
}
{
"code": "NOT_FOUND",
"message": "Job not found",
"error_uid": "err_abc123"
}
{
"detail": "Invalid access with key: api_key_not_found"
}
Requires version 1.1.0 or later of the Archetype platform.
Overview
This endpoint returns tracked inputs for a job, each paired with its most recentjob_progress
row (if any). Use it to drive per-input progress UIs without N+1 fetches against the progress
endpoint. Inputs attached to non-tracked ports (e.g. n-shot reference files) are always
excluded.
The page is cursor-paginated and comes back in display order: processing inputs first, then
pending, then finished (completed/failed) ones, each group sorted by its activity time in
the direction order gives. Unlike the other batch lists, this order is not newest first.
Request
string
required
The unique job identifier
string
Scope results to a single input port (e.g.
worker.inference)array
Statuses to include. Repeat this parameter to specify several statuses to filter on
(
?status=pending&status=processing). Accepts pending, processing, completed, and
failed. The reference status is always excluded.string
Sort direction within each status bucket.
asc (the default) puts the oldest first; desc puts
the most recently active inputs at the top. A cursor marks a position in the list and stays
valid under either direction.integer
default:"100"
Page size, between
1 and 1000. Clamped server-side.string
Forward cursor: return the inputs that follow this page’s last input in the display order.
This value is opaque and doesn’t correspond to any identifier you can rely upon. Instead, pass
the previous page’s
next_cursor back verbatim. This parameter is mutually exclusive with
before; including both returns an HTTP 400 error. A malformed cursor also returns 400. v1.1.11+string
Backward cursor: return the inputs that precede this page’s first input in the display order.
Just like
after, this parameter’s value is opaque and doesn’t correspond reliably to a
specific input. This parameter is mutually exclusive with after. v1.1.11+Response
string
The job identifier
array
Array of
InputWithLatestProgress objects, in the display order described above in both cursor
directions, each containing:input— TheInputResponse(same shape as the response for List Inputs)latest_progress— The most recentjob_progressrow for this input, ornullif none yetstep— 1-indexed completion rank across the whole job, ordered bycompleted_at.nullfor inputs still inpendingorprocessing— assigned only when the input reachescompletedorfailed. Ties (samecompleted_at) are broken by input id. Distinct fromlatest_progress.step, which is the container-reported training/inference step inside a single input.
string
Cursor for the next page in the same direction — pass it as
after when paging forward, or as
before when the request used before. null when has_more is false. v1.1.11+string
Cursor to step back the way this page was reached — pass it as
before after a forward page, or
as after after a backward one. null when the request carried no cursor. v1.1.11+curl "https://api.u1.archetypeai.app/v0.5/batch/jobs/job_2abc3def4ghi5jkl6mno7pqr/inputs/progress?status=processing&status=pending&order=desc&limit=20" \
-H "Authorization: Bearer $ATAI_API_KEY"
import requests
import os
api_key = os.environ.get("ATAI_API_KEY")
job_id = "job_2abc3def4ghi5jkl6mno7pqr"
response = requests.get(
f"https://api.u1.archetypeai.app/v0.5/batch/jobs/{job_id}/inputs/progress",
headers={"Authorization": f"Bearer {api_key}"},
params=[
("status", "processing"),
("status", "pending"),
("order", "desc"),
("limit", 20),
],
)
data = response.json()
for item in data["data"]:
inp = item["input"]
progress = item.get("latest_progress")
pct = progress["metrics"].get("percent_complete") if progress else None
print(f" {inp['id']} [{inp['status']}] step={item.get('step')} progress={pct}")
# Pass the cursor back verbatim as `after` to fetch the next page.
if data["has_more"]:
print(f"Next page cursor: {data['next_cursor']}")
const jobId = 'job_2abc3def4ghi5jkl6mno7pqr';
const params = new URLSearchParams();
params.append('status', 'processing');
params.append('status', 'pending');
params.append('order', 'desc');
params.append('limit', '20');
const response = await fetch(`https://api.u1.archetypeai.app/v0.5/batch/jobs/${jobId}/inputs/progress?${params}`, {
headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` }
});
const data = await response.json();
data.data.forEach(({ input, latest_progress, step }) => {
const pct = latest_progress?.metrics?.percent_complete ?? null;
console.log(` ${input.id} [${input.status}] step=${step} progress=${pct}`);
});
if (data.has_more) {
console.log(`Next page cursor: ${data.next_cursor}`);
}
{
"job_id": "job_2abc3def4ghi5jkl6mno7pqr",
"data": [
{
"input": {
"id": "inp_abc123def456",
"job_id": "job_2abc3def4ghi5jkl6mno7pqr",
"port_name": "worker.inference",
"file_id": "file_abc123",
"data": {
"ref": "https://storage.example.com/files/tep_inference.csv",
"filename": "tep_inference.csv",
"file_type": "text/csv",
"file_extension": ".csv",
"num_bytes": 245760,
"metadata": {}
},
"status": "processing",
"error_message": null,
"created_at": "2026-04-14T10:00:00Z",
"completed_at": null
},
"latest_progress": {
"id": 502,
"kind": "inference",
"step": 5,
"metrics": {
"percent_complete": 50,
"items_processed": 5,
"items_total": 10
},
"payload": {},
"input_id": "inp_abc123def456",
"index": 0,
"message": "Processing input 5 of 10",
"created_at": "2026-04-14T10:06:00Z"
},
"step": null
}
],
"has_more": true,
"next_cursor": "<opaque-cursor>",
"prev_cursor": null
}
{
"code": "...",
"message": "...",
"error_uid": "err_abc123"
}
{
"code": "NOT_FOUND",
"message": "Job not found",
"error_uid": "err_abc123"
}
{
"detail": "Invalid access with key: api_key_not_found"
}
The cursor is a snapshot of the position it was issued at, so an input that changes status
between two page requests is neither skipped nor repeated.
Was this page helpful?