Skip to Content
APIResourcesCanvases

Canvases

Read canvases and apply revision-safe graph operations.

Base URL: https://app.gavana.ai/api/canvas-agent/v1 · Authentication: HTTP bearer, token format cba_<token-id>.<secret>

Operations

OperationPurposeScopes
GET /canvasesList accessible canvasescanvas:read
POST /canvasesCreate a canvas or resolve Agent Canvascanvas:read, canvas:write
GET /canvases/{canvasId}Get a complete canvas and its current revisioncanvas:read
GET /canvases/{canvasId}/nodes/{nodeId}Get one node with incoming and outgoing connectionscanvas:read
POST /canvases/{canvasId}/operationsValidate or apply one revision-safe operation batchcanvas:read
GET /canvases/{canvasId}/renderRender a canvas as SVGcanvas:read

GET /canvases

List accessible canvases

Owned and shared canvases are merged and ordered by updatedAt descending, then handle descending.

  • Operation id: listCanvases
  • Scopes: Requires canvas:read.
  • CLI equivalent: gavana canvas list

Parameters

ParameterInTypeRequiredNotes
limitqueryintegerNoMaximum number of canvases in this page. Canvas pages are capped at 25 because summaries are derived from complete graph documents. Default 25. min 1, max 25.
cursorquerystringNoOpaque continuation cursor from page.nextCursor. Reuse it with the same list filters. max length 8192.

Responses

StatusPayloadMeaning
200objectAccessible canvas summaries.
defaultErrorResponseA stable machine-readable error. The response always includes X-Request-ID.

200 response body

FieldTypeRequiredNotes
canvasesarray of CanvasSummaryYes—
canvases[].idstringYesPattern ^[A-Za-z0-9_-]{1,180}$.
canvases[].canvasTypestringNoOne of agent.
canvases[].handlestringYesPattern ^canvas:.
canvases[].ownerUidstringYesPattern ^[A-Za-z0-9_-]{1,180}$.
canvases[].titlestringYes—
canvases[].createdAtstring (date-time)Yes—
canvases[].updatedAtstring (date-time)Yes—
canvases[].revisionstringYes—
canvases[].accessRolestringNoOne of owner, editor, viewer.
canvases[].nodeCountintegerYesmin 0.
canvases[].connectionCountintegerYesmin 0.
pageCursorPageYes—
page.limitintegerYesmin 1, max 200.
page.hasMorebooleanYes—
page.nextCursorstring | nullYesmax length 8192.

Example

curl "https://app.gavana.ai/api/canvas-agent/v1/canvases" \ -H "Authorization: Bearer $GAVANA_AGENT_TOKEN"

POST /canvases

Create a canvas or resolve Agent Canvas

  • Operation id: createCanvas
  • Scopes: Requires canvas:read + canvas:write.
  • CLI equivalent: gavana canvas create

Request body (application/json, required)

FieldTypeRequiredNotes
idstringNoPattern ^[A-Za-z0-9_-]{1,180}$.
titlestringNomax length 160.
canvasTypestringNoOne of agent.
destinationstringNoOne of agent-canvas.

Responses

StatusPayloadMeaning
201CanvasResponseA complete canvas with its current revision.
defaultErrorResponseA stable machine-readable error. The response always includes X-Request-ID.

201 response body

FieldTypeRequiredNotes
canvasCanvasYes—
canvas.idstringYesPattern ^[A-Za-z0-9_-]{1,180}$.
canvas.canvasTypestringNoOne of agent.
canvas.handlestringYesPattern ^canvas:[A-Za-z0-9_-]+:[A-Za-z0-9_-]+$.
canvas.ownerUidstringYesPattern ^[A-Za-z0-9_-]{1,180}$.
canvas.titlestringYesmax length 160.
canvas.createdAtstring (date-time)Yes—
canvas.updatedAtstring (date-time)Yes—
canvas.revisionstringYesmin length 1.
canvas.nodesarray of CanvasNodeYes—
canvas.nodes[].idstringYesPattern ^[A-Za-z0-9_-]{1,180}$.
canvas.nodes[].handlestringYesPattern ^node:.
canvas.nodes[].typestringYesOne of image, video, text, sticky.
canvas.nodes[].titlestringYes—
canvas.nodes[].positionPositionYes—
canvas.nodes[].position.xnumberYesmin -10000000, max 10000000.
canvas.nodes[].position.ynumberYesmin -10000000, max 10000000.
canvas.nodes[].widthnumberYes—
canvas.nodes[].heightnumberYes—
canvas.nodes[].metadataobjectNo—
canvas.nodes[].assetstringNoPattern ^asset:.
canvas.connectionsarray of CanvasConnectionYes—
canvas.connections[].idstringYesPattern ^[A-Za-z0-9_-]{1,180}$.
canvas.connections[].handlestringYesPattern ^connection:.
canvas.connections[].fromNodeIdstringYesPattern ^[A-Za-z0-9_-]{1,180}$.
canvas.connections[].toNodeIdstringYesPattern ^[A-Za-z0-9_-]{1,180}$.
canvas.connections[].fromstringYesPattern ^node:.
canvas.connections[].tostringYesPattern ^node:.
activityarray of objectYes—

