Sign in Get started

Jobs

One view of every job your organization is running - list, read, wait for and cancel training, auto-annotation, workflow runs, evaluations, exports and imports.

View as Markdown

Long-running work in Pictograph comes in many kinds: training runs, batch auto-annotation, workflow runs, model evaluations, exports, and the background jobs behind imports, video frame extraction and bulk image operations. Each kind has its own status call on its own resource. client.jobs answers “what am I waiting on?” across all of them at once.

Every job reads the same way, whatever its kind:

  • type - training, auto_annotate, workflow_run, evaluation, export, or a background job’s own type (connector_import, public_dataset_import, video_extract, batch_move, …).
  • status - one vocabulary for every kind: queued and running are active, completed, failed and cancelled are finished.
  • progress - 0 to 100.
  • detail - what only that kind has: a training run’s epochs, a workflow run’s frames, a background job’s item counts.
  • cancel_path - the API route that cancels the job, or None when it is finished or its kind cannot be cancelled through the API.

The list is scoped to the API key’s organization, and any role can read it. Finished background jobs (imports, extractions, bulk operations) are kept 30 days; training runs, workflow runs, batch auto-annotation and evaluations keep their history.

list

Your organization’s jobs, newest first. Queued and running jobs by default.

Source: Jobs.list

Arg Type Default Notes
status str "active" active, finished, all, or one of queued, running, completed, failed, cancelled
type str | None None Only jobs of this kind
page_size int 50 Jobs per request, maximum 100
max_total int | None None Stop after this many jobs
for job in client.jobs.list():
    print(job.type, job.status, job.progress, job.name)

failed = list(client.jobs.list(status="failed", type="training", max_total=20))
pictograph jobs list
pictograph jobs list --status failed --type training --limit 20
curl -s "https://api.pictograph.io/api/v1/developer/jobs?status=failed&type=training&limit=20&offset=0" \
  -H "X-API-Key: $PICTOGRAPH_API_KEY"

Returns OffsetPager[Job]

Job · 12 fields
class Job(BaseModel):
    """One job, whatever kind of work it is."""
    id: str
    type: str
    status: str
    progress: float | None = None
    name: str | None = None
    dataset_id: str | None = None
    error: str | None = None
    created_at: datetime | None = None
    updated_at: datetime | None = None
    completed_at: datetime | None = None
    cancel_path: str | None = None
    detail: dict[str, Any] = {}

The API reads at most the newest 1,000 jobs of one filter (offset + limit up to 1000); narrow with status or type past that.

get

One job, by the id the work answered when it started: a training run’s id, an import’s id, a workflow run’s id, and so on. Either spelling of a uuid works.

Source: Jobs.get

Arg Type Default Notes
job_id str required The job’s id
job = client.jobs.get(
    job_id="c1c1c1c1-0000-4000-8000-000000000002",
)
print(job.type, job.status, job.progress, job.error)
pictograph jobs get c1c1c1c1-0000-4000-8000-000000000002
curl -s "https://api.pictograph.io/api/v1/developer/jobs/c1c1c1c1-0000-4000-8000-000000000002" \
  -H "X-API-Key: $PICTOGRAPH_API_KEY"

Returns Job

Job · 12 fields
class Job(BaseModel):
    """One job, whatever kind of work it is."""
    id: str
    type: str
    status: str
    progress: float | None = None
    name: str | None = None
    dataset_id: str | None = None
    error: str | None = None
    created_at: datetime | None = None
    updated_at: datetime | None = None
    completed_at: datetime | None = None
    cancel_path: str | None = None
    detail: dict[str, Any] = {}

Another organization’s job returns 404, like an id that does not exist.

wait

Poll a job until it finishes. Returns the completed job; raises when it failed or was cancelled.

Source: Jobs.wait

Arg Type Default Notes
job_id str required The job’s id
poll_interval float 3.0 Seconds between status checks
timeout float 3600.0 Seconds to wait. The job keeps running after it
sleep Callable | None None Injectable sleep (tests)
from pictograph.exceptions import ApiError, PollTimeoutError

try:
    job = client.jobs.wait(
        job_id="c1c1c1c1-0000-4000-8000-000000000002",
        timeout=1800,
    )
except ApiError as err:
    print(err.code, err.response["error"])  # job_failed or job_cancelled
except PollTimeoutError:
    print("still running - wait again later")
pictograph jobs wait c1c1c1c1-0000-4000-8000-000000000002 --timeout 1800
# REST: poll the job until its status is completed, failed or cancelled
curl -s "https://api.pictograph.io/api/v1/developer/jobs/c1c1c1c1-0000-4000-8000-000000000002" \
  -H "X-API-Key: $PICTOGRAPH_API_KEY"

Returns Job

Job · 12 fields
class Job(BaseModel):
    """One job, whatever kind of work it is."""
    id: str
    type: str
    status: str
    progress: float | None = None
    name: str | None = None
    dataset_id: str | None = None
    error: str | None = None
    created_at: datetime | None = None
    updated_at: datetime | None = None
    completed_at: datetime | None = None
    cancel_path: str | None = None
    detail: dict[str, Any] = {}

The CLI exits 0 when the job completed, non-zero when it failed or was cancelled, and 10 when it was still running at --timeout.

cancel

Cancel a queued or running job. The cancel goes through the route that cancels its kind, with that kind’s own rules: a training run is refunded what it did not use, and a cancelled workflow run keeps its outputs so far, its time on its endpoint billed as uptime. The answer is the job as it reads after the cancel.

Source: Jobs.cancel

Arg Type Default Notes
job_id str required The job’s id
job = client.jobs.cancel(
    job_id="c1c1c1c1-0000-4000-8000-000000000002",
)
print(job.status)
pictograph jobs cancel c1c1c1c1-0000-4000-8000-000000000002
# REST: read the job, then POST to its cancel_path
curl -s -X POST "https://api.pictograph.io/api/v1/developer/training/c1c1c1c1-0000-4000-8000-000000000002/cancel" \
  -H "X-API-Key: $PICTOGRAPH_API_KEY"

Returns Job

Job · 12 fields
class Job(BaseModel):
    """One job, whatever kind of work it is."""
    id: str
    type: str
    status: str
    progress: float | None = None
    name: str | None = None
    dataset_id: str | None = None
    error: str | None = None
    created_at: datetime | None = None
    updated_at: datetime | None = None
    completed_at: datetime | None = None
    cancel_path: str | None = None
    detail: dict[str, Any] = {}

Training runs, batch auto-annotation, workflow runs, model evaluations and V7 / Roboflow imports can be cancelled through the API. A job whose cancel_path is None cannot: the call raises ValidationError without sending anything.

Copied to clipboard