Skip to content

client.annotations

Bases: SyncResource

Sync annotations namespace (client.annotations).

asset_batch_create

asset_batch_create(project_id: UUID | str, asset_id: UUID | str, annotations: list[AnnotationCreateParam], *, replace: bool = False) -> list[Annotation]

Create many annotations on ONE asset in a single sync call — the labeling submit path. All-or-nothing (any invalid row -> 422, nothing inserted); source is always manual; replace=True clears the asset's existing annotations first. Cap 1000 rows.

Raises:

Type Description
UnprocessableError

an invalid row (details carry the index) or >1000 rows.

ConflictError

PROJECT_STATE_FORBIDDEN when the asset is edit-locked.

list

list(project_id: UUID | str, *, class_id: list[UUID | str] | None = None, type: AnnotationType | str | None = None, source: AnnotationSource | str | None = None, created_by: UUID | str | None = None, asset_id: UUID | str | None = None, asset_ids: list[UUID | str] | None = None, instance_id: UUID | str | None = None, created_at_from: datetime | str | None = None, created_at_to: datetime | str | None = None, include: list[str] | None = None, include_total: bool = False, version_id: UUID | str | None = None, limit: int | None = None, cursor: str | None = None) -> Page[Annotation]

Annotation-level list, newest first (created_at DESC, id DESC); cursor-paginated (iterate for all pages). Wide page size (server cap 200).

Parameters:

Name Type Description Default
class_id list[UUID | str] | None

repeatable class filter — class_id IN (...).

None
type AnnotationType | str | None

geometry discriminator (bbox / polygon / keypoint / classification); exact match.

None
source AnnotationSource | str | None

provenance — manual / imported / model.

None
created_by UUID | str | None

filter to annotations authored by this user (user UUID).

None
asset_id UUID | str | None

single asset; mutually exclusive with asset_ids.

None
asset_ids list[UUID | str] | None

repeatable, up to 100 assets (IN); mutually exclusive with asset_id.

None
instance_id UUID | str | None

filter to annotations sharing this instance id (the multi-shape instance-grouping id).

None
created_at_from datetime | str | None

lower bound on created_at (inclusive; datetime or ISO-8601 string).

None
created_at_to datetime | str | None

upper bound on created_at (exclusive; datetime or ISO-8601 string).

None
include list[str] | None

sub-resources to embed on each row — any of "asset", "class" (sent as a CSV ?include= param).

None
include_total bool

also populate page.total (COUNT over the same filter).

False
version_id UUID | str | None

read from this version's frozen S3 manifests instead of the live table; REQUIRES asset_id or asset_ids to scope the per-asset fan-out.

None

Raises:

Type Description
NotFoundError

unknown project (PROJECT_NOT_FOUND), or unknown version_id in this project (VERSION_NOT_FOUND).

ForbiddenError

caller is not a member of this project (AUTH_FORBIDDEN).

BadRequestError

both asset_id and asset_ids given, asset_ids over 100, or an unknown include value (INVALID_FILTER); a malformed cursor (INVALID_CURSOR); version_id without an asset scope (BAD_REQUEST).

ConflictError

version_id is not yet ready (RESOURCE_NOT_READY).

UnprocessableError

invalid type / source enum value.

batch_delete

batch_delete(project_id: UUID | str, *, ids: list[UUID | str]) -> AnnotationBatchDeleteResult

Hard-delete up to 500 annotations by id, scoped to this project (member+). Idempotent — ids that match no row in this project come back as skipped. Live children (parent_id in ids) cascade. For larger sets, chunk.

Raises:

Type Description
NotFoundError

unknown project (PROJECT_NOT_FOUND).

ForbiddenError

caller is not a member of this project (AUTH_FORBIDDEN).

UnprocessableError

empty ids or more than 500 (VALIDATION_ERROR).

project_batch_create

project_batch_create(project_id: UUID | str, *, annotations: list[MappedAnnotationCreateParam], source: AnnotationSource | str = AnnotationSource.MANUAL, replace: bool = False) -> AnnotationBatchCreateResult