Example

curl -X POST "https://app.gavana.ai/api/canvas-agent/v1/canvases" \ -H "Authorization: Bearer $GAVANA_AGENT_TOKEN" \ -H "Content-Type: application/json" \ -d '{}'

GET /canvases/{canvasId}

Get a complete canvas and its current revision

  • Operation id: getCanvas
  • Scopes: Requires canvas:read.
  • CLI equivalent: gavana canvas get

Parameters

ParameterInTypeRequiredNotes
canvasIdpathstringYesPattern ^[A-Za-z0-9_-]{1,180}$.
ownerUidquerystringNoIdentifies the owner of a shared canvas or asset. Owner-qualified handles let the CLI supply it automatically. Pattern ^[A-Za-z0-9_-]{1,180}$.

Responses

StatusPayloadMeaning
200CanvasResponseA complete canvas with its current revision.
defaultErrorResponseA stable machine-readable error. The response always includes X-Request-ID.

200 response body

FieldTypeRequiredNotes
canvasCanvasYes—
canvas.idstringYesPattern ^[A-Za-z0-9_-]{1,180}$.
canvas.canvasTypestringNoOne of agent.
canvas.handlestringYesPattern ^canvas:[A-Za-z0-9_-]+:[A-Za-z0-9_-]+$.
canvas.ownerUidstringYesPattern ^[A-Za-z0-9_-]{1,180}$.
canvas.titlestringYesmax length 160.
canvas.createdAtstring (date-time)Yes—
canvas.updatedAtstring (date-time)Yes—
canvas.revisionstringYesmin length 1.
canvas.nodesarray of CanvasNodeYes—
canvas.nodes[].idstringYesPattern ^[A-Za-z0-9_-]{1,180}$.
canvas.nodes[].handlestringYesPattern ^node:.
canvas.nodes[].typestringYesOne of image, video, text, sticky.
canvas.nodes[].titlestringYes—
canvas.nodes[].positionPositionYes—
canvas.nodes[].position.xnumberYesmin -10000000, max 10000000.
canvas.nodes[].position.ynumberYesmin -10000000, max 10000000.
canvas.nodes[].widthnumberYes—
canvas.nodes[].heightnumberYes—
canvas.nodes[].metadataobjectNo—
canvas.nodes[].assetstringNoPattern ^asset:.
canvas.connectionsarray of CanvasConnectionYes—
canvas.connections[].idstringYesPattern ^[A-Za-z0-9_-]{1,180}$.
canvas.connections[].handlestringYesPattern ^connection:.
canvas.connections[].fromNodeIdstringYesPattern ^[A-Za-z0-9_-]{1,180}$.
canvas.connections[].toNodeIdstringYesPattern ^[A-Za-z0-9_-]{1,180}$.
canvas.connections[].fromstringYesPattern ^node:.
canvas.connections[].tostringYesPattern ^node:.
activityarray of objectYes—

Example

curl "https://app.gavana.ai/api/canvas-agent/v1/canvases/canvas:8f2c1d40-9a77-4c2e-9c11-2b0a5f6d7e31" \ -H "Authorization: Bearer $GAVANA_AGENT_TOKEN"

GET /canvases/{canvasId}/nodes/{nodeId}

Get one node with incoming and outgoing connections

  • Operation id: getCanvasNode
  • Scopes: Requires canvas:read.
  • CLI equivalent: gavana node get

