Canvases
A canvas is the core workspace in Canvus. It is an infinite, zoomable surface where users place and arrange content -- notes, images, videos, PDFs, browser windows, connectors, and more. Every piece of content on a canvas is a widget.
Canvases live inside folders (see Canvas Folders). Each canvas has an owner, a set of permissions, and optional shared link access. Canvases can operate in normal mode or demo mode, which allows saving and restoring a snapshot of the canvas state for repeatable presentations.
All endpoints below are prefixed with /api/v1.
Authentication
Most canvas endpoints require a Private-Token header containing a valid API access token.
Private-Token: YOUR_TOKEN
Exception -- shared links: If a canvas has its link_permission set to view or edit, the Private-Token header may be omitted. In that case, access is granted as the Guest user with the corresponding permission level. If the Guest user is blocked on the server, unauthenticated access is unavailable. If a valid token is provided alongside a shared link, the authenticated user's permissions apply, but are never lower than the link permission.
Streaming (Long-Polling)
GET endpoints that list this as supported accept a ?subscribe query parameter. When present, the server holds the connection open and streams JSON updates as newline-delimited JSON, with keepalive pings at a configurable interval (default 15 seconds). See the Streaming documentation for details.
Canvas Object
Every canvas returned by the API includes these fields:
id(string) -- UUID identifying the canvasname(string) -- display namefolder_id(string) -- ID of the parent folderaccess(string) -- the requesting user's effective permission (owner,edit,view,none)mode(string) --normalordemostate(string) -- canvas state (normal)in_trash(boolean) -- whether the canvas is in the trashasset_size(integer) -- total size of assets on the canvas in bytespreview_hash(string) -- hash of the preview image, empty string if no preview existscreated_at(string) -- ISO 8601 creation timestampmodified_at(string) -- ISO 8601 last-modified timestamp
List Canvases
Returns all canvases visible to the authenticated user.
GET /api/v1/canvases
- Authentication: Required
- Streaming: Supported
Query parameters:
subscribe(boolean, optional) -- enable streaming
curl example:
curl -H "Private-Token: YOUR_TOKEN" \
https://canvus.example.com/api/v1/canvases
Response: 200 OK
[
{
"access": "owner",
"asset_size": 0,
"created_at": "2025-03-15T09:12:04.426Z",
"folder_id": "1034",
"id": "020b063d-0086-49a5-8dd0-965b8e117216",
"in_trash": false,
"mode": "normal",
"modified_at": "2025-03-15T09:12:04.426Z",
"name": "Q1 Planning",
"preview_hash": "a3f8c91b2e07",
"state": "normal"
},
{
"access": "edit",
"asset_size": 52428800,
"created_at": "2025-03-10T14:30:00.000Z",
"folder_id": "1034",
"id": "9c21f153-ac8b-4ad3-83c5-60c282ee9359",
"in_trash": false,
"mode": "demo",
"modified_at": "2025-03-14T16:45:22.100Z",
"name": "Showroom Demo",
"preview_hash": "f7e2d4a8b103",
"state": "normal"
}
]
Error responses:
401 Unauthorized-- missing or invalid token
Get a Single Canvas
Returns details for one canvas.
GET /api/v1/canvases/:canvas_id
- Authentication: Required (unless canvas has a shared link)
- Streaming: Supported
Path parameters:
canvas-id(uuid, required) -- the canvas ID
Query parameters:
subscribe(boolean, optional) -- enable streaming
curl example:
curl -H "Private-Token: YOUR_TOKEN" \
https://canvus.example.com/api/v1/canvases/020b063d-0086-49a5-8dd0-965b8e117216
Response: 200 OK
{
"access": "owner",
"asset_size": 0,
"created_at": "2025-03-15T09:12:04.426Z",
"folder_id": "1034",
"id": "020b063d-0086-49a5-8dd0-965b8e117216",
"in_trash": false,
"mode": "normal",
"modified_at": "2025-03-15T09:12:04.426Z",
"name": "Q1 Planning",
"preview_hash": "a3f8c91b2e07",
"state": "normal"
}
Error responses:
401 Unauthorized-- missing or invalid token (and no shared link)404 Not Found-- canvas does not exist
Get Canvas Preview
Downloads the canvas preview image as a file, if one has been generated. Preview images are created automatically by connected Canvus clients.
GET /api/v1/canvases/:canvas_id/preview
- Authentication: Required (unless canvas has a shared link)
- Streaming: Not supported
Path parameters:
canvas-id(uuid, required) -- the canvas ID
curl example:
curl -H "Private-Token: YOUR_TOKEN" -o preview.png \
https://canvus.example.com/api/v1/canvases/020b063d-0086-49a5-8dd0-965b8e117216/preview
Response: 200 OK with binary image data and Content-Disposition header.
If no preview is available:
{
"msg": "Canvas 020b063d-0086-49a5-8dd0-965b8e117216 doesn't have preview"
}
Error responses:
401 Unauthorized-- missing or invalid token (and no shared link)404 Not Found-- canvas does not exist
Create a Canvas
Creates a new canvas. If no folder_id is specified, the canvas is created in the authenticated user's home folder.
POST /api/v1/canvases
- Authentication: Required
- Streaming: Not supported
Request body (JSON):
name(string, optional) -- name for the new canvas. Server assigns a default name if omittedfolder_id(string, optional) -- ID of the parent folderwidth(number, optional) -- canvas width in pixels. Server uses a default if omitted.height(number, optional) -- canvas height in pixels. Server uses a default if omitted.
curl example:
curl -X POST \
-H "Private-Token: YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "Sprint Retro", "folder_id": "b574c9f9-2717-4c95-b6dd-c48d146c28f3"}' \
https://canvus.example.com/api/v1/canvases
Response: 200 OK
{
"access": "owner",
"asset_size": 0,
"created_at": "2025-03-20T10:00:00.000Z",
"folder_id": "b574c9f9-2717-4c95-b6dd-c48d146c28f3",
"id": "70c54ca9-a31d-45d8-af84-bacc9b708caf",
"in_trash": false,
"mode": "normal",
"modified_at": "2025-03-20T10:00:00.000Z",
"name": "Sprint Retro",
"preview_hash": "",
"state": "normal"
}
Error responses:
401 Unauthorized-- missing or invalid token403 Forbidden-- insufficient permissions on target folder
Update a Canvas
Renames a canvas or changes its mode between normal and demo. You cannot change folder_id with this endpoint; use Move Canvas or Copy Canvas instead.
PATCH /api/v1/canvases/:canvas_id
- Authentication: Required
- Streaming: Not supported
Path parameters:
canvas-id(uuid, required) -- the canvas ID
Request body (JSON):
name(string, optional) -- new name for the canvasmode(string, optional) --normalordemo
Mode values:
normal-- canvas is a regular canvasdemo-- canvas is a demo canvas (supports save/restore)
curl example:
curl -X PATCH \
-H "Private-Token: YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "Q1 Planning - Final", "mode": "demo"}' \
https://canvus.example.com/api/v1/canvases/020b063d-0086-49a5-8dd0-965b8e117216
Response: 200 OK
{
"access": "owner",
"asset_size": 0,
"created_at": "2025-03-15T09:12:04.426Z",
"folder_id": "1034",
"id": "020b063d-0086-49a5-8dd0-965b8e117216",
"in_trash": false,
"mode": "demo",
"modified_at": "2025-03-20T11:30:00.000Z",
"name": "Q1 Planning - Final",
"preview_hash": "a3f8c91b2e07",
"state": "normal"
}
Error responses:
401 Unauthorized-- missing or invalid token403 Forbidden-- insufficient permissions404 Not Found-- canvas does not exist
Delete a Canvas
Permanently deletes a canvas and all of its contents. This action is irreversible. To move a canvas to the trash instead (recoverable), see Trash a Canvas.
DELETE /api/v1/canvases/:canvas_id
- Authentication: Required
- Streaming: Not supported
Path parameters:
canvas-id(uuid, required) -- the canvas ID
curl example:
curl -X DELETE \
-H "Private-Token: YOUR_TOKEN" \
https://canvus.example.com/api/v1/canvases/020b063d-0086-49a5-8dd0-965b8e117216
Response: 200 OK (empty body)
Error responses:
401 Unauthorized-- missing or invalid token403 Forbidden-- insufficient permissions404 Not Found-- canvas does not exist
Move Canvas
Moves a canvas to a different folder.
POST /api/v1/canvases/:canvas_id/move
- Authentication: Required
- Streaming: Not supported
Path parameters:
canvas-id(uuid, required) -- the canvas to move
Request body (JSON):
folder_id(string, required) -- the destination folder IDconflicts(string, optional) -- conflict resolution strategy (default:skip)
Conflict resolution values:
skip-- synonym forcancel(default)cancel-- cancel the operation if a name conflict exists in the destinationreplace-- replace the conflicting canvas in the destination
curl example:
curl -X POST \
-H "Private-Token: YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"folder_id": "47c0e2cb-a299-4f3b-ac9a-810cc7c242d3", "conflicts": "replace"}' \
https://canvus.example.com/api/v1/canvases/020b063d-0086-49a5-8dd0-965b8e117216/move
Response: 200 OK
{
"access": "owner",
"asset_size": 0,
"created_at": "2025-03-15T09:12:04.426Z",
"folder_id": "47c0e2cb-a299-4f3b-ac9a-810cc7c242d3",
"id": "020b063d-0086-49a5-8dd0-965b8e117216",
"in_trash": false,
"mode": "normal",
"modified_at": "2025-03-15T09:12:04.426Z",
"name": "Q1 Planning",
"preview_hash": "a3f8c91b2e07",
"state": "normal"
}
Error responses:
401 Unauthorized-- missing or invalid token403 Forbidden-- insufficient permissions on source or destination404 Not Found-- canvas or folder does not exist409 Conflict-- name conflict andconflictsiscancelorskip
Copy Canvas
Copies a canvas to another folder. All widgets and assets are duplicated. Copying a canvas to the same folder it already lives in creates a duplicate.
POST /api/v1/canvases/:canvas_id/copy
- Authentication: Required
- Streaming: Not supported
Path parameters:
canvas-id(uuid, required) -- the canvas to copy
Request body (JSON):
folder_id(string, required) -- the destination folder IDconflicts(string, optional) -- conflict resolution strategy (default:skip)
Conflict resolution values:
skip-- synonym forcancel(default)cancel-- cancel the operation if a name conflict exists in the destinationreplace-- replace the conflicting canvas in the destination
curl example:
curl -X POST \
-H "Private-Token: YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"folder_id": "47c0e2cb-a299-4f3b-ac9a-810cc7c242d3"}' \
https://canvus.example.com/api/v1/canvases/020b063d-0086-49a5-8dd0-965b8e117216/copy
Response: 200 OK -- returns the newly created canvas object.
{
"access": "owner",
"asset_size": 0,
"created_at": "2025-03-20T12:00:00.000Z",
"folder_id": "47c0e2cb-a299-4f3b-ac9a-810cc7c242d3",
"id": "c4a91e3f-7b2d-48a0-9f15-3e8d72c1a5b6",
"in_trash": false,
"mode": "normal",
"modified_at": "2025-03-20T12:00:00.000Z",
"name": "Q1 Planning",
"preview_hash": "",
"state": "normal"
}
Error responses:
401 Unauthorized-- missing or invalid token403 Forbidden-- insufficient permissions404 Not Found-- canvas or folder does not exist409 Conflict-- name conflict andconflictsiscancelorskip
Trash a Canvas
Moves a canvas to the user's trash folder. This is a soft delete -- the canvas can be restored by moving it back out of trash. Use the Move Canvas endpoint with the trash folder ID.
The conflicts parameter is ignored when moving to trash. You cannot move items to another user's trash folder.
POST /api/v1/canvases/:canvas_id/move
- Authentication: Required
- Streaming: Not supported
Path parameters:
canvas-id(uuid, required) -- the canvas to trash
Request body (JSON):
folder_id(string, required) -- the trash folder ID (format:trash.<user-id>)
curl example:
curl -X POST \
-H "Private-Token: YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"folder_id": "trash.1034"}' \
https://canvus.example.com/api/v1/canvases/020b063d-0086-49a5-8dd0-965b8e117216/move
Response: 200 OK
{
"access": "owner",
"asset_size": 0,
"created_at": "2025-03-15T09:12:04.426Z",
"folder_id": "trash.1034",
"id": "020b063d-0086-49a5-8dd0-965b8e117216",
"in_trash": true,
"mode": "normal",
"modified_at": "2025-03-15T09:12:04.426Z",
"name": "Q1 Planning",
"preview_hash": "a3f8c91b2e07",
"state": "normal"
}
Permissions
Canvas permissions control who can view, edit, or manage a canvas. Permissions are assigned per-user or per-group, and optionally via shared links.
Permission Levels
none-- no accessview-- read-only accessedit-- can modify canvas contentowner-- full control including permission management and deletion
Get Canvas Permissions
Returns the permission configuration for a canvas, including per-user overrides, per-group overrides, and the shared link setting.
GET /api/v1/canvases/:canvas_id/permissions
- Authentication: Required
- Streaming: Supported
Path parameters:
canvas-id(uuid, required) -- the canvas ID
Query parameters:
subscribe(boolean, optional) -- enable streaming
curl example:
curl -H "Private-Token: YOUR_TOKEN" \
https://canvus.example.com/api/v1/canvases/9c21f153-ac8b-4ad3-83c5-60c282ee9359/permissions
Response: 200 OK
{
"editors_can_share": true,
"link_permission": "none",
"users": [
{
"id": 1034,
"inherited": false,
"permission": "owner"
},
{
"id": 1050,
"inherited": true,
"permission": "view"
}
],
"groups": [
{
"id": 5,
"inherited": false,
"permission": "edit"
}
]
}
Response fields:
editors_can_share(boolean) -- when true, users with edit access can also modify permissionslink_permission(string) -- shared link permission level (none,view, oredit)users(array) -- per-user permission overridesid(integer) -- user IDinherited(boolean) -- whether this permission is inherited from the parent folderpermission(string) -- permission levelgroups(array) -- per-group permission overridesid(integer) -- group IDinherited(boolean) -- whether this permission is inherited from the parent folderpermission(string) -- permission level
Tip: The access field on the canvas object itself provides a quick way to check the requesting user's effective permission without calling this endpoint.
Error responses:
401 Unauthorized-- missing or invalid token404 Not Found-- canvas does not exist
Set Canvas Permissions
Replaces the permission configuration for a canvas. You can set per-user permissions, per-group permissions, shared link access, and whether editors can share.
POST /api/v1/canvases/:canvas_id/permissions
- Authentication: Required
- Streaming: Not supported
Path parameters:
canvas-id(uuid, required) -- the canvas ID
Request body (JSON):
editors_can_share(boolean, optional) -- whether users with edit access can change permissionslink_permission(string, optional) -- shared link permission:none,view, oreditusers(array, optional) -- per-user permission overridesgroups(array, optional) -- per-group permission overrides
Each entry in the users and groups arrays is an object with:
id(integer, required) -- the user or group IDpermission(string, required) -- one ofnone,view,edit, orowner
Link permission values:
none-- canvas is not shared via linkview-- anyone with the link can view (read-only)edit-- anyone with the link can edit
curl example:
curl -X POST \
-H "Private-Token: YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"editors_can_share": false,
"link_permission": "view",
"users": [{"id": 1050, "permission": "edit"}],
"groups": [{"id": 5, "permission": "view"}]
}' \
https://canvus.example.com/api/v1/canvases/9c21f153-ac8b-4ad3-83c5-60c282ee9359/permissions
Response: 200 OK
{
"editors_can_share": false,
"link_permission": "view",
"users": [
{
"id": 1034,
"inherited": false,
"permission": "owner"
},
{
"id": 1050,
"inherited": false,
"permission": "edit"
}
],
"groups": [
{
"id": 5,
"inherited": false,
"permission": "view"
}
]
}
Error responses:
401 Unauthorized-- missing or invalid token403 Forbidden-- insufficient permissions (must be owner or editor with sharing enabled)404 Not Found-- canvas does not exist
Shared Links
Shared links allow unauthenticated access to a canvas. The link format is:
https://canvus.example.com/open/<canvas-id>
To enable a shared link, set link_permission to view or edit using the Set Canvas Permissions endpoint. To revoke a shared link, set link_permission back to none.
When a shared link is active:
- API requests for that canvas can omit the
Private-Tokenheader - Unauthenticated access is granted as the Guest user with the link's permission level
- If the Guest user account is blocked on the server, shared link access is denied
- If a valid token is provided, the user gets whichever permission is higher: their own or the link permission
Color Presets
Color presets define the palette of colors available in the canvas UI for annotations (inking), note backgrounds, note text, and connectors. Each canvas has its own set of presets.
Get Color Presets
Returns the color presets configured for a canvas.
GET /api/v1/canvases/:canvas_id/color-presets
- Authentication: Required
- Streaming: Not supported
Path parameters:
canvas-id(uuid, required) -- the canvas ID
curl example:
curl -H "Private-Token: YOUR_TOKEN" \
https://canvus.example.com/api/v1/canvases/020b063d-0086-49a5-8dd0-965b8e117216/color-presets
Response: 200 OK
{
"annotation": ["#00338dff", "#005eb8ff", "#0091daff", "#470a68ff", "#6d2077ff", "#00a3a1ff"],
"connector": ["#00338dff", "#005eb8ff", "#0091daff", "#470a68ff", "#6d2077ff", "#00a3a1ff"],
"note_background": ["#00338dff", "#005eb8ff", "#0091daff", "#470a68ff", "#6d2077ff", "#00a3a1ff"],
"note_text": []
}
Response fields:
annotation(array of strings) -- hex color values for annotation/inking toolsconnector(array of strings) -- hex color values for connector linesnote_background(array of strings) -- hex color values for note backgroundsnote_text(array of strings) -- hex color values for note text
Colors use the format #RRGGBB or #RRGGBBAA (with alpha).
Error responses:
401 Unauthorized-- missing or invalid token404 Not Found-- canvas does not exist
Update Color Presets
Updates one or more color preset categories. Only the categories included in the request body are modified; omitted categories are left unchanged.
PATCH /api/v1/canvases/:canvas_id/color-presets
- Authentication: Required
- Streaming: Not supported
Path parameters:
canvas-id(uuid, required) -- the canvas ID
Request body (JSON):
annotation(array of strings, optional) -- inking color paletteconnector(array of strings, optional) -- connector color palettenote_background(array of strings, optional) -- note background color palettenote_text(array of strings, optional) -- note text color palette
curl example:
curl -X PATCH \
-H "Private-Token: YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"note_background": ["#ff6b6bff", "#4ecdc4ff", "#45b7d1ff", "#96e6a1ff"],
"annotation": ["#2d3436ff", "#636e72ff", "#b2bec3ff"]
}' \
https://canvus.example.com/api/v1/canvases/020b063d-0086-49a5-8dd0-965b8e117216/color-presets
Response: 200 OK -- returns the full color presets object with all categories.
{
"annotation": ["#2d3436ff", "#636e72ff", "#b2bec3ff"],
"connector": ["#00338dff", "#005eb8ff", "#0091daff", "#470a68ff", "#6d2077ff", "#00a3a1ff"],
"note_background": ["#ff6b6bff", "#4ecdc4ff", "#45b7d1ff", "#96e6a1ff"],
"note_text": []
}
Error responses:
401 Unauthorized-- missing or invalid token403 Forbidden-- insufficient permissions404 Not Found-- canvas does not exist
Canvas Background
The canvas background can be a solid color, an animated haze, or an uploaded image. An optional grid overlay can be enabled with any background type.
Get Canvas Background
Returns the current background configuration.
GET /api/v1/canvases/:canvas_id/background
- Authentication: Required (unless canvas has a shared link)
- Streaming: Not supported
Path parameters:
canvas-id(uuid, required) -- the canvas ID
curl example:
curl -H "Private-Token: YOUR_TOKEN" \
https://canvus.example.com/api/v1/canvases/020b063d-0086-49a5-8dd0-965b8e117216/background
Response: 200 OK
{
"type": "haze",
"haze": {
"color1": "#e0e0e0",
"color2": "#f0f0f0",
"speed": 0.5,
"scale": 1.0
},
"grid": {
"visible": true,
"color": "#cccccc"
},
"image": {
"hash": "",
"fit": "fill"
}
}
Response fields:
type(string) -- background type:solid_color,haze, orimagebackground_color(string) -- hex color, used when type issolid_colorhaze(object) -- haze animation settingscolor1(string) -- first gradient colorcolor2(string) -- second gradient colorspeed(number) -- animation speedscale(number) -- pattern scalegrid(object) -- grid overlay settingsvisible(boolean) -- whether the grid is showncolor(string) -- grid line colorimage(object) -- background image settingshash(string) -- asset hash of the uploaded imagefit(string) -- how the image fills the canvas (e.g.,fill)
Error responses:
401 Unauthorized-- missing or invalid token404 Not Found-- canvas does not exist
Update Canvas Background
Changes background settings such as type, color, haze parameters, or grid visibility.
PATCH /api/v1/canvases/:canvas_id/background
- Authentication: Required
- Streaming: Not supported
Path parameters:
canvas-id(uuid, required) -- the canvas ID
Request body (JSON):
type(string, required) --solid_color,haze, orimagebackground_color(string, optional) -- hex color for solid backgroundshaze(object, optional) -- haze settings (when type ishaze)grid(object, optional) -- grid overlay settings
curl example -- set solid color:
curl -X PATCH \
-H "Private-Token: YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"type": "solid_color", "background_color": "#1a1a2e"}' \
https://canvus.example.com/api/v1/canvases/020b063d-0086-49a5-8dd0-965b8e117216/background
curl example -- set haze with grid:
curl -X PATCH \
-H "Private-Token: YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"type": "haze",
"haze": {"color1": "#0f0c29", "color2": "#302b63", "speed": 0.3, "scale": 1.5},
"grid": {"visible": true, "color": "#ffffff22"}
}' \
https://canvus.example.com/api/v1/canvases/020b063d-0086-49a5-8dd0-965b8e117216/background
Response: 200 OK -- returns the full background configuration.
Error responses:
401 Unauthorized-- missing or invalid token403 Forbidden-- insufficient permissions404 Not Found-- canvas does not exist
Upload Background Image
Uploads an image file to use as the canvas background. This is a multipart request.
POST /api/v1/canvases/:canvas_id/background
- Authentication: Required
- Streaming: Not supported
Path parameters:
canvas-id(uuid, required) -- the canvas ID
Request body (multipart/form-data):
data(file, required) -- the image file to uploadjson(string, optional) -- JSON string with additional parameters such asfit
curl example:
curl -X POST \
-H "Private-Token: YOUR_TOKEN" \
-F "data=@background.jpg" \
-F 'json={"type": "image", "fit": "fill"}' \
https://canvus.example.com/api/v1/canvases/020b063d-0086-49a5-8dd0-965b8e117216/background
Response: 200 OK -- returns the updated background configuration.
Error responses:
401 Unauthorized-- missing or invalid token403 Forbidden-- insufficient permissions404 Not Found-- canvas does not exist
Demo Canvas Operations
Demo mode allows saving a snapshot of a canvas and restoring it later. This is useful for trade show demos, training sessions, or any scenario where you want to return a canvas to a known state after users have interacted with it.
To enable demo mode, set the canvas mode to demo using the Update a Canvas endpoint.
Save Demo State
Captures the current state of a demo canvas as a snapshot. This overwrites any previously saved state.
POST /api/v1/canvases/:canvas_id/save
- Authentication: Required
- Streaming: Not supported
Path parameters:
canvas-id(uuid, required) -- the canvas ID (must be a demo canvas)
curl example:
curl -X POST \
-H "Private-Token: YOUR_TOKEN" \
https://canvus.example.com/api/v1/canvases/9c21f153-ac8b-4ad3-83c5-60c282ee9359/save
Response: 200 OK (empty body)
Error responses:
401 Unauthorized-- missing or invalid token403 Forbidden-- insufficient permissions404 Not Found-- canvas does not exist
Restore Demo State
Restores a demo canvas to its last saved state. All changes made since the last save are discarded.
POST /api/v1/canvases/:canvas_id/restore
- Authentication: Required
- Streaming: Not supported
Path parameters:
canvas-id(uuid, required) -- the canvas ID (must be a demo canvas)
curl example:
curl -X POST \
-H "Private-Token: YOUR_TOKEN" \
https://canvus.example.com/api/v1/canvases/9c21f153-ac8b-4ad3-83c5-60c282ee9359/restore
Response: 200 OK (empty body)
Error responses:
401 Unauthorized-- missing or invalid token403 Forbidden-- insufficient permissions404 Not Found-- canvas does not exist