Actions
Discover and run deterministic, credit-free image transformations.
Base URL: https://app.gavana.ai/api/canvas-agent/v1 · Authentication: HTTP bearer, token format cba_<token-id>.<secret>
Operations
| Operation | Purpose | Scopes |
|---|---|---|
GET /actions | List deterministic Image Actions | canvas:read |
GET /actions/{actionKey} | Read one Image Action schema | canvas:read |
POST /actions/{actionKey}/runs | Run a deterministic Image Action | canvas:read, canvas:write, asset:read |
GET /actions
List deterministic Image Actions
Returns typed schemas for the eight deterministic, credit-free raster transformations available in the browser, CLI, API, and MCP adapter.
- Operation id:
listImageActions - Scopes: Requires
canvas:read. - CLI equivalent:
gavana action list
Parameters
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
q | query | string | No | Free-text Action slug, title, or summary search. max length 240. |
limit | query | integer | No | Maximum number of items in this page. min 1, max 100. |
cursor | query | string | No | Opaque continuation cursor from page.nextCursor. Reuse it with the same list filters. max length 8192. |
Responses
| Status | Payload | Meaning |
|---|---|---|
200 | object | Deterministic Image Actions with typed schemas and pagination. |
default | ErrorResponse | A stable machine-readable error. The response always includes X-Request-ID. |
200 response body
| Field | Type | Required | Notes |
|---|---|---|---|
actions | array of ImageAction | Yes | — |
actions[].id | string | Yes | Pattern ^action:. |
actions[].slug | string | Yes | One of resize, crop, change-aspect-ratio, side-by-side-composite, add-text-to-image, overlay-image, color-grade, rotate. |
actions[].version | “1.0.0” | Yes | — |
actions[].title | string | Yes | min length 1. |
actions[].summary | string | Yes | min length 1. |
actions[].estimatedSeconds | integer | Yes | min 1. |
actions[].inputs | array of ImageActionInput | Yes | min items 1, max items 2. |
actions[].inputs[].id | string | Yes | Pattern ^[A-Za-z][A-Za-z0-9_-]{0,79}$. |
actions[].inputs[].title | string | Yes | — |
actions[].inputs[].description | string | Yes | — |
actions[].output | ImageActionOutput | Yes | — |
actions[].output.title | string | Yes | — |
actions[].output.description | string | Yes | — |
actions[].parameters | array of ImageActionParameter | Yes | — |
actions[].parameters[].id | string | Yes | Pattern ^[A-Za-z][A-Za-z0-9_-]{0,79}$. |
actions[].parameters[].title | string | Yes | — |
actions[].parameters[].description | string | No | — |
actions[].parameters[].type | string | Yes | One of number, select, text, color. |
actions[].parameters[].required | boolean | Yes | — |
actions[].parameters[].integer | boolean | No | — |
actions[].parameters[].min | number | No | — |
actions[].parameters[].max | number | No | — |
actions[].parameters[].step | number | No | — |
actions[].parameters[].maxLength | integer | No | min 1. |
actions[].parameters[].options | array of ImageActionParameterOption | No | — |
actions[].parameters[].options[].value | string | number | Yes | — |
actions[].parameters[].options[].label | string | Yes | — |
page | CursorPage | Yes | — |
page.limit | integer | Yes | min 1, max 200. |
page.hasMore | boolean | Yes | — |
page.nextCursor | string | null | Yes | max length 8192. |
Example
curl "https://app.gavana.ai/api/canvas-agent/v1/actions" \
-H "Authorization: Bearer $GAVANA_AGENT_TOKEN"GET /actions/{actionKey}
Read one Image Action schema
Returns the exact ordered image inputs, typed parameters, defaults, limits, output contract, and cost behavior for one Action.
- Operation id:
getImageAction - Scopes: Requires
canvas:read. - CLI equivalent:
gavana action get
Parameters
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
actionKey | path | string | Yes | An Action slug or action:<slug> handle returned by GET /actions. Pattern ^(?:action:)?(?:resize|crop|change-aspect-ratio|side-by-side-composite|add-text-to-image|overlay-image|color-grade|rotate)$. |
Responses
| Status | Payload | Meaning |
|---|---|---|
200 | object | One deterministic Image Action with its typed input and parameter schema. |
default | ErrorResponse | A stable machine-readable error. The response always includes X-Request-ID. |
200 response body
| Field | Type | Required | Notes |
|---|---|---|---|
action | ImageAction | Yes | — |
action.id | string | Yes | Pattern ^action:. |
action.slug | string | Yes | One of resize, crop, change-aspect-ratio, side-by-side-composite, add-text-to-image, overlay-image, color-grade, rotate. |
action.version | “1.0.0” | Yes | — |
action.title | string | Yes | min length 1. |
action.summary | string | Yes | min length 1. |
action.estimatedSeconds | integer | Yes | min 1. |
action.inputs | array of ImageActionInput | Yes | min items 1, max items 2. |
action.inputs[].id | string | Yes | Pattern ^[A-Za-z][A-Za-z0-9_-]{0,79}$. |
action.inputs[].title | string | Yes | — |
action.inputs[].description | string | Yes | — |
action.output | ImageActionOutput | Yes | — |
action.output.title | string | Yes | — |
action.output.description | string | Yes | — |
action.parameters | array of ImageActionParameter | Yes | — |
action.parameters[].id | string | Yes | Pattern ^[A-Za-z][A-Za-z0-9_-]{0,79}$. |
action.parameters[].title | string | Yes | — |
action.parameters[].description | string | No | — |
action.parameters[].type | string | Yes | One of number, select, text, color. |
action.parameters[].required | boolean | Yes | — |
action.parameters[].integer | boolean | No | — |
action.parameters[].min | number | No | — |
action.parameters[].max | number | No | — |
action.parameters[].step | number | No | — |
action.parameters[].maxLength | integer | No | min 1. |
action.parameters[].options | array of ImageActionParameterOption | No | — |
action.parameters[].options[].value | string | number | Yes | — |
action.parameters[].options[].label | string | Yes | — |
Example
curl "https://app.gavana.ai/api/canvas-agent/v1/actions/action:resize" \
-H "Authorization: Bearer $GAVANA_AGENT_TOKEN"POST /actions/{actionKey}/runs
Run a deterministic Image Action
Queues a credit-free raster transform against one or two durable node or asset handles. The result is stored as a durable asset and materialized in the selected target image node.
- Operation id:
startImageAction - Scopes: Requires
canvas:read+canvas:write+asset:read. - CLI equivalent:
gavana action run
Parameters
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
actionKey | path | string | Yes | An Action slug or action:<slug> handle returned by GET /actions. Pattern ^(?:action:)?(?:resize|crop|change-aspect-ratio|side-by-side-composite|add-text-to-image|overlay-image|color-grade|rotate)$. |
Request body (application/json, required)
| Field | Type | Required | Notes |
|---|---|---|---|
canvasId | string | Yes | A plain id, canvas:<id>, or canvas:<ownerUid>:<id> handle. |
baseRevision | string | Yes | min length 1, max length 200. |
idempotencyKey | string | Yes | min length 8, max length 200. |
targetNodeId | string | Yes | A new, empty image node reserved for this Action result. It must not also appear in inputs, and it must have no content, asset binding, or active Run. Pattern ^(?:node:)?[A-Za-z0-9_-]{1,180}$. |
inputs | array of string | Yes | One or two durable images in the exact order declared by the selected Action. min items 1, max items 2. |
params | ResizeActionParameters | CropActionParameters | ChangeAspectRatioActionParameters | SideBySideActionParameters | AddTextActionParameters | OverlayImageActionParameters | ColorGradeActionParameters | RotateActionParameters | Yes | Use the parameter object declared by GET /actions/{actionKey}. Unknown fields are rejected. |
webhook | ImageJobWebhookInput | No | — |
webhook.url | string (uri) | Yes | A public HTTPS callback endpoint. Private, loopback, local-network, credential-bearing, and fragment-bearing URLs are rejected. max length 2048. Pattern ^https://. |
webhook.secret | string | Yes | A caller-owned HMAC secret encrypted at rest and never returned by the API. min length 32, max length 512. |
Validation rules the service enforces across these fields:
- targetNodeId must not identify any node supplied in inputs
- targetNodeId must identify an empty, unbound image node
Responses
| Status | Payload | Meaning |
|---|---|---|
202 | ImageJob | VideoJob | An image, Action, or video job state or finalized result. Image and Action results follow the documented Run retention policy. Video records are retained for 30 days and expose a protected download URL after completion. |
default | ErrorResponse | A stable machine-readable error. The response always includes X-Request-ID. |
202 response body
| Field | Type | Required | Notes |
|---|---|---|---|
(ImageJob).id | string | Yes | Pattern ^job:. |
(ImageJob).run | string | Yes | Pattern ^run:. |
(ImageJob).kind | string | Yes | One of image, action. |
(ImageJob).pollUrl | string | Yes | Pattern ^/api/canvas-agent/v1/runs/. |
(ImageJob).rawId | string (uuid) | No | — |
(ImageJob).status | string | Yes | Current temporary job state. Successful results retain the observation record for 24 hours before the first successful server finalization and 15 minutes after it; an authenticated Run GET or pre-callback worker finalization both count. Failed and canceled records keep the normal 24-hour window. Expired tombstones remain seven days. One of preparing, queued, running, finalizing, canceling, succeeded, failed, canceled, expired. |
(ImageJob).estimatedSeconds | integer | No | Typical provider runtime for the selected model. This is guidance, not a deadline. min 1. |
(ImageJob).durationMs | integer | No | Total observed duration once the job is terminal. min 0. |
(ImageJob).timing | ImageJobTiming | No | — |
(ImageJob).timing.createdAt | string (date-time) | No | — |
(ImageJob).timing.queuedAt | string (date-time) | No | — |
(ImageJob).timing.startedAt | string (date-time) | No | — |
(ImageJob).timing.completedAt | string (date-time) | No | — |
(ImageJob).timing.queueDurationMs | integer | No | min 0. |
(ImageJob).timing.executionDurationMs | integer | No | min 0. |
(ImageJob).timing.totalDurationMs | integer | No | min 0. |
(ImageJob).failure | ImageJobFailure | No | — |
(ImageJob).failure.code | string | Yes | One of provider_authentication_failed, provider_timeout, provider_rate_limited, provider_rejected, provider_unavailable, runtime_failed, action_input_invalid, result_expired. |
(ImageJob).failure.message | string | Yes | — |
(ImageJob).failure.retryable | boolean | Yes | — |
(ImageJob).failure.providerStatus | integer | No | min 400, max 599. |
(ImageJob).webhook | ImageJobWebhookDelivery | No | Durable delivery state. Gavana makes four total attempts. Retryable network failures and 408, 425, 429, or 5xx responses back off for 10 seconds, 60 seconds, then 5 minutes; redirects and other 4xx responses stop delivery. |
(ImageJob).webhook.id | string | Yes | Pattern ^webhook:. |
(ImageJob).webhook.status | string | Yes | One of pending, delivering, delivered, failed. |
(ImageJob).webhook.attempts | integer | Yes | min 0. |
(ImageJob).webhook.nextAttemptAt | string (date-time) | No | — |
(ImageJob).webhook.lastAttemptAt | string (date-time) | No | — |
(ImageJob).webhook.deliveredAt | string (date-time) | No | — |
(ImageJob).webhook.lastStatus | integer | No | min 100, max 599. |
(ImageJob).webhook.errorCode | string | No | One of invalid_destination, delivery_failed, redirect_not_allowed, endpoint_rejected, secret_unavailable, finalization_unavailable, finalization_auth_unavailable, finalization_auth_expired, finalization_failed. |
(ImageJob).replayed | boolean | No | — |
(ImageJob).operation | string | No | One of generate, edit, variations, action. |
(ImageJob).actionId | string | No | Pattern ^action:. |
(ImageJob).actionVersion | string | No | — |
(ImageJob).canvasId | string | No | Pattern ^canvas:. |
(ImageJob).canvasRevision | string | No | — |
(ImageJob).canvasUrl | string (uri) | No | — |
(ImageJob).canceledAt | string (date-time) | No | — |
(ImageJob).cancelReason | string | No | One of stale_preparing, user_requested, setup_failed. |
(ImageJob).targets | array of string | No | — |
(ImageJob).references | array of string | No | — |
(ImageJob).referenceInputs | array of ImageReferenceInput | No | Exact reference handles and optional semantic roles used by the provider request. |
(ImageJob).referenceInputs[].handle | string | Yes | Pattern ^(?:node:[A-Za-z0-9_-]{1,180}|asset:(?:[A-Za-z0-9_-]{1,180}:)?[A-Za-z0-9_-]{1,180})$. |
(ImageJob).referenceInputs[].role | string | No | One of identity, construction, texture, fit, style. |
(ImageJob).images | array of ImageJobResultImage | No | — |
(ImageJob).images[].assetId | string | Yes | Pattern ^asset:. |
(ImageJob).images[].nodeId | string | Yes | Pattern ^node:. |
(ImageJob).images[].mediaType | string | No | Pattern ^image/. |
(ImageJob).images[].width | integer | No | min 1. |
(ImageJob).images[].height | integer | No | min 1. |
(ImageJob).images[].bytes | integer | No | min 1. |
(ImageJob).images[].previewUrl | string (uri) | Yes | — |
(ImageJob).images[].markdown | string | No | — |
(ImageJob).completionReview | CanvasCompletionReview | No | — |
(ImageJob).completionReview.status | string | Yes | One of ready, needs-review, blocked. |
(ImageJob).completionReview.doneClaimAllowed | boolean | Yes | False while agent-owned spatial or lineage findings remain, or a generated output is pending, failed, or non-durable. |
(ImageJob).completionReview.instruction | string | Yes | — |
(ImageJob).completionReview.outputs | CanvasCompletionOutputs | Yes | Generated-output count and durable, pending, and failed breakdown. |
(ImageJob).completionReview.outputs.count | integer | Yes | min 0. |
(ImageJob).completionReview.outputs.durableCount | integer | Yes | min 0. |
(ImageJob).completionReview.outputs.pendingCount | integer | Yes | min 0. |
(ImageJob).completionReview.outputs.failedCount | integer | Yes | min 0. |
(ImageJob).completionReview.outputs.handles | array of string | Yes | — |
(ImageJob).completionReview.overlap | CanvasCompletionFindingArea | Yes | — |
(ImageJob).completionReview.overlap.status | string | Yes | One of clear, needs-review, blocked. |
(ImageJob).completionReview.overlap.findingCodes | array of string | Yes | — |
(ImageJob).completionReview.overlap.nodeHandles | array of string | Yes | — |
(ImageJob).completionReview.overlap.connectionHandles | array of string | Yes | — |
(ImageJob).completionReview.containment | CanvasCompletionFindingArea | Yes | — |
(ImageJob).completionReview.containment.status | string | Yes | One of clear, needs-review, blocked. |
(ImageJob).completionReview.containment.findingCodes | array of string | Yes | — |
(ImageJob).completionReview.containment.nodeHandles | array of string | Yes | — |
(ImageJob).completionReview.containment.connectionHandles | array of string | Yes | — |
(ImageJob).completionReview.referenceLineage | CanvasCompletionFindingArea | Yes | — |
(ImageJob).completionReview.referenceLineage.status | string | Yes | One of clear, needs-review, blocked. |
(ImageJob).completionReview.referenceLineage.findingCodes | array of string | Yes | — |
(ImageJob).completionReview.referenceLineage.nodeHandles | array of string | Yes | — |
(ImageJob).completionReview.referenceLineage.connectionHandles | array of string | Yes | — |
(ImageJob).completionReview.productFidelity | CanvasProductFidelityReview | Yes | A conservative review signal, not an authoritative visual inspection. |
(ImageJob).completionReview.productFidelity.status | string | Yes | One of not-applicable, needs-review, passed. |
(ImageJob).completionReview.productFidelity.reviewedOutputCount | integer | Yes | min 0. |
(ImageJob).completionReview.productFidelity.needsReviewOutputHandles | array of string | Yes | — |
(ImageJob).completionReview.productFidelity.evidenceMissingOutputHandles | array of string | Yes | — |
(ImageJob).completionReview.productFidelity.reasons | array of object | No | — |
(ImageJob).completionReview.productFidelity.reasons[].nodeHandle | string | Yes | Pattern ^node:. |
(ImageJob).completionReview.productFidelity.reasons[].reason | string | Yes | — |
(ImageJob).completionReview.delivery | CanvasCompletionDelivery | Yes | Generated-output delivery evidence. A blocked state prevents a Done claim. |
(ImageJob).completionReview.delivery.status | string | Yes | One of clear, blocked. |
(ImageJob).completionReview.delivery.reasons | array of string | No | — |
(ImageJob).completionReview.delivery.pendingOutputHandles | array of string | Yes | — |
(ImageJob).completionReview.delivery.failedOutputHandles | array of string | Yes | — |
(ImageJob).completionReview.delivery.nonDurableOutputHandles | array of string | Yes | — |
(ImageJob).completionReview.blockingFindingCodes | array of string | Yes | — |
(ImageJob).completionReview.advisoryFindingCodes | array of string | Yes | — |
(VideoJob).id | string | Yes | Pattern ^job:. |
(VideoJob).rawId | string (uuid) | Yes | — |
(VideoJob).kind | “video” | Yes | — |
(VideoJob).operation | “generate” | Yes | — |
(VideoJob).pollUrl | string | Yes | Pattern ^/api/canvas-agent/v1/jobs/. |
(VideoJob).status | string | Yes | One of queued, running, succeeded, failed, canceled. |
(VideoJob).model | object | Yes | — |
(VideoJob).model.id | string | Yes | — |
(VideoJob).model.name | string | Yes | — |
(VideoJob).progress | number | Yes | min 0, max 100. |
(VideoJob).estimatedSeconds | integer | Yes | min 1. |
(VideoJob).providerRunId | string | No | — |
(VideoJob).failure | VideoJobFailure | No | — |
(VideoJob).failure.code | string | Yes | One of video_generation_failed, canceled. |
(VideoJob).failure.message | string | Yes | — |
(VideoJob).failure.retryable | boolean | Yes | — |
(VideoJob).video | object | No | — |
(VideoJob).video.downloadUrl | string | Yes | Pattern ^/api/canvas-agent/v1/jobs/.+/output$. |
(VideoJob).replayed | boolean | No | — |
(VideoJob).createdAt | string (date-time) | Yes | — |
(VideoJob).updatedAt | string (date-time) | Yes | — |
Callbacks
imageJobTerminal→{$request.body#/webhook/url}: Receive a signed terminal image-job event. Gavana signs${timestamp}.${rawBody}with HMAC-SHA256 and the caller-owned secret. Return any 2xx response to acknowledge delivery. Delivery uses four total attempts. Retryable network failures and 408, 425, 429, or 5xx responses back off for 10 seconds, 60 seconds, then 5 minutes; redirects and other 4xx responses stop delivery. Successful Image and Action callbacks already contain durable asset and node handles indata.run.images, so callback-only clients do not need a follow-up GET. A caller withjob:managemay read the shared Run later for inspection. Successful image and Action results retain their temporary observation record for 24 hours before the first successful server finalization and 15 minutes after it; an authenticated Run GET or pre-callback worker finalization both count. Failed and canceled records keep the normal 24-hour window.
Example
curl -X POST "https://app.gavana.ai/api/canvas-agent/v1/actions/action:resize/runs" \
-H "Authorization: Bearer $GAVANA_AGENT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"canvasId": "canvas:8f2c1d40-9a77-4c2e-9c11-2b0a5f6d7e31",
"baseRevision": "12",
"idempotencyKey": "2026-08-04-first-attempt",
"targetNodeId": "<targetNodeId>",
"inputs": [
"<inputs>"
],
"params": {}
}'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.