Parameters

ParameterInTypeRequiredNotes
canvasIdpathstringYesPattern ^[A-Za-z0-9_-]{1,180}$.
nodeIdpathstringYesPattern ^(?:node:)?[A-Za-z0-9_-]{1,180}$.
ownerUidquerystringNoIdentifies the owner of a shared canvas or asset. Owner-qualified handles let the CLI supply it automatically. Pattern ^[A-Za-z0-9_-]{1,180}$.

Responses

StatusPayloadMeaning
200objectA successful JSON response.
defaultErrorResponseA stable machine-readable error. The response always includes X-Request-ID.

Example

curl "https://app.gavana.ai/api/canvas-agent/v1/canvases/canvas:8f2c1d40-9a77-4c2e-9c11-2b0a5f6d7e31/nodes/node:1f4b8c9a" \ -H "Authorization: Bearer $GAVANA_AGENT_TOKEN"

POST /canvases/{canvasId}/operations

Validate or apply one revision-safe operation batch

Set validateOnly to true to run the canonical operation engine and graph validator without writing, consuming an idempotency key, or requiring canvas:write. Validation includes completionReview for overlap, full-frame Section containment, lineage, and output delivery; do not claim Done while completionReview.doneClaimAllowed is false. For mutation, read the canvas first, pass its revision as baseRevision, and provide an idempotencyKey. A 409 response includes the current revision when another actor changed the canvas.

  • Operation id: applyCanvasOperations
  • Scopes: Requires canvas:read. When validateOnly is not true, also requires canvas:write.
  • CLI equivalent: gavana canvas apply

Parameters

ParameterInTypeRequiredNotes
canvasIdpathstringYesPattern ^[A-Za-z0-9_-]{1,180}$.
ownerUidquerystringNoIdentifies the owner of a shared canvas or asset. Owner-qualified handles let the CLI supply it automatically. Pattern ^[A-Za-z0-9_-]{1,180}$.

Request body (application/json, required)

FieldTypeRequiredNotes
baseRevisionstringNomin length 1, max length 200.
idempotencyKeystringNoRequired for mutation. Ignored and not consumed when validateOnly is true. min length 8, max length 200.
validateOnlybooleanNoRun the canonical operation engine and graph validator without persisting any change. Default false.
forcebooleanNoApply even when the proposed agent write has blocking error-severity validation findings. New agent-owned overlap and full-frame Section overflow are blocked; historical user-canvas findings remain advisory. Without force, a blocking write is rejected with 422 and nothing is written. Default false.
operationsarray of CanvasOperationYesmin items 1, max items 200.

Validation rules the service enforces across these fields:

  • Non-empty content is writable only on text and sticky nodes.

Responses

StatusPayloadMeaning
200CanvasValidationResponse | MutationResponseA canonical read-only validation result when validateOnly is true, otherwise a revision-safe mutation result.
409ErrorResponseA stable machine-readable error. The response always includes X-Request-ID.
defaultErrorResponseA stable machine-readable error. The response always includes X-Request-ID.

200 response body

