Skip to Content

Assets

Read durable assets and upload raster references.

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

Operations

OperationPurposeScopes
GET /assetsList accessible assetsasset:read
POST /assetsUpload a durable raster referenceasset:read, image:generate?, video:generate?
GET /assets/{assetId}Get an accessible assetasset:read
GET /assets/previewRead a short-lived scoped image previewnone
POST /product-references/importImport a product-page gallery as a Product References packcanvas:read, canvas:write, asset:read

GET /assets

List accessible assets

Assets are ordered by updatedAt descending, then handle descending.

  • Operation id: listAssets
  • Scopes: Requires asset:read.
  • CLI equivalent: gavana asset list

Parameters

ParameterInTypeRequiredNotes
canvasIdquerystringNoOptional plain canvas id used to filter or scope the request. Pattern ^[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}$.
limitqueryintegerNoMaximum number of items in this page. min 1, max 200.
cursorquerystringNoOpaque continuation cursor from page.nextCursor. Reuse it with the same list filters. max length 8192.

Responses

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

200 response body

FieldTypeRequiredNotes
assetsarray of AssetYes—
assets[].idstringYesPattern ^[A-Za-z0-9_-]{1,180}$.
assets[].handlestringYesShared assets include their owner: asset:<ownerUid>:<id>. Pattern ^asset:(?:[A-Za-z0-9_-]{1,180}:)?[A-Za-z0-9_-]{1,180}$.
assets[].ownerUidstringNoPattern ^[A-Za-z0-9_-]{1,180}$.
assets[].kindstringNoOne of image, prompt.
assets[].namestringYes—
assets[].mimeTypestringNo—
assets[].widthintegerNomin 0.
assets[].heightintegerNomin 0.
assets[].bytesintegerNomin 0.
assets[].previewUrlstring (uri)No—
assets[].previewExpiresInSecondsintegerNomin 1.
assets[].nodestringNoPattern ^node:.
pageCursorPageYes—
page.limitintegerYesmin 1, max 200.
page.hasMorebooleanYes—
page.nextCursorstring | nullYesmax length 8192.

Example

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

POST /assets

Upload a durable raster reference

Uploads a private raster reference for image or video generation. When canvasId is supplied, canvas read/write scopes are also required and the upload is stored inside that canvas.

  • Operation id: uploadAsset
  • Scopes: Requires asset:read. Requires at least one of image:generate or video:generate. When canvasId query parameter is present, also requires canvas:read + canvas:write.
  • CLI equivalent: gavana asset upload

Parameters

ParameterInTypeRequiredNotes
canvasIdquerystringNoOptional plain canvas id used to filter or scope the request. Pattern ^[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}$.
X-Gavana-File-NameheaderstringNomax length 255.
X-Craftboard-File-NameheaderstringNoDeprecated. Legacy alias for X-Gavana-File-Name. max length 255.

Request body (application/octet-stream, image/png, image/jpeg, image/webp, image/gif, required)

Responses

StatusPayloadMeaning
201objectA durable asset.
defaultErrorResponseA stable machine-readable error. The response always includes X-Request-ID.

201 response body

FieldTypeRequiredNotes
assetAssetYes—
asset.idstringYesPattern ^[A-Za-z0-9_-]{1,180}$.
asset.handlestringYesShared assets include their owner: asset:<ownerUid>:<id>. Pattern ^asset:(?:[A-Za-z0-9_-]{1,180}:)?[A-Za-z0-9_-]{1,180}$.
asset.ownerUidstringNoPattern ^[A-Za-z0-9_-]{1,180}$.
asset.kindstringNoOne of image, prompt.
asset.namestringYes—
asset.mimeTypestringNo—
asset.widthintegerNomin 0.
asset.heightintegerNomin 0.
asset.bytesintegerNomin 0.
asset.previewUrlstring (uri)No—
asset.previewExpiresInSecondsintegerNomin 1.
asset.nodestringNoPattern ^node:.

Example

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

GET /assets/{assetId}

Get an accessible asset

For a shared asset, pass the ownerUid encoded in its owner-qualified handle. The CLI does this automatically.

  • Operation id: getAsset
  • Scopes: Requires asset:read.
  • CLI equivalent: gavana asset get

Parameters

