Superb AI Annotations API
The annotations API from Superb AI — 9 operation(s) for annotations.
The annotations API from Superb AI — 9 operation(s) for annotations.
Every API here is available over the APIs.io API and to AI agents over MCP.
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
find_apisBrowse and filter every API in the catalog.get_api_artifactsOne API's artifacts, grouped by type.get_openapiThe primary OpenAPI for this API.find_similar_apisAPIs that look like this one.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.curl "https://apis.io/api/v1/apis/superb-ai-annotations-api"
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: MLOps Platform Annotations API
description: Multi-tenant labeling-platform backend.
version: 0.1.0
tags:
- name: Annotations
paths:
/tenants/{slug}/projects/{project_id}/annotations:
get:
tags:
- Annotations
summary: List Annotations
description: 'Annotation-level cursor-paginated list (ADR-0029 Phase 1).
Default sort: `created_at DESC, id DESC` — backed by `ix_ann_project_created`
+ `ix_ann_project_class`. Empirically <1 ms at 5M rows.
Phase 1 advertises NO `?sort=` parameter — only the default. Phase 2 will
add an allowlist + index when the FE asks.
When `version_id` is set, the read swaps to the S3 manifest backing that
project version (see ADR-0024). The fan-out is per-asset, so the request
must specify `asset_id` or `asset_ids` — version-wide enumeration is left
to a separate paginated endpoint (deferred until the FE asks for it).'
operationId: annotations-list_annotations
security:
- HTTPBearer: []
parameters:
- name: slug
in: path
required: true
schema:
type: string
title: Slug
- name: project_id
in: path
required: true
schema:
type: string
format: uuid
title: Project Id
- name: limit
in: query
required: false
schema:
type: integer
maximum: 200
minimum: 1
description: Max rows per page.
default: 50
title: Limit
description: Max rows per page.
- name: cursor
in: query
required: false
schema:
anyOf:
- type: string
- type: 'null'
description: Opaque pagination cursor from a previous response's `next_cursor`; omit for the first page.
title: Cursor
description: Opaque pagination cursor from a previous response's `next_cursor`; omit for the first page.
- name: class_id
in: query
required: false
schema:
anyOf:
- type: array
items:
type: string
format: uuid
- type: 'null'
description: 'Repeatable class filter: `?class_id=a&class_id=b` → `class_id IN (...)`.'
title: Class Id
description: 'Repeatable class filter: `?class_id=a&class_id=b` → `class_id IN (...)`.'
- name: type
in: query
required: false
schema:
anyOf:
- $ref: '#/components/schemas/AnnotationType'
- type: 'null'
description: Annotation type (the geometry discriminator). Exact match; invalid values 422.
title: Type
description: Annotation type (the geometry discriminator). Exact match; invalid values 422.
- name: source
in: query
required: false
schema:
anyOf:
- type: array
items:
$ref: '#/components/schemas/AnnotationSource'
- type: 'null'
description: Repeatable `?source=manual&source=model`. ANY-of provenance filter (`manual`/`imported`/`model`); a single value keeps the prior exact-match behavior.
title: Source
description: Repeatable `?source=manual&source=model`. ANY-of provenance filter (`manual`/`imported`/`model`); a single value keeps the prior exact-match behavior.
- name: source_none
in: query
required: false
schema:
anyOf:
- type: array
items:
$ref: '#/components/schemas/AnnotationSource'
- type: 'null'
description: Repeatable `?source_none=a&source_none=b`. Excludes annotations whose source is any listed provenance (negative twin, ADR-0115). A value repeated in `source` → 400.
title: Source None
description: Repeatable `?source_none=a&source_none=b`. Excludes annotations whose source is any listed provenance (negative twin, ADR-0115). A value repeated in `source` → 400.
- name: created_by
in: query
required: false
schema:
anyOf:
- type: string
format: uuid
- type: 'null'
description: Filter to annotations authored by this user (labeler / model actor).
title: Created By
description: Filter to annotations authored by this user (labeler / model actor).
- name: asset_id
in: query
required: false
schema:
anyOf:
- type: string
format: uuid
- type: 'null'
description: Filter to annotations on this single asset. Mutually exclusive with `asset_ids`.
title: Asset Id
description: Filter to annotations on this single asset. Mutually exclusive with `asset_ids`.
- name: asset_ids
in: query
required: false
schema:
anyOf:
- type: array
items:
type: string
format: uuid
- type: 'null'
description: Repeatable `?asset_ids=a&asset_ids=b` → filter to annotations on any of these assets (max 100). Used by the FE grid view to merge per-asset annotation calls into one request. Mutually exclusive with `asset_id`.
title: Asset Ids
description: Repeatable `?asset_ids=a&asset_ids=b` → filter to annotations on any of these assets (max 100). Used by the FE grid view to merge per-asset annotation calls into one request. Mutually exclusive with `asset_id`.
- name: instance_id
in: query
required: false
schema:
anyOf:
- type: string
format: uuid
- type: 'null'
description: Filter to annotations sharing this instance id (multi-shape instance grouping).
title: Instance Id
description: Filter to annotations sharing this instance id (multi-shape instance grouping).
- name: created_at_from
in: query
required: false
schema:
anyOf:
- type: string
format: date-time
- type: 'null'
description: Inclusive lower bound (>=) on `created_at` (ISO-8601).
title: Created At From
description: Inclusive lower bound (>=) on `created_at` (ISO-8601).
- name: created_at_to
in: query
required: false
schema:
anyOf:
- type: string
format: date-time
- type: 'null'
description: Exclusive upper bound (<) on `created_at` (ISO-8601).
title: Created At To
description: Exclusive upper bound (<) on `created_at` (ISO-8601).
- name: include
in: query
required: false
schema:
anyOf:
- type: string
- type: 'null'
description: 'CSV of sub-resources to embed: `asset`, `class`. Whole-record only.'
title: Include
description: 'CSV of sub-resources to embed: `asset`, `class`. Whole-record only.'
- name: include_total
in: query
required: false
schema:
type: boolean
description: When true, response carries `total` = COUNT(*) for the same filter (ignores cursor/limit). Sub-400ms at the 5M-row project cap; opt in only when the FE needs a 'showing X of Y' total.
default: false
title: Include Total
description: When true, response carries `total` = COUNT(*) for the same filter (ignores cursor/limit). Sub-400ms at the 5M-row project cap; opt in only when the FE needs a 'showing X of Y' total.
- name: version_id
in: query
required: false
schema:
anyOf:
- type: string
format: uuid
- type: 'null'
description: When set, read annotations from this version's frozen S3 manifests instead of the live `annotation` table — same response shape, but the data is what was frozen at version-build time. Requires `asset_id` or `asset_ids` to scope the fan-out (capped at 100). Version must belong to this project (404 otherwise) and have `status=ready` (425 otherwise). All other filters (class_id, type, source, created_by, instance_id, created_at_*) are applied in memory after the manifest read. Sort + cursor pagination work the same way as the live path.
title: Version Id
description: When set, read annotations from this version's frozen S3 manifests instead of the live `annotation` table — same response shape, but the data is what was frozen at version-build time. Requires `asset_id` or `asset_ids` to scope the fan-out (capped at 100). Version must belong to this project (404 otherwise) and have `status=ready` (425 otherwise). All other filters (class_id, type, source, created_by, instance_id, created_at_*) are applied in memory after the manifest read. Sort + cursor pagination work the same way as the live path.
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/AnnotationListPage'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
'401':
description: Unauthenticated — missing, malformed, or expired Bearer token
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Authenticated but not authorized for this resource
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Resource not found in this tenant
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'409':
description: Conflict — resource state prevents this action
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'429':
description: Rate-limited (per-tenant token bucket)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/tenants/{slug}/projects/{project_id}/annotations/batch-delete:
post:
tags:
- Annotations
summary: Batch Delete Annotations
description: 'Delete up to 500 annotations by id, scoped to this project.
POST `batch-delete` (not DELETE-with-body — proxies strip request bodies on
DELETE per RFC 9110 §9.3.5 / cloud-LB behavior). Hard-cap 500 to keep p95 under
~200 ms (per ADR-0029 perf test); FE chunks for larger sets.'
operationId: annotations-batch_delete_annotations
security:
- HTTPBearer: []
parameters:
- name: slug
in: path
required: true
schema:
type: string
title: Slug
- name: project_id
in: path
required: true
schema:
type: string
format: uuid
title: Project Id
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AnnotationBatchDeleteRequest'
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/AnnotationBatchDeleteResponse'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
'401':
description: Unauthenticated — missing, malformed, or expired Bearer token
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Authenticated but not authorized for this resource
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Resource not found in this tenant
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'409':
description: Conflict — resource state prevents this action
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'429':
description: Rate-limited (per-tenant token bucket)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/tenants/{slug}/projects/{project_id}/annotations/batch-create:
post:
tags:
- Annotations
summary: Project Batch Create Annotations
description: 'Create a flat mapped list of annotations across many assets in one sync
call (ADR-0061) — the import/prediction path. Each row references its asset
by `asset_id` or `filename`. All-or-nothing: any invalid row → 422 with its
index, nothing inserted. Cap MAX_SYNC_BATCH_SIZE. manager+.'
operationId: annotations-project_batch_create_annotations
security:
- HTTPBearer: []
parameters:
- name: slug
in: path
required: true
schema:
type: string
title: Slug
- name: project_id
in: path
required: true
schema:
type: string
format: uuid
title: Project Id
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ProjectAnnotationBatchCreate'
responses:
'201':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/ProjectAnnotationBatchCreateResponse'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
'401':
description: Unauthenticated — missing, malformed, or expired Bearer token
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Authenticated but not authorized for this resource
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Resource not found in this tenant
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'409':
description: Conflict — resource state prevents this action
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'429':
description: Rate-limited (per-tenant token bucket)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/tenants/{slug}/projects/{project_id}/annotations/import-init:
post:
tags:
- Annotations
summary: Annotation Import Init
description: 'Mint a presigned PUT for a staged NDJSON import file (ADR-0061). The
file''s byte count is pinned at S3 (`size_bytes`), capped at
MAX_IMPORT_FILE_BYTES (over → 422 here). PUT the raw NDJSON, then pass the
returned `import_id` to `bulk-create`. 15-min TTL. manager+, rate-limited.'
operationId: annotations-annotation_import_init
security:
- HTTPBearer: []
parameters:
- name: slug
in: path
required: true
schema:
type: string
title: Slug
- name: project_id
in: path
required: true
schema:
type: string
format: uuid
title: Project Id
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AnnotationImportInitRequest'
responses:
'201':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/AnnotationImportInitResponse'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
'401':
description: Unauthenticated — missing, malformed, or expired Bearer token
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Authenticated but not authorized for this resource
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Resource not found in this tenant
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'409':
description: Conflict — resource state prevents this action
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'429':
description: Rate-limited (per-tenant token bucket)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/tenants/{slug}/projects/{project_id}/annotations/bulk-create:
post:
tags:
- Annotations
summary: Project Bulk Create Annotations
description: 'Kick off an async annotation-create job (ADR-0061) — for large imports /
predictions. Body is EITHER `annotations` inline (≤~6 MB) OR an `import_id`
from `import-init` (staged NDJSON). The worker scans (count + size + parse),
then validates + inserts in resumable batches, reporting per-row errors.
manager+. Returns a Job (202).'
operationId: annotations-project_bulk_create_annotations
security:
- HTTPBearer: []
parameters:
- name: slug
in: path
required: true
schema:
type: string
title: Slug
- name: project_id
in: path
required: true
schema:
type: string
format: uuid
title: Project Id
- name: Idempotency-Key
in: header
required: false
schema:
anyOf:
- type: string
- type: 'null'
title: Idempotency-Key
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ProjectAnnotationBulkCreate'
responses:
'202':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/JobResponse'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
'401':
description: Unauthenticated — missing, malformed, or expired Bearer token
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Authenticated but not authorized for this resource
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Resource not found in this tenant
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'409':
description: Conflict — resource state prevents this action
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'429':
description: Rate-limited (per-tenant token bucket)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/tenants/{slug}/projects/{project_id}/annotations/batch:
post:
tags:
- Annotations
summary: Batch Edit Annotations
description: 'Create, update, and delete annotations in ONE atomic transaction — the
editor "save" path (ADR-0070). All-or-nothing: any validation or edit-lock
failure rolls back the whole batch and returns the offending items keyed by
`id`. `deletes` is idempotent (ids already gone are no-ops). Applied order is
create → update → delete; the response echoes each bucket''s ids (ADR-0092).
Caps: `MAX_SYNC_BATCH_SIZE` ops and `MAX_SYNC_BATCH_BYTES` body (the route
deps reject over-cap before parse). Edit-lock is enforced per touched asset
via the same stage-handoff matrix as single edit; manager/reviewer override.'
operationId: annotations-batch_edit_annotations
security:
- HTTPBearer: []
parameters:
- name: slug
in: path
required: true
schema:
type: string
title: Slug
- name: project_id
in: path
required: true
schema:
type: string
format: uuid
title: Project Id
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AnnotationBatchEditRequest'
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/AnnotationBatchEditResponse'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
'401':
description: Unauthenticated — missing, malformed, or expired Bearer token
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Authenticated but not authorized for this resource
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Resource not found in this tenant
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'409':
description: Conflict — resource state prevents this action
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'429':
description: Rate-limited (per-tenant token bucket)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/tenants/{slug}/projects/{project_id}/assets/{asset_id}/revisions:
get:
tags:
- Annotations
summary: List Asset Revisions
description: 'List an asset''s commits (newest first). One entry per submit/approve/reject
boundary, with who committed it and how many annotations it captured.'
operationId: annotations-list_asset_revisions
security:
- HTTPBearer: []
parameters:
- name: asset_id
in: path
required: true
schema:
type: string
format: uuid
title: Asset Id
- name: slug
in: path
required: true
schema:
type: string
title: Slug
- name: project_id
in: path
required: true
schema:
type: string
format: uuid
title: Project Id
- name: limit
in: query
required: false
schema:
type: integer
maximum: 100
minimum: 1
description: Max rows per page.
default: 50
title: Limit
description: Max rows per page.
- name: cursor
in: query
required: false
schema:
anyOf:
- type: string
- type: 'null'
description: Opaque pagination cursor from a previous response's `next_cursor`; omit for the first page.
title: Cursor
description: Opaque pagination cursor from a previous response's `next_cursor`; omit for the first page.
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/RevisionSummaryPage'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
'401':
description: Unauthenticated — missing, malformed, or expired Bearer token
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Authenticated but not authorized for this resource
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Resource not found in this tenant
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'409':
description: Conflict — resource state prevents this action
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'429':
description: Rate-limited (per-tenant token bucket)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/tenants/{slug}/projects/{project_id}/assets/{asset_id}/revisions/{seq}:
get:
tags:
- Annotations
summary: Get Asset Revision
description: 'The full annotation snapshot at one commit — what the editor renders to
view or diff a past state.'
operationId: annotations-get_asset_revision
security:
- HTTPBearer: []
parameters:
- name: asset_id
in: path
required: true
schema:
type: string
format: uuid
title: Asset Id
- name: seq
in: path
required: true
schema:
type: integer
minimum: 1
title: Seq
- name: slug
in: path
required: true
schema:
type: string
title: Slug
- name: project_id
in: path
required: true
schema:
type: string
format: uuid
title: Project Id
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/RevisionDetail'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
'401':
description: Unauthenticated — missing, malformed, or expired Bearer token
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Authenticated but not authorized for this resource
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Resource not found in this tenant
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'409':
description: Conflict — resource state prevents this action
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'429':
description: Rate-limited (per-tenant token bucket)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/tenants/{slug}/projects/{project_id}/annotations/{annotation_id}/revisions:
get:
tags:
- Annotations
summary: List Annotation Revisions
description: 'One shape''s state at each commit it appeared in (newest first) — the
GitHub-blame timeline for a single annotation.'
operationId: annotations-list_annotation_revisions
security:
- HTTPBearer: []
parameters:
- name: annotation_id
in: path
required: true
schema:
type: string
format: uuid
title: Annotation Id
- name: slug
in: path
required: true
schema:
type: string
title: Slug
- name: project_id
in: path
required: true
schema:
type: string
format: uuid
title: Project Id
- name: limit
in: query
required: false
schema:
type: integer
maximum: 100
minimum: 1
description: Max rows per page.
default: 50
title: Limit
description: Max rows per page.
- name: cursor
in: query
required: false
schema:
anyOf:
- type: string
- type: 'null'
description: Opaque pagination cursor from a previous response's `next_cursor`; omit for the first page.
title: Cursor
description: Opaque pagination cursor from a previous response's `next_cursor`; omit for the first page.
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/AnnotationBlamePage'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
'401':
description: Unauthenticated — missing, malformed, or expired Bearer token
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Authenticated but not authorized for this resource
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Resource not found in this tenant
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'409':
description: Conflict — resource state prevents this action
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'429':
description: Rate-limited (per-tenant token bucket)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
components:
schemas:
ErrorResponse:
type: object
required:
- error
properties:
error:
type: object
required:
- code
- message
properties:
code:
$ref: '#/components/schemas/ErrorCode'
message:
type: string
description: Human-readable; free to evolve. Don't pattern-match on this.
hint:
type: string
nullable: true
# --- truncated at 32 KB (76 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/superb-ai/refs/heads/main/openapi/superb-ai-annotations-api-openapi.yml