Recipes
Discover, fork, and explicitly run approved or private Recipe workflows.
Base URL: https://app.gavana.ai/api/canvas-agent/v1 · Authentication: HTTP bearer, token format cba_<token-id>.<secret>
Operations
| Operation | Purpose | Scopes |
|---|---|---|
POST /canvases/{canvasId}/workflows | Create a private reusable workflow without running it | canvas:read, canvas:write |
GET /recipes | Search approved Recipes | canvas:read |
GET /recipes/{recipeId} | Get an approved Recipe | canvas:read |
POST /recipes/{recipeId}/fork | Fork a Recipe into a canvas without running it | canvas:read, canvas:write |
POST /recipes/{recipeId}/runs | Run a Recipe explicitly | canvas:read, canvas:write, asset:read, image:generate |
POST /canvases/{canvasId}/workflows
Create a private reusable workflow without running it
Creates the workflow graph, a private Recipe draft, and a compact runnable Recipe instance. Inputs marked useAsDefault reuse their saved source on later runs, so callers only need to provide changing inputs. This operation does not start generation or consume provider credits.
- Operation id:
createCanvasWorkflow - Scopes: Requires
canvas:read+canvas:write.
Parameters
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
canvasId | path | string | Yes | Pattern ^[A-Za-z0-9_-]{1,180}$. |
ownerUid | query | string | No | Identifies 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)
| Field | Type | Required | Notes |
|---|---|---|---|
name | string | Yes | min length 1, max length 160. |
description | string | No | max length 1200. |
category | string | No | One of Brand & Visual Design, Product Visualization, Marketing & Ads, Content Package. Default "Product Visualization". |
tags | array of string | No | max items 12. |
inputs | array of CanvasWorkflowInput | Yes | min items 1, max items 16. |
inputs[].key | string | Yes | Pattern ^[A-Za-z0-9_-]{1,80}$. |
inputs[].label | string | Yes | min length 1, max length 80. |
inputs[].description | string | No | max length 200. |
inputs[].type | string | Yes | One of image, text, sticky. |
inputs[].sourceNodeId | string | No | Pattern ^(?:node:)?[A-Za-z0-9_-]{1,180}$. |
inputs[].value | string | No | max length 8000. |
inputs[].useAsDefault | boolean | Yes | When true, preserve this durable source or text value as the input used when a later run omits the port. |
outputs | array of CanvasWorkflowOutput | Yes | min items 1, max items 8. |
outputs[].key | string | Yes | Pattern ^[A-Za-z0-9_-]{1,80}$. |
outputs[].label | string | Yes | min length 1, max length 80. |
outputs[].description | string | No | max length 200. |
outputs[].type | string | Yes | One of image, text. |
outputs[].prompt | string | Yes | min length 1, max length 8000. |
outputs[].inputKeys | array of string | Yes | min items 1, max items 16. |
outputs[].model | string | No | max length 650. |
outputs[].size | string | No | max length 80. |
outputs[].quality | string | No | max length 80. |
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 | CanvasWorkflowMutationResponse | A private reusable workflow creation or idempotent replay result. |
201 | CanvasWorkflowMutationResponse | A private reusable workflow creation or idempotent replay result. |
default | ErrorResponse | A stable machine-readable error. The response always includes X-Request-ID. |
200 response body
| Field | Type | Required | Notes |
|---|---|---|---|
canvas | Canvas | Yes | — |
canvas.id | string | Yes | Pattern ^[A-Za-z0-9_-]{1,180}$. |
canvas.canvasType | string | No | One of agent. |
canvas.handle | string | Yes | Pattern ^canvas:[A-Za-z0-9_-]+:[A-Za-z0-9_-]+$. |
canvas.ownerUid | string | Yes | Pattern ^[A-Za-z0-9_-]{1,180}$. |
canvas.title | string | Yes | max length 160. |
canvas.createdAt | string (date-time) | Yes | — |
canvas.updatedAt | string (date-time) | Yes | — |
canvas.revision | string | Yes | min length 1. |
canvas.nodes | array of CanvasNode | Yes | — |
canvas.nodes[].id | string | Yes | Pattern ^[A-Za-z0-9_-]{1,180}$. |
canvas.nodes[].handle | string | Yes | Pattern ^node:. |
canvas.nodes[].type | string | Yes | One of image, video, text, sticky. |
canvas.nodes[].title | string | Yes | — |
canvas.nodes[].position | Position | Yes | — |
canvas.nodes[].position.x | number | Yes | min -10000000, max 10000000. |
canvas.nodes[].position.y | number | Yes | min -10000000, max 10000000. |
canvas.nodes[].width | number | Yes | — |
canvas.nodes[].height | number | Yes | — |
canvas.nodes[].metadata | object | No | — |
canvas.nodes[].asset | string | No | Pattern ^asset:. |
canvas.connections | array of CanvasConnection | Yes | — |
canvas.connections[].id | string | Yes | Pattern ^[A-Za-z0-9_-]{1,180}$. |
canvas.connections[].handle | string | Yes | Pattern ^connection:. |
canvas.connections[].fromNodeId | string | Yes | Pattern ^[A-Za-z0-9_-]{1,180}$. |
canvas.connections[].toNodeId | string | Yes | Pattern ^[A-Za-z0-9_-]{1,180}$. |
canvas.connections[].from | string | Yes | Pattern ^node:. |
canvas.connections[].to | string | Yes | Pattern ^node:. |
replayed | boolean | No | — |
resolvedIds | object | No | — |
changedNodeIds | array of string | No | — |
deletedNodeIds | array of string | No | — |
changedConnectionIds | array of string | No | — |
deletedConnectionIds | array of string | No | — |
workflow | CanvasWorkflowResponse | Yes | — |
workflow.id | string | Yes | Pattern ^[A-Za-z0-9_-]{1,180}$. |
workflow.handle | string | Yes | Pattern ^recipe:. |
workflow.version | string | Yes | — |
workflow.name | string | Yes | — |
workflow.recipeNodeId | string | No | Handle of the visible Recipe definition card. Present only when that card exists on the canvas; omitted while the Recipe UI is disabled. Pattern ^node:. |
workflow.workflowNodeId | string | Yes | Pattern ^node:. |
workflow.inputs | array of CanvasWorkflowInputResponse | Yes | — |
workflow.inputs[].key | string | Yes | Pattern ^[A-Za-z0-9_-]{1,80}$. |
workflow.inputs[].portNodeId | string | Yes | Pattern ^node:. |
workflow.inputs[].nodeId | string | Yes | Pattern ^node:. |
workflow.inputs[].label | string | Yes | — |
workflow.inputs[].useAsDefault | boolean | Yes | — |
workflow.outputs | array of CanvasWorkflowOutputResponse | Yes | — |
workflow.outputs[].key | string | Yes | Pattern ^[A-Za-z0-9_-]{1,80}$. |
workflow.outputs[].portNodeId | string | Yes | Pattern ^node:. |
workflow.outputs[].templateNodeId | string | Yes | Pattern ^node:. |
workflow.outputs[].label | string | Yes | — |
Example
curl -X POST "https://app.gavana.ai/api/canvas-agent/v1/canvases/canvas:8f2c1d40-9a77-4c2e-9c11-2b0a5f6d7e31/workflows" \
-H "Authorization: Bearer $GAVANA_AGENT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "<name>",
"idempotencyKey": "2026-08-04-first-attempt",
"inputs": [
{}
],
"outputs": [
{}
]
}'GET /recipes
Search approved Recipes
- Operation id:
searchRecipes - Scopes: Requires
canvas:read. - CLI equivalent:
gavana recipe search
Parameters
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
q | query | string | No | Free-text Recipe Library search. max length 500. |
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 | Approved Recipe Library search results. |
default | ErrorResponse | A stable machine-readable error. The response always includes X-Request-ID. |
200 response body
| Field | Type | Required | Notes |
|---|---|---|---|
recipes | array of Recipe | Yes | — |
recipes[].id | string | Yes | Pattern ^[A-Za-z0-9_-]{1,180}$. |
recipes[].handle | string | Yes | Pattern ^recipe:. |
recipes[].version | string | Yes | — |
recipes[].name | string | Yes | — |
recipes[].summary | string | No | — |
recipes[].description | string | No | — |
recipes[].tags | array of string | No | — |
recipes[].inputs | array of RecipePort | Yes | — |
recipes[].inputs[].nodeId | string | Yes | Pattern ^[A-Za-z0-9_-]{1,180}$. |
recipes[].inputs[].key | string | No | Optional stable caller-facing key for a high-level workflow input or output. Pattern ^[A-Za-z0-9_-]{1,80}$. |
recipes[].inputs[].label | string | Yes | — |
recipes[].inputs[].description | string | Yes | — |
recipes[].inputs[].useAsPreset | boolean | Yes | — |
recipes[].inputs[].nodeType | string | Yes | One of image, text, sticky. |
recipes[].outputs | array of RecipePort | Yes | — |
recipes[].outputs[].nodeId | string | Yes | Pattern ^[A-Za-z0-9_-]{1,180}$. |
recipes[].outputs[].key | string | No | Optional stable caller-facing key for a high-level workflow input or output. Pattern ^[A-Za-z0-9_-]{1,80}$. |
recipes[].outputs[].label | string | Yes | — |
recipes[].outputs[].description | string | Yes | — |
recipes[].outputs[].useAsPreset | boolean | Yes | — |
recipes[].outputs[].nodeType | string | Yes | One of image, text, sticky. |
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/recipes" \
-H "Authorization: Bearer $GAVANA_AGENT_TOKEN"GET /recipes/{recipeId}
Get an approved Recipe
- Operation id:
getRecipe - Scopes: Requires
canvas:read. - CLI equivalent:
gavana recipe get
Parameters
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
recipeId | path | string | Yes | Pattern ^[A-Za-z0-9_-]{1,180}$. |
version | query | string | No | Optional immutable Recipe version. max length 80. |
Responses
| Status | Payload | Meaning |
|---|---|---|
200 | object | An approved Recipe Library workflow. |
default | ErrorResponse | A stable machine-readable error. The response always includes X-Request-ID. |
200 response body
| Field | Type | Required | Notes |
|---|---|---|---|
recipe | Recipe | Yes | — |
recipe.id | string | Yes | Pattern ^[A-Za-z0-9_-]{1,180}$. |
recipe.handle | string | Yes | Pattern ^recipe:. |
recipe.version | string | Yes | — |
recipe.name | string | Yes | — |
recipe.summary | string | No | — |
recipe.description | string | No | — |
recipe.tags | array of string | No | — |
recipe.inputs | array of RecipePort | Yes | — |
recipe.inputs[].nodeId | string | Yes | Pattern ^[A-Za-z0-9_-]{1,180}$. |
recipe.inputs[].key | string | No | Optional stable caller-facing key for a high-level workflow input or output. Pattern ^[A-Za-z0-9_-]{1,80}$. |
recipe.inputs[].label | string | Yes | — |
recipe.inputs[].description | string | Yes | — |
recipe.inputs[].useAsPreset | boolean | Yes | — |
recipe.inputs[].nodeType | string | Yes | One of image, text, sticky. |
recipe.outputs | array of RecipePort | Yes | — |
recipe.outputs[].nodeId | string | Yes | Pattern ^[A-Za-z0-9_-]{1,180}$. |
recipe.outputs[].key | string | No | Optional stable caller-facing key for a high-level workflow input or output. Pattern ^[A-Za-z0-9_-]{1,80}$. |
recipe.outputs[].label | string | Yes | — |
recipe.outputs[].description | string | Yes | — |
recipe.outputs[].useAsPreset | boolean | Yes | — |
recipe.outputs[].nodeType | string | Yes | One of image, text, sticky. |
Example
curl "https://app.gavana.ai/api/canvas-agent/v1/recipes/recipe:social-creative-angles" \
-H "Authorization: Bearer $GAVANA_AGENT_TOKEN"POST /recipes/{recipeId}/fork
Fork a Recipe into a canvas without running it
- Operation id:
forkRecipe - Scopes: Requires
canvas:read+canvas:write. - CLI equivalent:
gavana recipe fork
Parameters
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
recipeId | path | string | Yes | Pattern ^[A-Za-z0-9_-]{1,180}$. |
Request body (application/json, required)
| Field | Type | Required | Notes |
|---|---|---|---|
canvasId | string | Yes | A plain canvas id. |
ownerUid | string | No | Pattern ^[A-Za-z0-9_-]{1,180}$. |
version | string | No | max length 80. |
baseRevision | string | Yes | min length 1, max length 200. |
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 | MutationResponse | A revision-safe canvas mutation result. |
201 | MutationResponse | A revision-safe canvas mutation result. |
default | ErrorResponse | A stable machine-readable error. The response always includes X-Request-ID. |
200 response body
| Field | Type | Required | Notes |
|---|---|---|---|
canvas | Canvas | Yes | — |
canvas.id | string | Yes | Pattern ^[A-Za-z0-9_-]{1,180}$. |
canvas.canvasType | string | No | One of agent. |
canvas.handle | string | Yes | Pattern ^canvas:[A-Za-z0-9_-]+:[A-Za-z0-9_-]+$. |
canvas.ownerUid | string | Yes | Pattern ^[A-Za-z0-9_-]{1,180}$. |
canvas.title | string | Yes | max length 160. |
canvas.createdAt | string (date-time) | Yes | — |
canvas.updatedAt | string (date-time) | Yes | — |
canvas.revision | string | Yes | min length 1. |
canvas.nodes | array of CanvasNode | Yes | — |
canvas.nodes[].id | string | Yes | Pattern ^[A-Za-z0-9_-]{1,180}$. |
canvas.nodes[].handle | string | Yes | Pattern ^node:. |
canvas.nodes[].type | string | Yes | One of image, video, text, sticky. |
canvas.nodes[].title | string | Yes | — |
canvas.nodes[].position | Position | Yes | — |
canvas.nodes[].position.x | number | Yes | min -10000000, max 10000000. |
canvas.nodes[].position.y | number | Yes | min -10000000, max 10000000. |
canvas.nodes[].width | number | Yes | — |
canvas.nodes[].height | number | Yes | — |
canvas.nodes[].metadata | object | No | — |
canvas.nodes[].asset | string | No | Pattern ^asset:. |
canvas.connections | array of CanvasConnection | Yes | — |
canvas.connections[].id | string | Yes | Pattern ^[A-Za-z0-9_-]{1,180}$. |
canvas.connections[].handle | string | Yes | Pattern ^connection:. |
canvas.connections[].fromNodeId | string | Yes | Pattern ^[A-Za-z0-9_-]{1,180}$. |
canvas.connections[].toNodeId | string | Yes | Pattern ^[A-Za-z0-9_-]{1,180}$. |
canvas.connections[].from | string | Yes | Pattern ^node:. |
canvas.connections[].to | string | Yes | Pattern ^node:. |
replayed | boolean | No | — |
resolvedIds | object | No | — |
changedNodeIds | array of string | No | — |
deletedNodeIds | array of string | No | — |
changedConnectionIds | array of string | No | — |
deletedConnectionIds | array of string | No | — |
Example
curl -X POST "https://app.gavana.ai/api/canvas-agent/v1/recipes/recipe:social-creative-angles/fork" \
-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"
}'POST /recipes/{recipeId}/runs
Run a Recipe explicitly
Creates or reuses a private Recipe instance, binds typed inputs, materializes declared output nodes, and queues sequential text or image work. Forking a Recipe never calls this operation automatically.
- Operation id:
startRecipeRun - Scopes: Requires
canvas:read+canvas:write+asset:read+image:generate. - CLI equivalent:
gavana recipe run
Parameters
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
recipeId | path | string | Yes | Pattern ^[A-Za-z0-9_-]{1,180}$. |
Request body (application/json, required)
| Field | Type | Required | Notes |
|---|---|---|---|
canvasId | string | Yes | Stable canvas:<id> or canvas:<ownerUid>:<id> destination. min length 1, max length 560. |
baseRevision | string | Yes | min length 1, max length 200. |
idempotencyKey | string | Yes | min length 8, max length 200. |
version | string | No | max length 80. |
instanceNodeId | string | No | Optional private Recipe instance already present and connected on the destination canvas. Pattern ^(?:node:)?[A-Za-z0-9_-]{1,180}$. |
inputs | object | No | Typed values keyed by the declared input node id or normalized label. Values may be node:, asset:, or plain text. |
model | string | No | Optional model handle or provider model override for image outputs. max length 650. |
size | string | No | Optional size override for image outputs. max length 80. |
quality | string | No | Optional quality override for image outputs. 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. |
Responses
| Status | Payload | Meaning |
|---|---|---|
202 | RecipeRun | A durable Recipe Run with typed input bindings and declared output state. |
default | ErrorResponse | A stable machine-readable error. The response always includes X-Request-ID. |
202 response body
| Field | Type | Required | Notes |
|---|---|---|---|
id | string | Yes | Pattern ^recipe-. |
rawId | string | Yes | Pattern ^recipe-. |
handle | string | Yes | Pattern ^run:recipe-. |
run | string | Yes | Pattern ^run:recipe-. |
status | string | Yes | One of queued, running, succeeded, failed, canceled. |
recipeId | string | Yes | Pattern ^[A-Za-z0-9_-]{1,180}$. |
recipeHandle | string | Yes | Pattern ^recipe:. |
recipeVersion | string | Yes | — |
recipeInstanceNodeId | string | Yes | Pattern ^[A-Za-z0-9_-]{1,180}$. |
recipeInstanceNodeHandle | string | Yes | Pattern ^node:. |
canvasId | string | Yes | Pattern ^[A-Za-z0-9_-]{1,180}$. |
canvasHandle | string | Yes | Pattern ^canvas:. |
canvasUrl | string (uri) | No | — |
inputs | array of RecipeRunInputBinding | Yes | — |
inputs[].key | string | Yes | — |
inputs[].label | string | Yes | — |
inputs[].type | string | Yes | One of image, text, sticky. |
inputs[].nodeId | string | Yes | Pattern ^[A-Za-z0-9_-]{1,180}$. |
inputs[].nodeHandle | string | Yes | Pattern ^node:. |
inputs[].sourceHandle | string | No | Pattern ^(?:node|asset):. |
inputs[].summary | string | Yes | — |
outputs | array of RecipeRunOutput | Yes | — |
outputs[].key | string | Yes | — |
outputs[].label | string | Yes | — |
outputs[].type | string | Yes | One of image, text, sticky. |
outputs[].status | string | Yes | One of pending, running, succeeded, failed, canceled. |
outputs[].nodeId | string | Yes | Pattern ^[A-Za-z0-9_-]{1,180}$. |
outputs[].nodeHandle | string | Yes | Pattern ^node:. |
outputs[].jobId | string (uuid) | No | — |
outputs[].runHandle | string | No | Pattern ^run:. |
outputs[].assetId | string | No | Pattern ^asset:. |
outputs[].value | string | No | max length 24000. |
outputs[].startedAt | string (date-time) | No | — |
outputs[].completedAt | string (date-time) | No | — |
outputs[].failure | RecipeRunFailure | No | — |
outputs[].failure.code | string | Yes | One of recipe_input_invalid, recipe_step_failed, recipe_output_missing, recipe_run_canceled, delegation_revoked. |
outputs[].failure.message | string | Yes | — |
outputs[].failure.retryable | boolean | Yes | — |
outputs[].failure.outputKey | string | No | — |
targets | array of string | Yes | — |
currentStep | string | Yes | — |
nextStep | string | No | — |
estimatedSeconds | integer | Yes | min 1. |
durationMs | integer | No | min 0. |
timing | ImageJobTiming | Yes | — |
timing.createdAt | string (date-time) | No | — |
timing.queuedAt | string (date-time) | No | — |
timing.startedAt | string (date-time) | No | — |
timing.completedAt | string (date-time) | No | — |
timing.queueDurationMs | integer | No | min 0. |
timing.executionDurationMs | integer | No | min 0. |
timing.totalDurationMs | integer | No | min 0. |
failure | RecipeRunFailure | No | — |
failure.code | string | Yes | One of recipe_input_invalid, recipe_step_failed, recipe_output_missing, recipe_run_canceled, delegation_revoked. |
failure.message | string | Yes | — |
failure.retryable | boolean | Yes | — |
failure.outputKey | string | No | — |
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. |
webhook.id | string | Yes | Pattern ^webhook:. |
webhook.status | string | Yes | One of pending, delivering, delivered, failed. |
webhook.attempts | integer | Yes | min 0. |
webhook.nextAttemptAt | string (date-time) | No | — |
webhook.lastAttemptAt | string (date-time) | No | — |
webhook.deliveredAt | string (date-time) | No | — |
webhook.lastStatus | integer | No | min 100, max 599. |
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. |
replayed | boolean | No | — |
pollUrl | string | Yes | Pattern ^/api/canvas-agent/v1/runs/. |
createdAt | string (date-time) | Yes | — |
updatedAt | string (date-time) | Yes | — |
startedAt | string (date-time) | No | — |
completedAt | string (date-time) | No | — |
canceledAt | string (date-time) | No | — |
completionReview | CanvasCompletionReview | No | — |
completionReview.status | string | Yes | One of ready, needs-review, blocked. |
completionReview.doneClaimAllowed | boolean | Yes | False while agent-owned spatial or lineage findings remain, or a generated output is pending, failed, or non-durable. |
completionReview.instruction | string | Yes | — |
completionReview.outputs | CanvasCompletionOutputs | Yes | Generated-output count and durable, pending, and failed breakdown. |
completionReview.outputs.count | integer | Yes | min 0. |
completionReview.outputs.durableCount | integer | Yes | min 0. |
completionReview.outputs.pendingCount | integer | Yes | min 0. |
completionReview.outputs.failedCount | integer | Yes | min 0. |
completionReview.outputs.handles | array of string | Yes | — |
completionReview.overlap | CanvasCompletionFindingArea | Yes | — |
completionReview.overlap.status | string | Yes | One of clear, needs-review, blocked. |
completionReview.overlap.findingCodes | array of string | Yes | — |
completionReview.overlap.nodeHandles | array of string | Yes | — |
completionReview.overlap.connectionHandles | array of string | Yes | — |
completionReview.containment | CanvasCompletionFindingArea | Yes | — |
completionReview.containment.status | string | Yes | One of clear, needs-review, blocked. |
completionReview.containment.findingCodes | array of string | Yes | — |
completionReview.containment.nodeHandles | array of string | Yes | — |
completionReview.containment.connectionHandles | array of string | Yes | — |
completionReview.referenceLineage | CanvasCompletionFindingArea | Yes | — |
completionReview.referenceLineage.status | string | Yes | One of clear, needs-review, blocked. |
completionReview.referenceLineage.findingCodes | array of string | Yes | — |
completionReview.referenceLineage.nodeHandles | array of string | Yes | — |
completionReview.referenceLineage.connectionHandles | array of string | Yes | — |
completionReview.productFidelity | CanvasProductFidelityReview | Yes | A conservative review signal, not an authoritative visual inspection. |
completionReview.productFidelity.status | string | Yes | One of not-applicable, needs-review, passed. |
completionReview.productFidelity.reviewedOutputCount | integer | Yes | min 0. |
completionReview.productFidelity.needsReviewOutputHandles | array of string | Yes | — |
completionReview.productFidelity.evidenceMissingOutputHandles | array of string | Yes | — |
completionReview.productFidelity.reasons | array of object | No | — |
completionReview.productFidelity.reasons[].nodeHandle | string | Yes | Pattern ^node:. |
completionReview.productFidelity.reasons[].reason | string | Yes | — |
completionReview.delivery | CanvasCompletionDelivery | Yes | Generated-output delivery evidence. A blocked state prevents a Done claim. |
completionReview.delivery.status | string | Yes | One of clear, blocked. |
completionReview.delivery.reasons | array of string | No | — |
completionReview.delivery.pendingOutputHandles | array of string | Yes | — |
completionReview.delivery.failedOutputHandles | array of string | Yes | — |
completionReview.delivery.nonDurableOutputHandles | array of string | Yes | — |
completionReview.blockingFindingCodes | array of string | Yes | — |
completionReview.advisoryFindingCodes | array of string | Yes | — |
Callbacks
recipeRunTerminal→{$request.body#/webhook/url}: Receive a signed terminal Recipe Run 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. Private-network destinations are blocked.
Example
curl -X POST "https://app.gavana.ai/api/canvas-agent/v1/recipes/recipe:social-creative-angles/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"
}'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.