ParameterInTypeRequiredNotes
assetIdpathstringYesPattern ^(?:asset:)?[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 durable asset.
defaultErrorResponseA stable machine-readable error. The response always includes X-Request-ID.

200 response body

FieldTypeRequiredNotes
assetAssetYes—
asset.idstringYesPattern ^[A-Za-z0-9_-]{1,180}$.
asset.handlestringYesShared assets include their owner: asset:<ownerUid>:<id>. Pattern ^asset:(?:[A-Za-z0-9_-]{1,180}:)?[A-Za-z0-9_-]{1,180}$.
asset.ownerUidstringNoPattern ^[A-Za-z0-9_-]{1,180}$.
asset.kindstringNoOne of image, prompt.
asset.namestringYes—
asset.mimeTypestringNo—
asset.widthintegerNomin 0.
asset.heightintegerNomin 0.
asset.bytesintegerNomin 0.
asset.previewUrlstring (uri)No—
asset.previewExpiresInSecondsintegerNomin 1.
asset.nodestringNoPattern ^node:.

Example

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

GET /assets/preview

Read a short-lived scoped image preview

The encrypted preview token is the authorization grant for this endpoint. Agent bearer tokens are not accepted or required.

  • Operation id: previewAsset
  • Scopes: Requires a valid Agent Access token; no additional product scope.

Parameters

ParameterInTypeRequiredNotes
tokenquerystringYesmin length 1.

Responses

StatusPayloadMeaning
200image/pngA proxied PNG, JPEG, WebP, or GIF image.
defaultErrorResponseA stable machine-readable error. The response always includes X-Request-ID.

Example

curl "https://app.gavana.ai/api/canvas-agent/v1/assets/preview?token=<token>" \ -H "Authorization: Bearer $GAVANA_AGENT_TOKEN"

POST /product-references/import

Import a product-page gallery as a Product References pack

Safely fetches one public HTTPS product page, discovers up to 12 distinct raster gallery images, stores them as private canvas assets and nodes, and creates one semantic Product References Section. An exact variant selector such as colorDisplayCode=08 is never inferred: if page evidence cannot tie the requested selector to gallery images, the response is review_required and creates no pack. Without a selector, pages that expose multiple variant values also return review_required rather than mix them. This operation never invokes an image or video provider.

  • Operation id: importProductReferencePack
  • Scopes: Requires canvas:read + canvas:write + asset:read.

Request body (application/json, required)

FieldTypeRequiredNotes
canvasIdstringYesA plain id, canvas:<id>, or canvas:<ownerUid>:<id> handle. min length 1, max length 600.
productPageUrlstring (uri)Yesmax length 4096. Pattern ^https://.
variantSelectorstringNoOptional exact key=value selector, for example colorDisplayCode=08. Gavana returns review_required instead of inferring a variant. min length 3, max length 300.
titlestringNoDefault "Product References". min length 1, max length 160.
idempotencyKeystringYesmin length 8, max length 200.

Responses

StatusPayloadMeaning
200ProductReferencePackImportResponseA durable product-reference pack or an explicit review-required result when an exact requested variant cannot be evidenced.
defaultErrorResponseA stable machine-readable error. The response always includes X-Request-ID.

200 response body

FieldTypeRequiredNotes
(variant 1).status“succeeded”Yes—
(variant 1).replayedbooleanYes—
(variant 1).canvasIdstringYesPattern ^canvas:.
(variant 1).canvasRevisionstringYes—
(variant 1).canvasUrlstring (uri)Yes—
(variant 1).pageProductReferencePageYes—
(variant 1).page.urlstring (uri)Yes—
(variant 1).page.resolvedUrlstring (uri)Yes—
(variant 1).variantProductReferenceVariantYes—
(variant 1).variant.selectorstringNo—
(variant 1).variant.evidencestringYesOne of exact, not_requested, selection_required, unavailable.
(variant 1).packProductReferencePackYes—
(variant 1).pack.sectionIdstringYesPattern ^node:.
(variant 1).pack.titlestringYes—
(variant 1).pack.imageCountintegerYesmin 1, max 12.
(variant 1).imagesarray of ProductReferencePackImageYesmin items 1, max items 12.
(variant 1).images[].assetIdstringYesPattern ^asset:.
(variant 1).images[].nodeIdstringYesPattern ^node:.
(variant 1).images[].mediaTypestringYesOne of image/png, image/jpeg, image/webp, image/gif.
(variant 1).images[].widthintegerYesmin 1.
(variant 1).images[].heightintegerYesmin 1.
(variant 1).images[].bytesintegerYesmin 1, max 52428800.
(variant 1).images[].sourceImageUrlstring (uri)Yes—
(variant 1).images[].previewUrlstring (uri)Yes—
(variant 1).images[].markdownstringYes—
(variant 1).discoveryProductReferenceDiscoveryNo—
(variant 1).discovery.discoveredCandidateCountintegerYesmin 0.
(variant 1).discovery.skippedImageCountintegerYesmin 0.
(variant 1).discovery.limitedbooleanNoPresent on an initial successful import when discovery found more than the 12-image pack limit.
(variant 2).status“review_required”Yes—
(variant 2).reviewRequiredtrueYes—
(variant 2).reasonstringYesOne of variant_evidence_unavailable, variant_selection_required, no_gallery_images_discovered, no_supported_raster_images.
(variant 2).canvasIdstringYesPattern ^canvas:.
(variant 2).pageProductReferencePageYes—
(variant 2).page.urlstring (uri)Yes—
(variant 2).page.resolvedUrlstring (uri)Yes—
(variant 2).variantProductReferenceVariantYes—
(variant 2).variant.selectorstringNo—
(variant 2).variant.evidencestringYesOne of exact, not_requested, selection_required, unavailable.
(variant 2).discoveryProductReferenceDiscoveryYes—
(variant 2).discovery.discoveredCandidateCountintegerYesmin 0.
(variant 2).discovery.skippedImageCountintegerYesmin 0.
(variant 2).discovery.limitedbooleanNoPresent on an initial successful import when discovery found more than the 12-image pack limit.

Example

curl -X POST "https://app.gavana.ai/api/canvas-agent/v1/product-references/import" \ -H "Authorization: Bearer $GAVANA_AGENT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "canvasId": "canvas:8f2c1d40-9a77-4c2e-9c11-2b0a5f6d7e31", "productPageUrl": "https://example.com/gavana-webhook", "idempotencyKey": "2026-08-04-first-attempt" }'

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