Skip to content

Jobs and polling

POST /v1/extract never returns extracted content — it returns one job id per submitted document with status pending, HTTP 202. A job then moves through zero or more intermediate states until it reaches one of four terminal statuses: completed, partial_success, failed or cancelled. Only completed and partial_success carry a usable result; the other two are failures the wait helpers raise on rather than return.

GET /v1/jobs/{id} fetches the current status. GET /v1/jobs/{id}/result fetches the stored result document and answers 409 until the job reaches a terminal successful status.

Job detail reads return an extraction or crawl record on both tiers. Python and TypeScript expose job_type for narrowing before accessing variant fields. Go returns GetJobResponse; decode its extraction or crawl variant with AsGetJobResponse0 or AsGetJobResponse1. The wait and batch extraction helpers return extraction records and reject crawl IDs.

Python
from pathlib import Path
from xberg_io_sdk import XbergClient
with XbergClient(api_key="kz_...", base_url="https://xberg.example.com") as client:
job = client.extract(file=Path("invoice.pdf"))
current = client.get_job(str(job.id))
if current.job_type == "extraction":
print(current.filename, current.status)
TypeScript
import { XbergClient } from "@xberg-io/sdk";
const client = new XbergClient({ baseUrl: "https://xberg.example.com", apiKey: process.env.XBERG_API_KEY! });
const job = await client.extract({ file: { name: "invoice.pdf", data, mimeType: "application/pdf" } });
const current = await client.getJob(job.id);
if (current.job_type === "extraction") {
console.log(current.filename, current.status);
}
Go
job, err := client.Extract(ctx, xberg.FileSource{Name: "invoice.pdf", Reader: file}, nil)
if err != nil {
log.Fatal(err)
}
current, err := client.GetJob(ctx, job.Id.String())
if err != nil {
log.Fatal(err)
}
extraction, err := current.AsGetJobResponse0()
if err != nil || extraction.JobType != "extraction" {
log.Fatal("Expected an extraction job")
}
fmt.Println(extraction.Filename, extraction.Status)

wait_for_job / waitForJob / WaitForJob poll GET /v1/jobs/{id} until the job reaches a terminal status, backing off between polls, and raise instead of returning a failed job:

Python
from xberg_io_sdk.errors import TimeoutError as XbergTimeoutError, XbergError
try:
result = client.wait_for_job(job.id, timeout=120, poll_interval=1.0, backoff="exponential")
except XbergTimeoutError:
print("still running after 120s")
except XbergError as exc:
print(f"job failed: {exc}")
TypeScript
import { TimeoutError, XbergError } from "@xberg-io/sdk";
try {
const result = await client.waitForJob(job.id, { timeoutMs: 120_000, pollIntervalMs: 1000 });
} catch (err) {
if (err instanceof TimeoutError) {
console.log("still running after 120s");
} else if (err instanceof XbergError) {
console.log(`job failed: ${err.message}`);
}
}
Go
result, err := client.WaitForJob(ctx, job.Id.String(), &xberg.WaitOptions{
Timeout: 120 * time.Second,
PollInterval: time.Second,
Backoff: xberg.BackoffExponential,
})
var timeoutErr *xberg.TimeoutError
if errors.As(err, &timeoutErr) {
fmt.Println("still running after 120s")
}

Defaults (all three clients): a 5-minute wait timeout, a 1-second initial poll interval, and exponential backoff capped at 30 seconds. Raise the wait timeout for large documents rather than the per-request timeout — the poll itself is always a short status read; only the wait loop needs to span the whole extraction.

wait_for_jobs / waitForJobs / WaitForJobs wait for several job ids. Python waits sequentially; TypeScript and Go wait concurrently and Go cancels the remaining waits on the first error.

extract_and_wait / extractAndWait / ExtractAndWait combine submit and wait in one call — see the quickstart for the single-document form.

cancel_job / cancelJob / CancelJob issues DELETE /v1/jobs/{id} and is idempotent: a job already in a terminal state also answers 204. list_jobs / listJobs / ListJobs paginates GET /v1/jobs with limit/offset.

A batch can end with one job completed and another partial_success for a different document in the same request — jobs are independent even when submitted together. A partial_success job’s result carries per-document errors alongside whatever did extract; read those before assuming the whole batch failed. See Batches for how batch results correlate back to inputs.

For a job in a specific Pro project, Python’s synchronous and asynchronous helpers accept project_id=project_id. Pass it to extraction and to subsequent job, result, page, listing, cancellation and polling calls. TypeScript accepts the equivalent { projectId } option.

In Go, derive projectCtx := xberg.WithProProject(ctx, projectID) and pass that context to the existing extraction and job methods. The selection follows internal job reads and polling, and concurrent contexts can select different projects on the same client.

Explicit project selection requires Pro. The SDK sends X-Project-ID when submitting extraction and project_id when reading or cancelling jobs. Calls without a selection keep their existing request URLs. Go’s project context leaves unrelated routes unchanged.