Create a flat mapped list of annotations across many assets in one sync call (ADR-0061, Manager+); 201. Up to 1000 rows; each references its asset by asset_id or filename. All-or-nothing: any invalid row → 422 with its index, nothing inserted. replace=True first deletes existing annotations on every referenced asset.

Parameters:

Name Type Description Default
annotations list[MappedAnnotationCreateParam]

mapped-create row dicts (asset_id/filename + class_id + type [+ geometry / data / id / ...]).

required
source AnnotationSource | str

provenance stamped on the rows — defaults to manual.

MANUAL

Raises:

Type Description
NotFoundError

unknown project (PROJECT_NOT_FOUND).

ForbiddenError

caller is not a project manager (AUTH_FORBIDDEN).

UnprocessableError

empty list, over 1000 rows, or an invalid row (VALIDATION_ERROR — the message names the offending index).

import_init

import_init(project_id: UUID | str, *, size_bytes: int) -> AnnotationImportInit

Mint a presigned PUT for a staged NDJSON import file (ADR-0061, Manager+); 201. The exact size_bytes is pinned at S3 (cap 256 MB). PUT the raw NDJSON bytes to upload_url (15-min TTL), then pass the returned import_id to :meth:bulk_create. Prefer :meth:import_ndjson, which wires all three steps.

Raises:

Type Description
NotFoundError

unknown project (PROJECT_NOT_FOUND).

ForbiddenError

caller is not a project manager (AUTH_FORBIDDEN).

RateLimitError

upload-init rate limit exceeded (RATE_LIMITED).

UnprocessableError

size_bytes ≤ 0 or over the 256 MB cap (VALIDATION_ERROR).

bulk_create

bulk_create(project_id: UUID | str, *, annotations: list[MappedAnnotationCreateParam] | None = None, import_id: UUID | str | None = None, source: AnnotationSource | str = AnnotationSource.IMPORTED, replace: bool = False, idempotency_key: str | None = None) -> JobHandle

Kick off an async annotation-create job (ADR-0061, Manager+); returns a :class:JobHandle (202). Provide EXACTLY ONE of annotations inline (bounded by the ~6 MB request payload) or import_id from :meth:import_init (S3-staged NDJSON). The worker scans, validates, and inserts in resumable batches, reporting per-row errors on the Job.

Parameters:

Name Type Description Default
source AnnotationSource | str

provenance stamped on the rows — defaults to imported.

IMPORTED
replace bool

delete existing annotations on referenced assets first.

False

Raises:

Type Description
NotFoundError

unknown project (PROJECT_NOT_FOUND); or import_id has no uploaded file yet (UNCATEGORIZED — call import-init and PUT the NDJSON first).

ForbiddenError

caller is not a project manager (AUTH_FORBIDDEN).

ConflictError

idempotency key reused with a different body (IDEMPOTENCY_REPLAY).

RateLimitError

per-tenant active-job cap reached (JOB_PER_TENANT_CAP), or the write rate limit (RATE_LIMITED).

UnprocessableError

neither or both of annotations / import_id (VALIDATION_ERROR).

import_ndjson

import_ndjson(project_id: UUID | str, rows: list[MappedAnnotationCreateParam], *, source: AnnotationSource | str = AnnotationSource.IMPORTED, replace: bool = False, idempotency_key: str | None = None) -> JobHandle

Convenience: stage rows as NDJSON and kick the async import in one call (Manager+). Wires the three-step protocol — :meth:import_init to mint a presigned PUT, upload the encoded NDJSON to S3, then :meth:bulk_create with the import_id — and returns the resulting :class:JobHandle (202). Use this instead of inline bulk_create for large imports.

Parameters:

Name Type Description Default
rows list[MappedAnnotationCreateParam]

