Report how far a job got
const url = 'https://beta-api.plune.ai/v1/jobs/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/progress';const options = { method: 'PATCH', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"done":600,"total":800,"cursor":"result:600"}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request PATCH \ --url https://beta-api.plune.ai/v1/jobs/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/progress \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "done": 600, "total": 800, "cursor": "result:600" }'The producer, every N records — N is its own setting (AC-06; the server’s own jobs take JOB_PROGRESS_EVERY, 500 by default). done of total, or both null while it is still counting. A report keeps a running job running and brings a waiting one back: an action_needed, paused or blocked job returns to in_progress and its reason is cleared. A finished job takes none — completed is the end, a failed one waits for a person’s Retry: 409 job_finished with its state. Not audited (machine intake, like results). Only from an API token — the producer’s: a browser session is refused with 403 reports come from a producer token, a reader with 403 read-only member. subjectId names what the job works on once the producer knows it (#1279) — only while the job names nothing: another value is 409 subject_set.
Authorizations
Section titled “Authorizations ”Parameters
Section titled “ Parameters ”Path Parameters
Section titled “Path Parameters ”Header Parameters
Section titled “Header Parameters ”Which of your projects to act in — an id from GET /v1/projects. Absent, your default project. A project you are not a member of answers 404, the same as one that does not exist. Ignored under a bearer token, which is bound to the project it was minted in.
Request Body required
Section titled “Request Body required ”object
At most total. Null with total: still counting.
Where to resume from. Absent keeps the stored one.
Job.attempt as the producer knows it. A report of another try than the job is on is 409 stale_attempt; absent, it is taken as the current try’s — the check is opt-in, a producer that omits it is not protected (only the server’s own bin-empty steps always send it).
#1279: what the job works on, learnt after it was opened — a sync names its run once the upload gave it an id, and the run’s page then shows the job (GET /v1/jobs?runId=). Taken only while the job has none; the same value again changes nothing, another is 409 subject_set. Absent keeps it.
Examples
600 of 800, and where to resume
{ "done": 600, "total": 800, "cursor": "result:600"}A sync names its run, once the upload gave it an id
{ "done": 0, "total": 6214, "subjectId": "6f1c2b3a-0000-4000-8000-0000000000d1"}Responses
Section titled “ Responses ”The job, as it is now
One long AI operation. Seven states: in_progress, action_needed (waits for a person — reason says for what), paused (the quota is spent; Resume, or it resumes by itself), blocked (an outside service failed — reason names it; no button), completed, failed (reason is the raw error; a person may Dismiss it), cancelled (a person’s Cancel — reason is «Cancelled by completed). progress is null while the operation does not know its size — never 0 / 0.
object
Which operation: ingest, sync, auto-analysis, and bin-empty — the Bin emptied by the server (#1388) — and runs-delete — runs deleted in the background (#1423) — today; open-ended.
What it works on — a run id, an import id.
Its name as people know it — shown after the kind.
How far it got; null while the size is not known yet.
object
Why it stopped — only on action_needed, paused, blocked, failed, cancelled. A cancel reads «Cancelled by
The producer’s own token for where it resumes; null — a Retry starts from the beginning.
Which try this is: 1, and one more for each Retry. A producer sends it back in its reports (attempt), and a report of an earlier try is 409 stale_attempt.
Set on completed, failed and cancelled, and only there.
Only on a run-export job in GET /v1/jobs and in the answer of GET /v1/runs/{id}/export (202): the run the file is of, so «Export again» works from any browser. A completed export stays in the list 7 days (its file goes after 24 hours).
Example
{ "id": "6f1c2b3a-0000-4000-8000-0000000000a9", "kind": "ingest", "state": "in_progress", "subjectId": "6f1c2b3a-0000-4000-8000-0000000000d1", "subjectName": "nightly-e2e", "progress": { "done": 600, "total": 800 }, "reason": null, "cursor": "result:600", "attempt": 1, "createdAt": "2026-09-16T10:02:00.000Z", "startedAt": "2026-09-16T10:02:00.000Z", "finishedAt": null, "updatedAt": "2026-09-16T10:09:41.000Z"}The body is not JSON, or not a report: one number without the other, done past total, a total of 0
object
Example generated
{ "error": "example"}No / invalid token or session
A reader asked, or a browser session sent a report — reports come from the producer’s API token; a job the server runs itself (bin-empty, #1388) takes no report at all; Cancel, Retry and Resume of a TestRail import are the project owner’s (403 project owner only)
object
Examples
{ "error": "read-only member"}{ "error": "reports come from a producer token"}No such job in this project
object
Example generated
{ "error": "example"}The job is completed, failed or cancelled, the report is of an earlier try (stale_attempt), or it names another subject than the job has (subject_set)
object
Where the job is now — a producer learns from it that a person cancelled.
Only with stale_attempt: the try the job is on.
Example
{ "error": "job '6f1c2b3a-0000-4000-8000-0000000000a9' is failed: a finished job takes no progress", "code": "job_finished", "state": "failed"}Rate-limited: the per-route throttle, or the per-minute request limit of the plan an API token counts by (#1442; the body names the plan, #2092). Retry-After carries the seconds until the window rolls over.
object
Example generated
{ "error": "example"}Headers
Section titled “Headers ”Seconds until the window rolls over