FieldTypeRequiredNotes
(CanvasValidationResponse).canvasCanvasSummaryYes—
(CanvasValidationResponse).canvas.idstringYesPattern ^[A-Za-z0-9_-]{1,180}$.
(CanvasValidationResponse).canvas.canvasTypestringNoOne of agent.
(CanvasValidationResponse).canvas.handlestringYesPattern ^canvas:.
(CanvasValidationResponse).canvas.ownerUidstringYesPattern ^[A-Za-z0-9_-]{1,180}$.
(CanvasValidationResponse).canvas.titlestringYes—
(CanvasValidationResponse).canvas.createdAtstring (date-time)Yes—
(CanvasValidationResponse).canvas.updatedAtstring (date-time)Yes—
(CanvasValidationResponse).canvas.revisionstringYes—
(CanvasValidationResponse).canvas.accessRolestringNoOne of owner, editor, viewer.
(CanvasValidationResponse).canvas.nodeCountintegerYesmin 0.
(CanvasValidationResponse).canvas.connectionCountintegerYesmin 0.
(CanvasValidationResponse).proposalobjectYes—
(CanvasValidationResponse).destructiveImpactobjectYes—
(CanvasValidationResponse).validationobjectYes—
(CanvasValidationResponse).validation.completionReviewCanvasCompletionReviewNo—
(CanvasValidationResponse).validation.completionReview.statusstringYesOne of ready, needs-review, blocked.
(CanvasValidationResponse).validation.completionReview.doneClaimAllowedbooleanYesFalse while agent-owned spatial or lineage findings remain, or a generated output is pending, failed, or non-durable.
(CanvasValidationResponse).validation.completionReview.instructionstringYes—
(CanvasValidationResponse).validation.completionReview.outputsCanvasCompletionOutputsYesGenerated-output count and durable, pending, and failed breakdown.
(CanvasValidationResponse).validation.completionReview.outputs.countintegerYesmin 0.
(CanvasValidationResponse).validation.completionReview.outputs.durableCountintegerYesmin 0.
(CanvasValidationResponse).validation.completionReview.outputs.pendingCountintegerYesmin 0.
(CanvasValidationResponse).validation.completionReview.outputs.failedCountintegerYesmin 0.
(CanvasValidationResponse).validation.completionReview.outputs.handlesarray of stringYes—
(CanvasValidationResponse).validation.completionReview.overlapCanvasCompletionFindingAreaYes—
(CanvasValidationResponse).validation.completionReview.overlap.statusstringYesOne of clear, needs-review, blocked.
(CanvasValidationResponse).validation.completionReview.overlap.findingCodesarray of stringYes—
(CanvasValidationResponse).validation.completionReview.overlap.nodeHandlesarray of stringYes—
(CanvasValidationResponse).validation.completionReview.overlap.connectionHandlesarray of stringYes—
(CanvasValidationResponse).validation.completionReview.containmentCanvasCompletionFindingAreaYes—
(CanvasValidationResponse).validation.completionReview.containment.statusstringYesOne of clear, needs-review, blocked.
(CanvasValidationResponse).validation.completionReview.containment.findingCodesarray of stringYes—
(CanvasValidationResponse).validation.completionReview.containment.nodeHandlesarray of stringYes—
(CanvasValidationResponse).validation.completionReview.containment.connectionHandlesarray of stringYes—
(CanvasValidationResponse).validation.completionReview.referenceLineageCanvasCompletionFindingAreaYes—
(CanvasValidationResponse).validation.completionReview.referenceLineage.statusstringYesOne of clear, needs-review, blocked.
(CanvasValidationResponse).validation.completionReview.referenceLineage.findingCodesarray of stringYes—
(CanvasValidationResponse).validation.completionReview.referenceLineage.nodeHandlesarray of stringYes—
(CanvasValidationResponse).validation.completionReview.referenceLineage.connectionHandlesarray of stringYes—
(CanvasValidationResponse).validation.completionReview.productFidelityCanvasProductFidelityReviewYesA conservative review signal, not an authoritative visual inspection.
(CanvasValidationResponse).validation.completionReview.productFidelity.statusstringYesOne of not-applicable, needs-review, passed.
(CanvasValidationResponse).validation.completionReview.productFidelity.reviewedOutputCountintegerYesmin 0.
(CanvasValidationResponse).validation.completionReview.productFidelity.needsReviewOutputHandlesarray of stringYes—
(CanvasValidationResponse).validation.completionReview.productFidelity.evidenceMissingOutputHandlesarray of stringYes—
(CanvasValidationResponse).validation.completionReview.productFidelity.reasonsarray of objectNo—
(CanvasValidationResponse).validation.completionReview.deliveryCanvasCompletionDeliveryYesGenerated-output delivery evidence. A blocked state prevents a Done claim.
(CanvasValidationResponse).validation.completionReview.delivery.statusstringYesOne of clear, blocked.
(CanvasValidationResponse).validation.completionReview.delivery.reasonsarray of stringNo—
(CanvasValidationResponse).validation.completionReview.delivery.pendingOutputHandlesarray of stringYes—
(CanvasValidationResponse).validation.completionReview.delivery.failedOutputHandlesarray of stringYes—
(CanvasValidationResponse).validation.completionReview.delivery.nonDurableOutputHandlesarray of stringYes—
(CanvasValidationResponse).validation.completionReview.blockingFindingCodesarray of stringYes—
(CanvasValidationResponse).validation.completionReview.advisoryFindingCodesarray of stringYes—
(MutationResponse).canvasCanvasYes—
(MutationResponse).canvas.idstringYesPattern ^[A-Za-z0-9_-]{1,180}$.
(MutationResponse).canvas.canvasTypestringNoOne of agent.
(MutationResponse).canvas.handlestringYesPattern ^canvas:[A-Za-z0-9_-]+:[A-Za-z0-9_-]+$.
(MutationResponse).canvas.ownerUidstringYesPattern ^[A-Za-z0-9_-]{1,180}$.
(MutationResponse).canvas.titlestringYesmax length 160.
(MutationResponse).canvas.createdAtstring (date-time)Yes—
(MutationResponse).canvas.updatedAtstring (date-time)Yes—
(MutationResponse).canvas.revisionstringYesmin length 1.
(MutationResponse).canvas.nodesarray of CanvasNodeYes—
(MutationResponse).canvas.nodes[].idstringYesPattern ^[A-Za-z0-9_-]{1,180}$.
(MutationResponse).canvas.nodes[].handlestringYesPattern ^node:.
(MutationResponse).canvas.nodes[].typestringYesOne of image, video, text, sticky.
(MutationResponse).canvas.nodes[].titlestringYes—
(MutationResponse).canvas.nodes[].positionPositionYes—
(MutationResponse).canvas.nodes[].position.xnumberYesmin -10000000, max 10000000.
(MutationResponse).canvas.nodes[].position.ynumberYesmin -10000000, max 10000000.
(MutationResponse).canvas.nodes[].widthnumberYes—
(MutationResponse).canvas.nodes[].heightnumberYes—
(MutationResponse).canvas.nodes[].metadataobjectNo—
(MutationResponse).canvas.nodes[].assetstringNoPattern ^asset:.
(MutationResponse).canvas.connectionsarray of CanvasConnectionYes—
(MutationResponse).canvas.connections[].idstringYesPattern ^[A-Za-z0-9_-]{1,180}$.
(MutationResponse).canvas.connections[].handlestringYesPattern ^connection:.
(MutationResponse).canvas.connections[].fromNodeIdstringYesPattern ^[A-Za-z0-9_-]{1,180}$.
(MutationResponse).canvas.connections[].toNodeIdstringYesPattern ^[A-Za-z0-9_-]{1,180}$.
(MutationResponse).canvas.connections[].fromstringYesPattern ^node:.
(MutationResponse).canvas.connections[].tostringYesPattern ^node:.
(MutationResponse).replayedbooleanNo—
(MutationResponse).resolvedIdsobjectNo—
(MutationResponse).changedNodeIdsarray of stringNo—
(MutationResponse).deletedNodeIdsarray of stringNo—
(MutationResponse).changedConnectionIdsarray of stringNo—
(MutationResponse).deletedConnectionIdsarray of stringNo—