mapped-create row dicts (same shape as :meth:project_batch_create's annotations).

required
source AnnotationSource | str

provenance stamped on the rows — defaults to imported.

IMPORTED

Raises:

Type Description
NotFoundError / ForbiddenError / RateLimitError / UnprocessableError

as raised by :meth:import_init and :meth:bulk_create.

batch_edit

batch_edit(project_id: UUID | str, *, creates: list[AnnotationBatchEditCreateParam] | None = None, updates: list[AnnotationBatchEditUpdateParam] | None = None, deletes: list[UUID | str] | None = None) -> AnnotationBatchEditResult

Create, update, and delete annotations in ONE atomic transaction — the editor "save" path (ADR-0070/0092, member+). At least one bucket must be non-empty; the combined op count is capped at 1000. Applied order is create → update → delete; the response echoes each bucket's ids. All-or-nothing: any validation failure or edit-lock rolls back everything. deletes is idempotent (ids already gone are no-ops).

Parameters:

Name Type Description Default
creates list[AnnotationBatchEditCreateParam] | None

full new-annotation dicts (client-minted id required per row, asset_id + class_id + type [+ geometry/data/...]).

None
updates list[AnnotationBatchEditUpdateParam] | None

partial-update dicts keyed by id (only supplied fields change; type is immutable).

None
deletes list[UUID | str] | None

annotation ids to hard-delete.

None

Raises:

Type Description
NotFoundError

unknown project (PROJECT_NOT_FOUND).

ForbiddenError

caller is not a member of this project (AUTH_FORBIDDEN).

ConflictError

one or more touched assets are edit-locked (PROJECT_STATE_FORBIDDEN — err.details["blocked_assets"]).

PayloadTooLargeError

raw body over the sync cap (PAYLOAD_TOO_LARGE).

UnprocessableError

empty batch, over 1000 ops, duplicate create ids, or any invalid create/update row (VALIDATION_ERROR — err.details["errors"] lists the offending ids).

Response models

Models returned by client.annotations methods (fields, types, and what each means).

Annotation domain models (ADR-0029 / ADR-0090 / ADR-0092).

Read-side shapes for the client.annotations namespace. The one true list endpoint (GET .../annotations) returns :class:Annotation rows — the stored annotation plus, when ?include=asset,class is passed, the embedded asset summary and the class it is an instance of.

Reserved word: the embedded class ref rides the wire key class (a Python keyword), so :attr:Annotation.class_ carries BOTH a validation_alias (to read it) and a serialization_alias (to round-trip it) of "class" (STYLE.md §types).

Geometry is the tolerant READ union (:data:GeometryRead, ADR-0104): pixel coordinates with no write-time value constraints re-imposed on a stored row. ClassRef mirrors the server's flat class serialization (ADR-0090) and reuses the keypoint/classification config shapes owned by types.classes.

ClassRef

Bases: BaseModel

Flat serialization of the project class an annotation is an instance of (ADR-0090; embedded on list items under the wire key class). Distinct from the nested ClassResponse: no inline attributes. kind="object" classes may carry keypoint_topology; kind="classification" carry a classification_config.

Annotation

Bases: BaseModel

One annotation row (ADR-0092: the client-minted UUID IS the identity).

Returned by client.annotations.list. asset and class_ are populated only when the matching include= value is requested; otherwise None. geometry is None for classification annotations.

AnnotationImportInit

Bases: BaseModel

Result of import-init: a presigned PUT for a staged NDJSON file plus the import_id to hand to bulk_create once the bytes are uploaded.

AnnotationBatchDeleteResultItem

Bases: BaseModel

Per-id outcome of a batch_delete call.

AnnotationBatchDeleteResult

Bases: BaseModel

Envelope for batch_delete (ADR-0041): total == deleted + skipped and len(results) == total. skipped = requested ids that matched no row in this project (already gone, wrong project, or never existed).

AnnotationBatchCreateResult

Bases: BaseModel

Envelope for the sync project_batch_create (create-only): every row is created or the whole call 422s, so there is no skipped bucket. replaced counts existing annotations deleted by replace=True across the referenced assets.

AnnotationBatchEditResult

Bases: BaseModel

Envelope for the transactional batch_edit (ADR-0092): the ids in each bucket, in request order. deleted excludes ids that were already gone.