Skip to content

client.jobs

Bases: SyncResource

Sync jobs namespace (client.jobs).

get

get(job_id: UUID | str) -> JobHandle

Fetch one job by id.

Raises:

Type Description
NotFoundError

unknown job id (JOB_NOT_FOUND).

list

list(*, status: JobStatus | list[JobStatus] | None = None, kind: JobKind | list[JobKind] | None = None, created_by: UUID | str | None = None, dataset_id: UUID | str | None = None, project_id: UUID | str | None = None, created_at_from: datetime | str | None = None, created_at_to: datetime | str | None = None, include_total: bool = False, limit: int | None = None, cursor: str | None = None) -> Page[Job]

List this tenant's jobs, newest first (cursor-paginated).

Parameters:

Name Type Description Default
status JobStatus | list[JobStatus] | None

filter to one or more of pending/queued/running/completed/ failed/canceled (repeatable = IN).

None
kind JobKind | list[JobKind] | None

filter by job kind(s). Required to see cleanup_s3_objects.

None
created_by UUID | str | None

only jobs created by this user id.

None
dataset_id UUID | str | None

only jobs whose target references this dataset.

None
project_id UUID | str | None

only jobs whose target references this project.

None
created_at_from datetime | str | None

created_at >= this bound (inclusive).

None
created_at_to datetime | str | None

created_at < this bound (exclusive).

None
include_total bool

also populate page.total (costs a COUNT).

False
limit int | None

page size (server cap 100).

None
cursor str | None

opaque page cursor (iteration handles this for you).

None

Job handles & model

Kickoff methods across the SDK return a JobHandle — call .wait(). Job is the status model.

Async-job ergonomics: submit → wait → inspect, without hand-rolled polling.

Every bulk/GPU operation returns a Job (202). Resources wrap that in a :class:JobHandle:

job = client.projects.assets.bulk_delete_annotations(pid, filter={}, source="model")
job = job.wait(timeout=600)              # polls until terminal; raises on failure
job.result_summary                        # e.g. {"skipped_locked": 3}

Gotchas the platform enforces (surfaced here so you don't rediscover them): - Per-tenant cap of 3 concurrently active jobs → RateLimitError(JOB_PER_TENANT_CAP). Serialize long-running jobs (train, embed, export) rather than firing in parallel. - GET /jobs hides internal kinds (cleanup_s3_objects) unless filtered by kind explicitly — mirror of the server contract, not an SDK omission.

JobFailedError

JobFailedError(job: Job)

Bases: Exception

Raised by wait() when the job reaches failed/canceled. Carries the terminal :class:Job on .job (job.error has the server reason).

JobTimeoutError

JobTimeoutError(job: Job, timeout: float)

Bases: Exception

Raised by wait() when the timeout elapses before a terminal status. The job keeps running server-side; carry on with handle.refresh() later.

JobHandle

JobHandle(client: Client, job: Job)

A submitted job + the client that can poll it. Attribute access proxies the underlying :class:Job model (handle.status, .processed, ...).

refresh

refresh() -> JobHandle

Re-fetch the job row; returns self for chaining.

wait

wait(*, timeout: float = _DEFAULT_TIMEOUT_S, poll_interval: float = _DEFAULT_POLL_S, on_progress: Callable[[Job], None] | None = None, raise_on_failure: bool = True) -> JobHandle

Poll until terminal. Raises :class:JobFailedError on failed/canceled (unless raise_on_failure=False) and :class:JobTimeoutError on timeout. on_progress fires after every poll with the fresh :class:Job.

AsyncJobHandle

AsyncJobHandle(client: AsyncClient, job: Job)

Async twin of :class:JobHandle.

wait async

wait(*, timeout: float = _DEFAULT_TIMEOUT_S, poll_interval: float = _DEFAULT_POLL_S, on_progress: Callable[[Job], None] | None = None, raise_on_failure: bool = True) -> AsyncJobHandle

Async twin of :meth:JobHandle.wait (same semantics).

Job models — the async-operation envelope every bulk/GPU kickoff returns.

Job

Bases: BaseModel

One async job row (ADR-0023). Counters accrete while status is pending/queued/running; terminal statuses are completed / failed / canceled.

target and result_summary are deliberately plain dicts — their keys vary per kind (the server validates them against per-kind registries). result_summary examples: bulk-delete-annotations → {"skipped_locked": n, "dropped_from_filter": n}; bulk-create → {"created", "failed", "errors"}.

pct is progress as an integer-valued percent (0–100) of processed over total; it is None — not 0 — whenever total == 0 (an empty bulk-op or a freshly-queued export with nothing counted yet), which is a normal state, not an error.