Skip to content

Annotations

Annotations are freehand pen strokes drawn on top of another widget or directly on the canvas. Each annotation belongs to a single parent -- a Note, Image, Video, PDF, Browser, Anchor, Table, VideoInput, IpVideo, or RdpConnection widget, or the canvas itself (the SharedCanvas root). Use annotations for markup, highlighting, or freehand drawing over existing content.

Unlike other widgets, annotations do not have location, size, scale, or pinned properties -- their geometry is entirely described by the points field, in the parent's coordinate space.

Authentication

All endpoints require authentication via the Private-Token header or a CanvusSession cookie, unless the canvas has link sharing enabled (View or Edit permission). Write operations (POST, PATCH, DELETE) require edit access. View-only users receive 403 Forbidden on any write attempt.

Annotation properties

  • id -- string (uuid, read-only). Unique identifier assigned by the server on creation.
  • widget_type -- string (read-only). Always "Annotation".
  • parent_id -- string (read-only). ID of the parent widget the annotation is drawn on, or the canvas root ID for annotations created directly on the SharedCanvas.
  • points -- string or array (patchable). The stroke geometry: a base64-encoded Float32Array, or a JSON array of arrays, with 9 floats per node. Required on create; on PATCH, replaces the entire stroke.
  • line_color -- string (patchable). Hex color code including alpha, e.g. "#ff0000ff". Defaults to "#000000ff" if omitted on create.
  • page -- integer (patchable). Page number the annotation belongs to. Only valid when the parent is a PDF widget -- setting it on any other parent type returns 400 Bad Request. Omitted from responses when not applicable.
  • depth -- number, float (read-only). Z-order value. Not settable via create or PATCH.

Streaming

All GET endpoints support real-time updates via the ?subscribe query parameter, the same as other widget types. See Streaming for details.


List annotations

Retrieves all annotations on a parent widget, or on the canvas itself.

GET /api/v1/canvases/:canvas_id/:parent_type/:parent_id/annotations
GET /api/v1/canvases/:canvas_id/shared-canvas/annotations

Path parameters:

  • canvas_id (uuid, required) -- ID of the canvas
  • parent_type (string, required) -- One of notes, images, browsers, videos, pdfs, anchors, video-inputs, ip-videos, rdp-connections, tables
  • parent_id (uuid, required) -- ID of the parent widget

Query parameters:

  • subscribe (boolean, optional) -- Enable streaming updates

Example request:

curl -H "Private-Token: YOUR_TOKEN" \
  https://canvus.example.com/api/v1/canvases/78cfbcc8-aed9-4bbb-95ca-a0b9a5358d5a/notes/f77e17a2-3716-46e4-8143-97dde114b20b/annotations

Example response:

[
  {
    "depth": 1.0,
    "id": "3f9c2a3e-9b3a-4b2e-9f4d-6a8c1e2b5d70",
    "line_color": "#ff0000ff",
    "parent_id": "f77e17a2-3716-46e4-8143-97dde114b20b",
    "points": "AACAPwAAgD8AAAAAAAAAAAAAgD8AAIA/AAAAAAAAAAAAAIA/",
    "widget_type": "Annotation"
  }
]

Example request -- annotations on the canvas itself:

curl -H "Private-Token: YOUR_TOKEN" \
  https://canvus.example.com/api/v1/canvases/78cfbcc8-aed9-4bbb-95ca-a0b9a5358d5a/shared-canvas/annotations

Get single annotation

Retrieves a single annotation by ID.

GET /api/v1/canvases/:canvas_id/:parent_type/:parent_id/annotations/:annotation_id
GET /api/v1/canvases/:canvas_id/shared-canvas/annotations/:annotation_id

Path parameters:

  • canvas_id (uuid, required) -- ID of the canvas
  • parent_type (string, required) -- Parent widget type (see List Annotations)
  • parent_id (uuid, required) -- ID of the parent widget
  • annotation_id (uuid, required) -- ID of the annotation

Query parameters:

  • subscribe (boolean, optional) -- Enable streaming updates

Example request:

curl -H "Private-Token: YOUR_TOKEN" \
  https://canvus.example.com/api/v1/canvases/78cfbcc8-aed9-4bbb-95ca-a0b9a5358d5a/notes/f77e17a2-3716-46e4-8143-97dde114b20b/annotations/3f9c2a3e-9b3a-4b2e-9f4d-6a8c1e2b5d70

Example response:

{
  "depth": 1.0,
  "id": "3f9c2a3e-9b3a-4b2e-9f4d-6a8c1e2b5d70",
  "line_color": "#ff0000ff",
  "parent_id": "f77e17a2-3716-46e4-8143-97dde114b20b",
  "points": "AACAPwAAgD8AAAAAAAAAAAAAgD8AAIA/AAAAAAAAAAAAAIA/",
  "widget_type": "Annotation"
}

Create annotation

Creates a new annotation on the specified parent widget, or directly on the canvas.

POST /api/v1/canvases/:canvas_id/:parent_type/:parent_id/annotations
POST /api/v1/canvases/:canvas_id/shared-canvas/annotations

Path parameters:

  • canvas_id (uuid, required) -- ID of the canvas
  • parent_type (string, required) -- Parent widget type (see List Annotations)
  • parent_id (uuid, required) -- ID of the parent widget

Request body (JSON):

  • points (required) -- Stroke geometry. Either a base64-encoded Float32Array, or a JSON array of 9-float arrays (one array per node).
  • line_color (string, optional) -- Hex color code including alpha, e.g. "#ff0000ff". Defaults to "#000000ff".
  • page (integer, optional) -- Page number. Only valid when the parent is a PDF widget.

