> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ndi.nace.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Jobs

> Wait, stream, cancel, inspect, delete, and usage

Every slow `/v1` call returns a `Job`. `wait_seconds` is a query parameter.
`Idempotency-Key` is minted automatically on document operations unless you
pass `idempotency_key=`.

```python theme={"dark"}
from ndi_sdk import NdiClient

with NdiClient() as client:
    upload = client.documents.create_upload("report.pdf")
    queued = client.documents.parse(upload)
    job = client.jobs.wait(queued.job_id, timeout=600)
    print(job.status, job.result.markdown)
```

## Methods

```text theme={"dark"}
def get(job_id: UUID | str) -> Job
def list(*, workspace_id=None, kind=None, status=None, created_after=None, cursor=None, limit=None) -> Page[Job]
def iter_all(...) -> Iterator[Job]
def wait(job_id, *, timeout: float = 300, raise_on_failure: bool = True) -> Job
def cancel(job_id, *, reason: str | None = None) -> Job
def request(job_id) -> JobRequestEcho          # Python only
def delete(job_id) -> None                    # Python only
def events(job_id, *, last_event_id=None) -> Iterator[JobEvent]
def ground_crop(job_id, artifact_ref, *, byte_range=None) -> bytes
def usage(*, period_start: date, period_end: date, workspace_id=None, group_by="day") -> UsageResponse
```

`wait` raises `JobFailedError` on `failed`/`cancelled` and `JobTimeoutError`
when the budget runs out (the job keeps running).

```python theme={"dark"}
from datetime import date

from ndi_sdk import NdiClient

with NdiClient() as client:
    usage = client.jobs.usage(
        period_start=date(2026, 8, 1),
        period_end=date(2026, 9, 1),
    )
    print(usage)
```

`GET /v1/usage/overview` is HTTP-only.

See [Jobs guide](/guides/jobs).
