Images
Queue image generation, editing, and variation jobs.
Base URL: https://app.gavana.ai/api/canvas-agent/v1 · Authentication: HTTP bearer, token format cba_<token-id>.<secret>
Operations
| Operation | Purpose | Scopes |
|---|---|---|
POST /images/edit | Queue an image edit | canvas:read, canvas:write, asset:read, image:generate |
POST /images/generate | Queue image generation | canvas:read, canvas:write, asset:read, image:generate |
POST /images/import | Import a public HTTPS image as a durable canvas node | canvas:read, canvas:write, asset:read, image:generate |
POST /images/variations | Queue image variations | canvas:read, canvas:write, asset:read, image:generate |
POST /images/edit
Queue an image edit
- Operation id:
startImageEdit - Scopes: Requires
canvas:read+canvas:write+asset:read+image:generate. When elements contains at least one version-pinned Element, also requireselement:read. - CLI equivalent:
gavana image edit
Request body (application/json, required)
At least one of references or source is 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 | No | Pattern ^(?:node:)?[A-Za-z0-9_-]{1,180}$. |
targetNodeIds | array of string | No | min items 1, max items 4. |
prompt | string | No | min length 1, max length 8000. |
promptNodeId | string | No | Pattern ^(?:node:)?[A-Za-z0-9_-]{1,180}$. |
references | array of string | ImageReferenceInput | No | Stable image handles or role-bearing reference objects. Across references and source, at most 16 handles are allowed and every handle must be unique. When omitted for one named target, Gavana may derive visible incoming mode:reference image edges; hidden provider plumbing is never derived. min items 1, max items 16. |
elements | array of ElementGenerationReference | No | Up to eight reusable Elements pinned to exact immutable versions. Their source images share the 16-image limit with references and source. element:read is required when this array is non-empty. max items 8. |
source | string | No | A convenience reference appended to references. It must be unique across both fields, and the combined maximum is 16. Pattern ^(?:node:[A-Za-z0-9_-]{1,180}|asset:(?:[A-Za-z0-9_-]{1,180}:)?[A-Za-z0-9_-]{1,180})$. |
count | integer | No | Number of outputs. When supplied, it must equal the selected target count; when omitted, Gavana uses the selected target count. min 1, max 4. |
connectionId | string | No | Pattern ^[A-Za-z0-9_-]{1,180}$. |
model | string | No | A provider model id or opaque model:<key> handle from GET /models. max length 650. |
size | string | No | max length 80. |
quality | string | No | max length 80. |
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. |
(variant 2) (variant 1).count | 1 | No | — |
(variant 3) (variant 1).count | 2 | No | — |
(variant 4) (variant 1).count | 3 | No | — |
(variant 5) (variant 1).count | 4 | No | — |
Validation rules the service enforces across these fields:
- references and source contain at most 16 handles combined
- references and source are unique when combined
- role-bearing references retain their exact handle and role in job and canvas provenance
- count equals the selected target count
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/images/edit" \
-H "Authorization: Bearer $GAVANA_AGENT_TOKEN" \
-H "Content-Type: application/json" \
-d '{}'POST /images/generate
Queue image generation
- Operation id:
startImageGeneration - Scopes: Requires
canvas:read+canvas:write+asset:read+image:generate. When elements contains at least one version-pinned Element, also requireselement:read. - CLI equivalent:
gavana image generate
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 | No | Pattern ^(?:node:)?[A-Za-z0-9_-]{1,180}$. |
targetNodeIds | array of string | No | min items 1, max items 4. |
prompt | string | No | min length 1, max length 8000. |
promptNodeId | string | No | Pattern ^(?:node:)?[A-Za-z0-9_-]{1,180}$. |
references | array of string | ImageReferenceInput | No | Stable image handles or role-bearing reference objects. Across references and source, at most 16 handles are allowed and every handle must be unique. When omitted for one named target, Gavana may derive visible incoming mode:reference image edges; hidden provider plumbing is never derived. min items 1, max items 16. |
elements | array of ElementGenerationReference | No | Up to eight reusable Elements pinned to exact immutable versions. Their source images share the 16-image limit with references and source. element:read is required when this array is non-empty. max items 8. |
source | string | No | A convenience reference appended to references. It must be unique across both fields, and the combined maximum is 16. Pattern ^(?:node:[A-Za-z0-9_-]{1,180}|asset:(?:[A-Za-z0-9_-]{1,180}:)?[A-Za-z0-9_-]{1,180})$. |
count | integer | No | Number of outputs. When supplied, it must equal the selected target count; when omitted, Gavana uses the selected target count. min 1, max 4. |
connectionId | string | No | Pattern ^[A-Za-z0-9_-]{1,180}$. |
model | string | No | A provider model id or opaque model:<key> handle from GET /models. max length 650. |
size | string | No | max length 80. |
quality | string | No | max length 80. |
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. |
(variant 2) (variant 1).count | 1 | No | — |
(variant 3) (variant 1).count | 2 | No | — |
(variant 4) (variant 1).count | 3 | No | — |
(variant 5) (variant 1).count | 4 | No | — |
Validation rules the service enforces across these fields:
- references and source contain at most 16 handles combined
- references and source are unique when combined
- role-bearing references retain their exact handle and role in job and canvas provenance
- count equals the selected target count
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/images/generate" \
-H "Authorization: Bearer $GAVANA_AGENT_TOKEN" \
-H "Content-Type: application/json" \
-d '{}'POST /images/import
Import a public HTTPS image as a durable canvas node
Downloads a bounded raster image through Gavana’s SSRF-safe fetcher, stores it as a canvas-scoped asset, and adds one deterministic image node. Reuse the idempotency key only for the exact same import.
- Operation id:
importImageToCanvas - Scopes: Requires
canvas:read+canvas:write+asset:read+image:generate.
Request body (application/json, required)
| Field | Type | Required | Notes |
|---|---|---|---|
canvasId | string | Yes | A plain id, canvas:<id>, or canvas:<ownerUid>:<id> handle. min length 1, max length 600. |
imageUrl | string (uri) | Yes | max length 4096. Pattern ^https://. |
sourceId | string | No | Optional stable source identity, such as ChatGPT file_id. When present, Gavana uses it instead of the expiring download URL to match idempotent retries. min length 1, max length 1000. |
title | string | No | Default "Image from ChatGPT". min length 1, max length 160. |
idempotencyKey | string | Yes | min length 8, max length 200. |
x | number | No | min -100000, max 100000. |
y | number | No | min -100000, max 100000. |
Responses
| Status | Payload | Meaning |
|---|---|---|
200 | ImageImportResponse | A durable canvas image import result. |
default | ErrorResponse | A stable machine-readable error. The response always includes X-Request-ID. |
200 response body
| Field | Type | Required | Notes |
|---|---|---|---|
replayed | boolean | Yes | — |
canvasId | string | Yes | Pattern ^canvas:. |
canvasRevision | string | Yes | — |
canvasUrl | string (uri) | Yes | — |
image | object | Yes | — |
image.assetId | string | Yes | Pattern ^asset:. |
image.nodeId | string | Yes | Pattern ^node:. |
image.mediaType | string | Yes | One of image/png, image/jpeg, image/webp, image/gif. |
image.width | integer | Yes | min 1. |
image.height | integer | Yes | min 1. |
image.bytes | integer | Yes | min 1, max 52428800. |
image.previewUrl | string (uri) | Yes | — |
image.markdown | string | Yes | — |
Example
curl -X POST "https://app.gavana.ai/api/canvas-agent/v1/images/import" \
-H "Authorization: Bearer $GAVANA_AGENT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"canvasId": "canvas:8f2c1d40-9a77-4c2e-9c11-2b0a5f6d7e31",
"imageUrl": "https://example.com/gavana-webhook",
"idempotencyKey": "2026-08-04-first-attempt"
}'POST /images/variations
Queue image variations
- Operation id:
startImageVariations - Scopes: Requires
canvas:read+canvas:write+asset:read+image:generate. When elements contains at least one version-pinned Element, also requireselement:read. - CLI equivalent:
gavana image variations
Request body (application/json, required)
At least one of references or source is 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 | No | Pattern ^(?:node:)?[A-Za-z0-9_-]{1,180}$. |
targetNodeIds | array of string | No | min items 1, max items 4. |
prompt | string | No | min length 1, max length 8000. |
promptNodeId | string | No | Pattern ^(?:node:)?[A-Za-z0-9_-]{1,180}$. |
references | array of string | ImageReferenceInput | No | Stable image handles or role-bearing reference objects. Across references and source, at most 16 handles are allowed and every handle must be unique. When omitted for one named target, Gavana may derive visible incoming mode:reference image edges; hidden provider plumbing is never derived. min items 1, max items 16. |
elements | array of ElementGenerationReference | No | Up to eight reusable Elements pinned to exact immutable versions. Their source images share the 16-image limit with references and source. element:read is required when this array is non-empty. max items 8. |
source | string | No | A convenience reference appended to references. It must be unique across both fields, and the combined maximum is 16. Pattern ^(?:node:[A-Za-z0-9_-]{1,180}|asset:(?:[A-Za-z0-9_-]{1,180}:)?[A-Za-z0-9_-]{1,180})$. |
count | integer | No | Number of outputs. When supplied, it must equal the selected target count; when omitted, Gavana uses the selected target count. min 1, max 4. |
connectionId | string | No | Pattern ^[A-Za-z0-9_-]{1,180}$. |
model | string | No | A provider model id or opaque model:<key> handle from GET /models. max length 650. |
size | string | No | max length 80. |
quality | string | No | max length 80. |
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. |
(variant 2) (variant 1).count | 1 | No | — |
(variant 3) (variant 1).count | 2 | No | — |
(variant 4) (variant 1).count | 3 | No | — |
(variant 5) (variant 1).count | 4 | No | — |
Validation rules the service enforces across these fields:
- references and source contain at most 16 handles combined
- references and source are unique when combined
- role-bearing references retain their exact handle and role in job and canvas provenance
- count equals the selected target count
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/images/variations" \
-H "Authorization: Bearer $GAVANA_AGENT_TOKEN" \
-H "Content-Type: application/json" \
-d '{}'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.