Annotation
A drawing or comment-anchor placed on a file — a shape on an image, or a moment in a video. Create places the anchor; commenting on it is a separate message (POST /messages with annotationId), and the first comment is what creates the annotation's comment thread. Read the thread with ?expand=messages.
List Annotations
List annotations. Returns a paginated envelope (data, total, limit, hasMore, nextCursor). Filterable by 6 fields. Ordered by createdAt unless you pass sort.
Required scope: annotations:read
query Parameters
sortField to sort by. Prefix with - for descending (-createdAt); a createdAt:desc / createdAt:asc suffix works too, but never both markers at once. Default: createdAt.
cursorOpaque cursor for the next page (the envelope nextCursor).
limitItems per page (1–200, default 50). A larger value is clamped to the cap rather than rejected, so always follow nextCursor instead of assuming one page held everything.
includeTotalWhen true, the response envelope includes the total number of matching rows. Omit it for cheaper pagination.
expandComma-separated relations to inline (see Expanding objects above). Valid values are listed in the enum.
fileId[eq]Filter where fileId equals.
fileId[in]Filter where fileId is one of (comma-separated list).
taskId[eq]Filter where taskId equals.
taskId[in]Filter where taskId is one of (comma-separated list).
videoTimeSeconds[eq]Filter where videoTimeSeconds equals.
videoTimeSeconds[gt]Filter where videoTimeSeconds is greater than.
videoTimeSeconds[gte]Filter where videoTimeSeconds is greater than or equal to.
videoTimeSeconds[lt]Filter where videoTimeSeconds is less than.
videoTimeSeconds[lte]Filter where videoTimeSeconds is less than or equal to.
videoTimeSeconds[null]Filter where videoTimeSeconds is null (pass true).
videoTimeSeconds[notNull]Filter where videoTimeSeconds is not null (pass true).
type[eq]Filter where type equals.
type[in]Filter where type is one of (comma-separated list).
createdAt[gt]Filter where createdAt is greater than.
createdAt[gte]Filter where createdAt is greater than or equal to.
createdAt[lt]Filter where createdAt is less than.
createdAt[lte]Filter where createdAt is less than or equal to.
updatedAt[gt]Filter where updatedAt is greater than.
updatedAt[gte]Filter where updatedAt is greater than or equal to.
updatedAt[lt]Filter where updatedAt is less than.
updatedAt[lte]Filter where updatedAt is less than or equal to.
List Annotations › Responses
OK
The page of results.
totalTotal rows matching the query (across pages).
limithasMorenextCursorOpaque cursor for the next page; null on the last page.
Create Annotation
Create an Annotation. Server-assigned fields are ignored if sent.
Required scope: annotations:write
query Parameters
expandComma-separated relations to inline (see Expanding objects above). Valid values are listed in the enum.
Headers
Idempotency-KeyOptional replay key (see Idempotent requests above).
Create Annotation › Request Body
typeAnnotation kind: image or video.
fileIdThe file this annotation is drawn on. Required and immutable.
Where the annotation sits on an image: the shape kind (POINT, RECTANGLE or OVAL) plus x / y / width / height. All four are PERCENTAGES of the file's own dimensions (0–100), not pixels, so an annotation keeps its place at any display size. A POINT needs only x and y. Empty for a bare anchor.
videoTimeSecondsPlayback position in seconds for a video annotation. Null for image annotations.
Create Annotation › Responses
Created
idUnique identifier — an opaque string; never parse or generate one.
createdAtCreation timestamp.
typeAnnotation kind: image or video.
fileIdThe file this annotation is drawn on. Required and immutable.
updatedAtLast update timestamp.
createdByActorIdWho created this record — a person, an agent, an automation or the system itself. Read-only, stamped by the server on writes made through this API, and null on records created any other way, so treat it as present-or-null rather than always populated. This is an actor id (a UUID), not a member id: look it up with GET /actors/{id}, whose memberId gives you the person to use against /members.
updatedByActorIdWho last wrote to this record — a person, an agent, an automation or the system itself. Read-only, stamped by the server on writes made through this API, and null on records last written any other way, so treat it as present-or-null rather than always populated. This is an actor id (a UUID), not a member id: look it up with GET /actors/{id}, whose memberId gives you the person to use against /members.
createdByActorTypeThe creator actor's type (human, agent, cron, recurringTask, automation, outboxRetry, systemDefault). Server-derived from actors.type; read-only, not directly writable.
updatedByActorTypeThe last writer actor's type (human, agent, cron, recurringTask, automation, outboxRetry, systemDefault). Server-derived from actors.type via the row's updatedByActorId; read-only, not directly writable.
Where the annotation sits on an image: the shape kind (POINT, RECTANGLE or OVAL) plus x / y / width / height. All four are PERCENTAGES of the file's own dimensions (0–100), not pixels, so an annotation keeps its place at any display size. A POINT needs only x and y. Empty for a bare anchor.
videoTimeSecondsPlayback position in seconds for a video annotation. Null for image annotations.
taskIdThe task that holds this annotation's comment thread. Created automatically when someone comments on the annotation in the Nifty app; null until then.
Messages threaded under this annotation — what the app calls its comments. Populated only when you ask for it with ?expand=messages; also reachable as GET /messages?annotationId=....
The related File, present only when you pass ?expand=file.
The related Task, present only when you pass ?expand=task.
The related Actor, present only when you pass ?expand=createdByActor.
The related Actor, present only when you pass ?expand=updatedByActor.
Get Annotation
Retrieve a single Annotation by id.
Required scope: annotations:read
path Parameters
id^[0-9A-Za-z_!]+$ · requiredId of the Annotation.
query Parameters
expandComma-separated relations to inline (see Expanding objects above). Valid values are listed in the enum.
Get Annotation › Responses
OK
idUnique identifier — an opaque string; never parse or generate one.
createdAtCreation timestamp.
typeAnnotation kind: image or video.
fileIdThe file this annotation is drawn on. Required and immutable.
updatedAtLast update timestamp.
createdByActorIdWho created this record — a person, an agent, an automation or the system itself. Read-only, stamped by the server on writes made through this API, and null on records created any other way, so treat it as present-or-null rather than always populated. This is an actor id (a UUID), not a member id: look it up with GET /actors/{id}, whose memberId gives you the person to use against /members.
updatedByActorIdWho last wrote to this record — a person, an agent, an automation or the system itself. Read-only, stamped by the server on writes made through this API, and null on records last written any other way, so treat it as present-or-null rather than always populated. This is an actor id (a UUID), not a member id: look it up with GET /actors/{id}, whose memberId gives you the person to use against /members.
createdByActorTypeThe creator actor's type (human, agent, cron, recurringTask, automation, outboxRetry, systemDefault). Server-derived from actors.type; read-only, not directly writable.
updatedByActorTypeThe last writer actor's type (human, agent, cron, recurringTask, automation, outboxRetry, systemDefault). Server-derived from actors.type via the row's updatedByActorId; read-only, not directly writable.
Where the annotation sits on an image: the shape kind (POINT, RECTANGLE or OVAL) plus x / y / width / height. All four are PERCENTAGES of the file's own dimensions (0–100), not pixels, so an annotation keeps its place at any display size. A POINT needs only x and y. Empty for a bare anchor.
videoTimeSecondsPlayback position in seconds for a video annotation. Null for image annotations.
taskIdThe task that holds this annotation's comment thread. Created automatically when someone comments on the annotation in the Nifty app; null until then.
Messages threaded under this annotation — what the app calls its comments. Populated only when you ask for it with ?expand=messages; also reachable as GET /messages?annotationId=....
The related File, present only when you pass ?expand=file.
The related Task, present only when you pass ?expand=task.
The related Actor, present only when you pass ?expand=createdByActor.
The related Actor, present only when you pass ?expand=updatedByActor.
Delete Annotation
Permanently delete this Annotation. This cannot be undone. The annotation's comment thread is deleted with it.
Required scope: annotations:delete
path Parameters
id^[0-9A-Za-z_!]+$ · requiredId of the Annotation.
Headers
Idempotency-KeyOptional replay key (see Idempotent requests above).
Delete Annotation › Responses
No Content
Update Annotation
Partially update an Annotation. Only the fields you send are changed.
Required scope: annotations:write
path Parameters
id^[0-9A-Za-z_!]+$ · requiredId of the Annotation.
query Parameters
expandComma-separated relations to inline (see Expanding objects above). Valid values are listed in the enum.
Headers
Idempotency-KeyOptional replay key (see Idempotent requests above).
Update Annotation › Request Body
Where the annotation sits on an image: the shape kind (POINT, RECTANGLE or OVAL) plus x / y / width / height. All four are PERCENTAGES of the file's own dimensions (0–100), not pixels, so an annotation keeps its place at any display size. A POINT needs only x and y. Empty for a bare anchor.
videoTimeSecondsPlayback position in seconds for a video annotation. Null for image annotations.
expectedUpdatedAtOptional concurrency guard: the updatedAt you last read. If the resource has changed since, the update is rejected with 409 instead of overwriting the other writer. Re-read, re-derive your change from the current values, and retry with the fresh updatedAt.
Update Annotation › Responses
OK
idUnique identifier — an opaque string; never parse or generate one.
createdAtCreation timestamp.
typeAnnotation kind: image or video.
fileIdThe file this annotation is drawn on. Required and immutable.
updatedAtLast update timestamp.
createdByActorIdWho created this record — a person, an agent, an automation or the system itself. Read-only, stamped by the server on writes made through this API, and null on records created any other way, so treat it as present-or-null rather than always populated. This is an actor id (a UUID), not a member id: look it up with GET /actors/{id}, whose memberId gives you the person to use against /members.
updatedByActorIdWho last wrote to this record — a person, an agent, an automation or the system itself. Read-only, stamped by the server on writes made through this API, and null on records last written any other way, so treat it as present-or-null rather than always populated. This is an actor id (a UUID), not a member id: look it up with GET /actors/{id}, whose memberId gives you the person to use against /members.
createdByActorTypeThe creator actor's type (human, agent, cron, recurringTask, automation, outboxRetry, systemDefault). Server-derived from actors.type; read-only, not directly writable.
updatedByActorTypeThe last writer actor's type (human, agent, cron, recurringTask, automation, outboxRetry, systemDefault). Server-derived from actors.type via the row's updatedByActorId; read-only, not directly writable.
Where the annotation sits on an image: the shape kind (POINT, RECTANGLE or OVAL) plus x / y / width / height. All four are PERCENTAGES of the file's own dimensions (0–100), not pixels, so an annotation keeps its place at any display size. A POINT needs only x and y. Empty for a bare anchor.
videoTimeSecondsPlayback position in seconds for a video annotation. Null for image annotations.
taskIdThe task that holds this annotation's comment thread. Created automatically when someone comments on the annotation in the Nifty app; null until then.
Messages threaded under this annotation — what the app calls its comments. Populated only when you ask for it with ?expand=messages; also reachable as GET /messages?annotationId=....
The related File, present only when you pass ?expand=file.
The related Task, present only when you pass ?expand=task.
The related Actor, present only when you pass ?expand=createdByActor.
The related Actor, present only when you pass ?expand=updatedByActor.