Example

curl -X POST "https://app.gavana.ai/api/canvas-agent/v1/canvases/canvas:8f2c1d40-9a77-4c2e-9c11-2b0a5f6d7e31/operations" \ -H "Authorization: Bearer $GAVANA_AGENT_TOKEN" \ -H "Content-Type: application/json" \ -d '{}'

GET /canvases/{canvasId}/render

Render a canvas as SVG

  • Operation id: renderCanvasSvg
  • Scopes: Requires canvas:read.
  • CLI equivalent: gavana canvas render

Parameters

ParameterInTypeRequiredNotes
canvasIdpathstringYesPattern ^[A-Za-z0-9_-]{1,180}$.
ownerUidquerystringNoIdentifies the owner of a shared canvas or asset. Owner-qualified handles let the CLI supply it automatically. Pattern ^[A-Za-z0-9_-]{1,180}$.

Responses

StatusPayloadMeaning
200image/svg+xmlAn SVG rendering of the canvas.
defaultErrorResponseA stable machine-readable error. The response always includes X-Request-ID.

Example

curl "https://app.gavana.ai/api/canvas-agent/v1/canvases/canvas:8f2c1d40-9a77-4c2e-9c11-2b0a5f6d7e31/render" \ -H "Authorization: Bearer $GAVANA_AGENT_TOKEN"

Errors

Every failure uses the shared error envelope described in Errors and X-Request-ID. The response always carries X-Request-ID; share that value with support instead of the request payload.

Last updated on