Example request -- base64 points:

curl -X POST \
  -H "Private-Token: YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"points": "AACAPwAAgD8AAAAAAAAAAAAAgD8AAIA/AAAAAAAAAAAAAIA/", "line_color": "#ff0000ff"}' \
  https://canvus.example.com/api/v1/canvases/78cfbcc8-aed9-4bbb-95ca-a0b9a5358d5a/notes/f77e17a2-3716-46e4-8143-97dde114b20b/annotations

Example request -- points as a JSON array (one node, 9 floats):

curl -X POST \
  -H "Private-Token: YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"points": [[0, 0, 0, 50, 50, 0, 0, 0, 0]], "line_color": "#ff0000ff"}' \
  https://canvus.example.com/api/v1/canvases/78cfbcc8-aed9-4bbb-95ca-a0b9a5358d5a/notes/f77e17a2-3716-46e4-8143-97dde114b20b/annotations

Example request -- annotation on a PDF page:

curl -X POST \
  -H "Private-Token: YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"points": [[0, 0, 0, 50, 50, 0, 0, 0, 0]], "page": 1}' \
  https://canvus.example.com/api/v1/canvases/78cfbcc8-aed9-4bbb-95ca-a0b9a5358d5a/pdfs/9b6f3c2a-1234-4de6-ad95-2c0ab7d47b70/annotations

Example response:

{
  "depth": 1.0,
  "id": "3f9c2a3e-9b3a-4b2e-9f4d-6a8c1e2b5d70",
  "line_color": "#ff0000ff",
  "parent_id": "f77e17a2-3716-46e4-8143-97dde114b20b",
  "points": "AACAPwAAgD8AAAAAAAAAAAAAgD8AAIA/AAAAAAAAAAAAAIA/",
  "widget_type": "Annotation"
}

Update annotation

Updates one or more properties of an existing annotation. The request body must contain at least one of points, line_color, or page -- an empty body returns 400 Bad Request.

PATCH /api/v1/canvases/:canvas_id/:parent_type/:parent_id/annotations/:annotation_id
PATCH /api/v1/canvases/:canvas_id/shared-canvas/annotations/:annotation_id

Path parameters:

  • canvas_id (uuid, required) -- ID of the canvas
  • parent_type (string, required) -- Parent widget type (see List Annotations)
  • parent_id (uuid, required) -- ID of the parent widget
  • annotation_id (uuid, required) -- ID of the annotation to update

Request body (JSON):

Any combination of: points, line_color, page.

Example request -- replace the stroke geometry:

curl -X PATCH \
  -H "Private-Token: YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"points": [[0, 0, 0, 100, 100, 0, 0, 0, 0]]}' \
  https://canvus.example.com/api/v1/canvases/78cfbcc8-aed9-4bbb-95ca-a0b9a5358d5a/notes/f77e17a2-3716-46e4-8143-97dde114b20b/annotations/3f9c2a3e-9b3a-4b2e-9f4d-6a8c1e2b5d70

Example request -- change color:

curl -X PATCH \
  -H "Private-Token: YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"line_color": "#00ff00ff"}' \
  https://canvus.example.com/api/v1/canvases/78cfbcc8-aed9-4bbb-95ca-a0b9a5358d5a/notes/f77e17a2-3716-46e4-8143-97dde114b20b/annotations/3f9c2a3e-9b3a-4b2e-9f4d-6a8c1e2b5d70

Example response:

{
  "depth": 1.0,
  "id": "3f9c2a3e-9b3a-4b2e-9f4d-6a8c1e2b5d70",
  "line_color": "#00ff00ff",
  "parent_id": "f77e17a2-3716-46e4-8143-97dde114b20b",
  "points": "AACAPwAAgD8AAAAAAAAAAAAAgD8AAIA/AAAAAAAAAAAAAIA/",
  "widget_type": "Annotation"
}

Validation errors:

  • Empty PATCH body returns 400 Bad Request: PATCH body must contain at least one of: points, line_color, page
  • Setting page when the parent is not a PDF widget returns 400 Bad Request: page is only valid when the parent is a PDF widget

Delete annotation

Permanently removes an annotation.

DELETE /api/v1/canvases/:canvas_id/:parent_type/:parent_id/annotations/:annotation_id
DELETE /api/v1/canvases/:canvas_id/shared-canvas/annotations/:annotation_id

Path parameters:

  • canvas_id (uuid, required) -- ID of the canvas
  • parent_type (string, required) -- Parent widget type (see List Annotations)
  • parent_id (uuid, required) -- ID of the parent widget
  • annotation_id (uuid, required) -- ID of the annotation to delete

Example request:

curl -X DELETE \
  -H "Private-Token: YOUR_TOKEN" \
  https://canvus.example.com/api/v1/canvases/78cfbcc8-aed9-4bbb-95ca-a0b9a5358d5a/notes/f77e17a2-3716-46e4-8143-97dde114b20b/annotations/3f9c2a3e-9b3a-4b2e-9f4d-6a8c1e2b5d70

A successful deletion returns an empty response with status 200 OK.


Error responses

All endpoints return errors as JSON with a msg field.

  • 400 Bad Request -- Invalid or malformed points, page set on a non-PDF parent, or an empty PATCH body
  • 401 Unauthorized -- Missing or invalid authentication token
  • 403 Forbidden -- View-only user attempted a write operation
  • 404 Not Found -- Canvas, parent widget, or annotation does not exist, or the parent widget type does not accept annotations

Example error response:

{"msg": "page is only valid when the parent is a PDF widget"}