English
Templates
Routes are relative to <PUBLIC_BASE_URL>; request and response bodies are JSON unless stated otherwise. Authentication, scopes, pagination and the error format are described in the REST API guides.
GET /api/v1/templates
List the templates of the instance
What the member can install. An administrator receives the same shape, disabled templates included.
Access — Member session or API key with scope templates:read.
Responses
200 — The templates.
| Field | Type | Required |
|---|---|---|
templates | object[] | yes |
JSON Schema
json
{
"type": "object",
"properties": {
"templates": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"name": { "type": "string" },
"description": { "type": "string" },
"category": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"enabled": { "type": "boolean" },
"nodeTypes": { "type": "array", "items": { "type": "string" } },
"requiresProviders": { "type": "array", "items": { "type": "string" } },
"createdBy": {
"anyOf": [
{
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
{ "type": "null" }
]
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
"updatedAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
"installCount": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }
},
"required": [
"id",
"name",
"description",
"category",
"enabled",
"nodeTypes",
"requiresProviders",
"createdBy",
"createdAt",
"updatedAt",
"installCount"
],
"additionalProperties": false
}
}
},
"required": [ "templates" ],
"additionalProperties": false
}401 — No valid session or API key (auth.unauthenticated).
403 — Refused: insufficient role (auth.forbidden), missing scope (api_key.scope_missing, details.required names it) or a route closed to API keys (api_key.session_required).
429 — The API key exceeded its rate limit (api_key.rate_limited); Retry-After says when to retry.
GET /api/v1/templates/{id}
Read a template and its graph
The graph travels so the installation can be a considered choice. For a member, a disabled template is the same 404 as an unknown id.
Access — Member session or API key with scope templates:read.
Parameters
| Name | In | Type | Required |
|---|---|---|---|
id | path | string | yes |
Responses
200 — The template.
| Field | Type | Required |
|---|---|---|
template | object | yes |
graph | object | yes |
JSON Schema
json
{
"type": "object",
"properties": {
"template": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"name": { "type": "string" },
"description": { "type": "string" },
"category": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"enabled": { "type": "boolean" },
"nodeTypes": { "type": "array", "items": { "type": "string" } },
"requiresProviders": { "type": "array", "items": { "type": "string" } },
"createdBy": {
"anyOf": [
{
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
{ "type": "null" }
]
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
"updatedAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
"installCount": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }
},
"required": [
"id",
"name",
"description",
"category",
"enabled",
"nodeTypes",
"requiresProviders",
"createdBy",
"createdAt",
"updatedAt",
"installCount"
],
"additionalProperties": false
},
"graph": {
"type": "object",
"properties": {
"id": {},
"workflowId": {},
"nodes": {
"readOnly": true,
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {},
"type": { "type": "string", "minLength": 1, "maxLength": 128 },
"version": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
},
"name": { "type": "string", "minLength": 1, "maxLength": 200 },
"params": {
"default": {},
"type": "object",
"propertyNames": { "type": "string" },
"additionalProperties": {}
},
"onError": {
"default": "fail",
"type": "string",
"enum": [ "fail", "continue", "errorPort" ]
},
"retry": {
"type": "object",
"properties": {
"maxAttempts": { "type": "integer", "minimum": 1, "maximum": 10 },
"delayMs": { "type": "integer", "minimum": 1000, "maximum": 3600000 }
},
"required": [ "maxAttempts" ],
"additionalProperties": false
},
"timeoutMs": { "type": "integer", "minimum": 5000, "maximum": 1800000 },
"position": {
"type": "object",
"properties": { "x": { "type": "number" }, "y": { "type": "number" } },
"required": [ "x", "y" ],
"additionalProperties": false
},
"disabled": { "type": "boolean" },
"notes": { "type": "string", "maxLength": 2000 }
},
"required": [ "id", "type", "version", "name", "params", "onError" ],
"additionalProperties": false
}
},
"connections": {
"readOnly": true,
"type": "array",
"items": {
"type": "object",
"properties": {
"from": {},
"output": { "type": "string" },
"to": {},
"input": { "type": "string" },
"kind": { "type": "string", "enum": [ "data", "service" ] }
},
"required": [ "from", "output", "to" ],
"additionalProperties": false
}
},
"notes": {
"readOnly": true,
"type": "array",
"items": {
"type": "object",
"properties": {
"id": { "type": "string", "minLength": 1, "maxLength": 64 },
"text": { "default": "", "type": "string", "maxLength": 4000 },
"position": {
"type": "object",
"properties": { "x": { "type": "number" }, "y": { "type": "number" } },
"required": [ "x", "y" ],
"additionalProperties": false
},
"size": {
"default": { "width": 240, "height": 160 },
"type": "object",
"properties": {
"width": { "type": "number", "minimum": 120, "maximum": 2000 },
"height": { "type": "number", "minimum": 80, "maximum": 2000 }
},
"required": [ "width", "height" ],
"additionalProperties": false
},
"color": {
"default": "jaune",
"type": "string",
"enum": [ "jaune", "menthe", "ciel", "rose", "lavande" ]
}
},
"required": [ "id", "text", "position", "size", "color" ],
"additionalProperties": false
}
},
"pins": {
"type": "object",
"propertyNames": { "type": "string", "minLength": 1, "maxLength": 64 },
"additionalProperties": {
"type": "object",
"properties": {
"output": {},
"port": { "type": "string" },
"pinnedAt": { "type": "string", "minLength": 1, "maxLength": 64 }
},
"required": [ "output", "pinnedAt" ],
"additionalProperties": false
}
}
},
"required": [ "id", "workflowId", "nodes", "connections" ],
"additionalProperties": false
}
},
"required": [ "template", "graph" ],
"additionalProperties": false
}401 — No valid session or API key (auth.unauthenticated).
403 — Refused: insufficient role (auth.forbidden), missing scope (api_key.scope_missing, details.required names it) or a route closed to API keys (api_key.session_required).
429 — The API key exceeded its rate limit (api_key.rate_limited); Retry-After says when to retry.
Error codes — templates.not_found. The common codes (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) apply to every route; see Errors.
POST /api/v1/templates/{id}/install
Install a template as a new draft
Creates a draft workflow owned by the member from a copy of the template graph; publishing stays an explicit step. A template using a node type the organisation forbids to this member is refused (409 templates.forbidden_node, the types in details.nodeTypes).
Access — Member session or API key with scope workflows:write.
Parameters
| Name | In | Type | Required |
|---|---|---|---|
id | path | string | yes |
Request body (application/json)
| Field | Type | Required |
|---|---|---|
name | string | no |
JSON Schema
json
{
"type": "object",
"properties": { "name": { "type": "string", "minLength": 1, "maxLength": 200 } }
}Responses
201 — The id of the new workflow.
| Field | Type | Required |
|---|---|---|
workflowId | string (uuid) | yes |
JSON Schema
json
{
"type": "object",
"properties": {
"workflowId": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
}
},
"required": [ "workflowId" ],
"additionalProperties": false
}400 — The request does not match its schema.
401 — No valid session or API key (auth.unauthenticated).
403 — Refused: insufficient role (auth.forbidden), missing scope (api_key.scope_missing, details.required names it) or a route closed to API keys (api_key.session_required).
429 — The API key exceeded its rate limit (api_key.rate_limited); Retry-After says when to retry.
This operation accepts an Idempotency-Key header: replaying the same request with the same key returns the original response instead of acting twice. See Idempotency.
Error codes — request.bad_request, templates.not_found, templates.forbidden_node. The common codes (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) apply to every route; see Errors.
Example request
json
{}Example response (201)
json
{ "workflowId": "0192f1c2-dddd-7000-8000-000000000011" }POST /api/v1/admin/templates/promote
Promote a workflow to a template
Freezes the graph of any member’s workflow (its published version, or its draft) as a template of the instance. A graph that fails validation is refused with 422 templates.invalid_graph and the diagnostic in details.validation.
Access — Member session or API key with scope admin:write (administrator role required).
Request body (application/json)
| Field | Type | Required |
|---|---|---|
workflowId | string (uuid) | yes |
name | string | yes |
description | string | yes |
category | string | null | no |
JSON Schema
json
{
"type": "object",
"properties": {
"workflowId": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"name": { "type": "string", "minLength": 1, "maxLength": 120 },
"description": { "type": "string", "maxLength": 2000 },
"category": {
"anyOf": [
{ "type": "string", "minLength": 1, "maxLength": 60 },
{ "type": "null" }
]
}
},
"required": [ "workflowId", "name", "description" ]
}Responses
201 — The template.
| Field | Type | Required |
|---|---|---|
template | object | yes |
JSON Schema
json
{
"type": "object",
"properties": {
"template": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"name": { "type": "string" },
"description": { "type": "string" },
"category": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"enabled": { "type": "boolean" },
"nodeTypes": { "type": "array", "items": { "type": "string" } },
"requiresProviders": { "type": "array", "items": { "type": "string" } },
"createdBy": {
"anyOf": [
{
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
{ "type": "null" }
]
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
"updatedAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
"installCount": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }
},
"required": [
"id",
"name",
"description",
"category",
"enabled",
"nodeTypes",
"requiresProviders",
"createdBy",
"createdAt",
"updatedAt",
"installCount"
],
"additionalProperties": false
}
},
"required": [ "template" ],
"additionalProperties": false
}400 — The request does not match its schema.
401 — No valid session or API key (auth.unauthenticated).
403 — Refused: insufficient role (auth.forbidden), missing scope (api_key.scope_missing, details.required names it) or a route closed to API keys (api_key.session_required).
429 — The API key exceeded its rate limit (api_key.rate_limited); Retry-After says when to retry.
This operation accepts an Idempotency-Key header: replaying the same request with the same key returns the original response instead of acting twice. See Idempotency.
Error codes — request.bad_request, templates.workflow_not_found, templates.invalid_graph. The common codes (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) apply to every route; see Errors.
PUT /api/v1/admin/templates/{id}
Update the metadata of a template
Partial, and metadata only (name, description, category, enabled). category: null clears it, an absent key leaves it. The graph never changes: promote again for a new one.
Access — Member session or API key with scope admin:write (administrator role required).
Parameters
| Name | In | Type | Required |
|---|---|---|---|
id | path | string | yes |
Request body (application/json)
| Field | Type | Required |
|---|---|---|
name | string | no |
description | string | no |
category | string | null | no |
enabled | boolean | no |
JSON Schema
json
{
"type": "object",
"properties": {
"name": { "type": "string", "minLength": 1, "maxLength": 120 },
"description": { "type": "string", "maxLength": 2000 },
"category": {
"anyOf": [
{ "type": "string", "minLength": 1, "maxLength": 60 },
{ "type": "null" }
]
},
"enabled": { "type": "boolean" }
}
}Responses
200 — The template, updated.
| Field | Type | Required |
|---|---|---|
template | object | yes |
Same schema as POST /api/v1/admin/templates/promote.
400 — The request does not match its schema.
401 — No valid session or API key (auth.unauthenticated).
403 — Refused: insufficient role (auth.forbidden), missing scope (api_key.scope_missing, details.required names it) or a route closed to API keys (api_key.session_required).
429 — The API key exceeded its rate limit (api_key.rate_limited); Retry-After says when to retry.
Error codes — request.bad_request, templates.not_found. The common codes (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) apply to every route; see Errors.
DELETE /api/v1/admin/templates/{id}
Delete a template
The workflows already installed from it are untouched: each received its own copy of the graph.
Access — Member session or API key with scope admin:write (administrator role required).
Parameters
| Name | In | Type | Required |
|---|---|---|---|
id | path | string | yes |
Responses
204 — Deleted.
401 — No valid session or API key (auth.unauthenticated).
403 — Refused: insufficient role (auth.forbidden), missing scope (api_key.scope_missing, details.required names it) or a route closed to API keys (api_key.session_required).
429 — The API key exceeded its rate limit (api_key.rate_limited); Retry-After says when to retry.
Error codes — templates.not_found. The common codes (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) apply to every route; see Errors.
GET /api/v1/gallery
The public gallery, seen from the member
Whether a gallery is configured (GALLERY_URL), the creator profile linked to the caller, and whether the instance can submit through its control plane link.
Access — Member session or API key with scope templates:read.
Responses
200 — The gallery status.
| Field | Type | Required |
|---|---|---|
enabled | boolean | yes |
galleryUrl | string (uri) | null | yes |
creator | object | null | yes |
instanceLink | boolean | yes |
productVersion | string | yes |
JSON Schema
json
{
"type": "object",
"properties": {
"enabled": { "type": "boolean" },
"galleryUrl": { "anyOf": [ { "type": "string", "format": "uri" }, { "type": "null" } ] },
"creator": {
"anyOf": [
{
"type": "object",
"properties": {
"slug": { "type": "string" },
"name": { "type": "string" },
"profileUrl": {
"anyOf": [ { "type": "string", "format": "uri" }, { "type": "null" } ]
}
},
"required": [ "slug", "name", "profileUrl" ],
"additionalProperties": false
},
{ "type": "null" }
]
},
"instanceLink": { "type": "boolean" },
"productVersion": { "type": "string" }
},
"required": [ "enabled", "galleryUrl", "creator", "instanceLink", "productVersion" ],
"additionalProperties": false
}401 — No valid session or API key (auth.unauthenticated).
403 — Refused: insufficient role (auth.forbidden), missing scope (api_key.scope_missing, details.required names it) or a route closed to API keys (api_key.session_required).
429 — The API key exceeded its rate limit (api_key.rate_limited); Retry-After says when to retry.
PUT /api/v1/gallery/creator-token
Link a creator profile
Verifies the creator token against the gallery and keeps it sealed on the instance. Session only: a token is a personal credential.
Access — Member session only: API keys are refused (api_key.session_required).
Request body (application/json)
| Field | Type | Required |
|---|---|---|
token | string | yes |
JSON Schema
json
{
"type": "object",
"properties": { "token": { "type": "string", "minLength": 16, "maxLength": 200 } },
"required": [ "token" ]
}Responses
200 — The updated status.
| Field | Type | Required |
|---|---|---|
enabled | boolean | yes |
galleryUrl | string (uri) | null | yes |
creator | object | null | yes |
instanceLink | boolean | yes |
productVersion | string | yes |
Same schema as GET /api/v1/gallery.
400 — The request does not match its schema.
401 — No valid session or API key (auth.unauthenticated).
403 — Refused: insufficient role (auth.forbidden), missing scope (api_key.scope_missing, details.required names it) or a route closed to API keys (api_key.session_required).
429 — The API key exceeded its rate limit (api_key.rate_limited); Retry-After says when to retry.
Error codes — request.bad_request, gallery.disabled, gallery.invalid_token, gallery.encryption_disabled, gallery.unreachable. The common codes (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) apply to every route; see Errors.
DELETE /api/v1/gallery/creator-token
Unlink the creator profile
Access — Member session only: API keys are refused (api_key.session_required).
Responses
204 — Unlinked.
401 — No valid session or API key (auth.unauthenticated).
403 — Refused: insufficient role (auth.forbidden), missing scope (api_key.scope_missing, details.required names it) or a route closed to API keys (api_key.session_required).
429 — The API key exceeded its rate limit (api_key.rate_limited); Retry-After says when to retry.
POST /api/v1/gallery/export
Preview a workflow as a public template
Exports a workflow (its published version, or its draft) or an organisation template to the public format: connections, mailboxes, tables and remote resources become placeholders, addresses and secrets are scrubbed. Nothing is sent; the report lists what was removed.
Access — Member session or API key with scope templates:read.
Request body (application/json)
| Field | Type | Required |
|---|---|---|
source | object | yes |
metadata | object | yes |
JSON Schema
json
{
"type": "object",
"properties": {
"source": {
"oneOf": [
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "workflow" },
"id": { "type": "string", "minLength": 1 },
"version": { "type": "string", "enum": [ "published", "draft" ] }
},
"required": [ "kind", "id" ]
},
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "orgTemplate" },
"id": { "type": "string", "minLength": 1 }
},
"required": [ "kind", "id" ]
}
]
},
"metadata": {
"type": "object",
"properties": {
"title": {
"type": "object",
"properties": { "en": { "type": "string" }, "fr": { "type": "string" } },
"required": [ "en", "fr" ]
},
"description": {
"type": "object",
"properties": { "en": { "type": "string" }, "fr": { "type": "string" } },
"required": [ "en", "fr" ]
},
"category": {
"type": "string",
"enum": [
"triage",
"replies",
"extraction",
"follow-ups",
"approvals",
"sync",
"notifications",
"other"
]
},
"useCases": {
"default": [],
"maxItems": 6,
"type": "array",
"items": { "type": "string", "minLength": 1, "maxLength": 60 }
}
},
"required": [ "title", "description", "category" ]
}
},
"required": [ "source", "metadata" ]
}Responses
200 — The sanitised template and its report.
| Field | Type | Required |
|---|---|---|
template | object | yes |
report | object[] | yes |
JSON Schema
json
{
"type": "object",
"properties": {
"template": {
"type": "object",
"properties": {
"formatVersion": { "type": "number", "const": 1 },
"title": {
"type": "object",
"properties": {
"en": { "type": "string", "maxLength": 60 },
"fr": { "type": "string", "maxLength": 60 }
},
"required": [ "en", "fr" ],
"additionalProperties": false
},
"description": {
"type": "object",
"properties": {
"en": { "type": "string", "maxLength": 4000 },
"fr": { "type": "string", "maxLength": 4000 }
},
"required": [ "en", "fr" ],
"additionalProperties": false
},
"category": {
"type": "string",
"enum": [
"triage",
"replies",
"extraction",
"follow-ups",
"approvals",
"sync",
"notifications",
"other"
]
},
"useCases": {
"default": [],
"maxItems": 6,
"type": "array",
"items": {
"type": "string",
"maxLength": 60,
"pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$"
}
},
"integrations": {
"default": [],
"maxItems": 30,
"type": "array",
"items": {
"type": "string",
"maxLength": 80,
"pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$"
}
},
"nodeTypes": {
"default": [],
"maxItems": 200,
"type": "array",
"items": { "type": "string", "minLength": 1, "maxLength": 128 }
},
"minProductVersion": { "type": "string", "pattern": "^\\d+\\.\\d+\\.\\d+$" },
"placeholders": {
"default": [],
"maxItems": 500,
"type": "array",
"items": {
"type": "object",
"properties": {
"nodeId": { "type": "string", "minLength": 1, "maxLength": 64 },
"nodeType": { "type": "string", "minLength": 1, "maxLength": 128 },
"param": { "type": "string", "minLength": 1, "maxLength": 200 },
"kind": {
"type": "string",
"enum": [
"connection",
"mailbox",
"table",
"resource",
"address",
"secret"
]
},
"credentialType": { "type": "string", "maxLength": 80 },
"capability": { "type": "string", "maxLength": 80 },
"provider": { "type": "string", "maxLength": 80 },
"resource": { "type": "string", "maxLength": 80 }
},
"required": [ "nodeId", "nodeType", "param", "kind" ],
"additionalProperties": false
}
},
"graph": {
"type": "object",
"properties": {
"id": { "type": "string", "const": "template" },
"workflowId": { "type": "string", "const": "template" },
"nodes": {
"minItems": 1,
"maxItems": 200,
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {},
"type": { "type": "string", "minLength": 1, "maxLength": 128 },
"version": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
},
"name": { "type": "string", "minLength": 1, "maxLength": 200 },
"params": {
"default": {},
"type": "object",
"propertyNames": { "type": "string" },
"additionalProperties": {}
},
"onError": {
"default": "fail",
"type": "string",
"enum": [ "fail", "continue", "errorPort" ]
},
"retry": {
"type": "object",
"properties": {
"maxAttempts": { "type": "integer", "minimum": 1, "maximum": 10 },
"delayMs": { "type": "integer", "minimum": 1000, "maximum": 3600000 }
},
"required": [ "maxAttempts" ],
"additionalProperties": false
},
"timeoutMs": { "type": "integer", "minimum": 5000, "maximum": 1800000 },
"position": {
"type": "object",
"properties": { "x": { "type": "number" }, "y": { "type": "number" } },
"required": [ "x", "y" ],
"additionalProperties": false
},
"disabled": { "type": "boolean" },
"notes": { "type": "string", "maxLength": 2000 }
},
"required": [ "id", "type", "version", "name", "params", "onError" ],
"additionalProperties": false
}
},
"connections": {
"type": "array",
"items": {
"type": "object",
"properties": {
"from": {},
"output": { "type": "string" },
"to": {},
"input": { "type": "string" },
"kind": { "type": "string", "enum": [ "data", "service" ] }
},
"required": [ "from", "output", "to" ],
"additionalProperties": false
}
},
"notes": {
"maxItems": 50,
"type": "array",
"items": {
"type": "object",
"properties": {
"id": { "type": "string", "minLength": 1, "maxLength": 64 },
"text": { "default": "", "type": "string", "maxLength": 4000 },
"position": {
"type": "object",
"properties": { "x": { "type": "number" }, "y": { "type": "number" } },
"required": [ "x", "y" ],
"additionalProperties": false
},
"size": {
"default": { "width": 240, "height": 160 },
"type": "object",
"properties": {
"width": { "type": "number", "minimum": 120, "maximum": 2000 },
"height": { "type": "number", "minimum": 80, "maximum": 2000 }
},
"required": [ "width", "height" ],
"additionalProperties": false
},
"color": {
"default": "jaune",
"type": "string",
"enum": [ "jaune", "menthe", "ciel", "rose", "lavande" ]
}
},
"required": [ "id", "text", "position", "size", "color" ],
"additionalProperties": false
}
}
},
"required": [ "id", "workflowId", "nodes", "connections" ],
"additionalProperties": false
}
},
"required": [
"formatVersion",
"title",
"description",
"category",
"useCases",
"integrations",
"nodeTypes",
"minProductVersion",
"placeholders",
"graph"
],
"additionalProperties": false
},
"report": {
"type": "array",
"items": {
"type": "object",
"properties": {
"nodeId": { "type": "string" },
"nodeType": { "type": "string" },
"param": { "type": "string" },
"action": { "type": "string", "enum": [ "placeholder", "scrubbed" ] },
"kind": {
"type": "string",
"enum": [
"connection",
"mailbox",
"table",
"resource",
"address",
"secret"
]
}
},
"required": [ "nodeId", "nodeType", "param", "action", "kind" ],
"additionalProperties": false
}
}
},
"required": [ "template", "report" ],
"additionalProperties": false
}400 — The request does not match its schema.
401 — No valid session or API key (auth.unauthenticated).
403 — Refused: insufficient role (auth.forbidden), missing scope (api_key.scope_missing, details.required names it) or a route closed to API keys (api_key.session_required).
429 — The API key exceeded its rate limit (api_key.rate_limited); Retry-After says when to retry.
Error codes — request.bad_request, gallery.source_not_found, gallery.invalid_graph. The common codes (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) apply to every route; see Errors.
POST /api/v1/gallery/submissions
Submit a template to the gallery
Exports (exactly as the preview does) and submits to the gallery, as the creator linked to the caller or, on a cloud instance, through the control plane link. The gallery moderates: nothing is public at submission.
Access — Member session or API key with scope templates:write.
Request body (application/json)
| Field | Type | Required |
|---|---|---|
source | object | yes |
metadata | object | yes |
via | "creator" | "instance" | no |
licenseAccepted | true | yes |
JSON Schema
json
{
"type": "object",
"properties": {
"source": {
"oneOf": [
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "workflow" },
"id": { "type": "string", "minLength": 1 },
"version": { "type": "string", "enum": [ "published", "draft" ] }
},
"required": [ "kind", "id" ]
},
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "orgTemplate" },
"id": { "type": "string", "minLength": 1 }
},
"required": [ "kind", "id" ]
}
]
},
"metadata": {
"type": "object",
"properties": {
"title": {
"type": "object",
"properties": { "en": { "type": "string" }, "fr": { "type": "string" } },
"required": [ "en", "fr" ]
},
"description": {
"type": "object",
"properties": { "en": { "type": "string" }, "fr": { "type": "string" } },
"required": [ "en", "fr" ]
},
"category": {
"type": "string",
"enum": [
"triage",
"replies",
"extraction",
"follow-ups",
"approvals",
"sync",
"notifications",
"other"
]
},
"useCases": {
"default": [],
"maxItems": 6,
"type": "array",
"items": { "type": "string", "minLength": 1, "maxLength": 60 }
}
},
"required": [ "title", "description", "category" ]
},
"via": {
"default": "creator",
"type": "string",
"enum": [ "creator", "instance" ]
},
"licenseAccepted": { "type": "boolean", "const": true }
},
"required": [ "source", "metadata", "licenseAccepted" ]
}Responses
201 — The submission.
| Field | Type | Required |
|---|---|---|
submissionId | string | yes |
status | string | yes |
templateSlug | string | null | yes |
url | string (uri) | null | yes |
JSON Schema
json
{
"type": "object",
"properties": {
"submissionId": { "type": "string" },
"status": { "type": "string" },
"templateSlug": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"url": { "anyOf": [ { "type": "string", "format": "uri" }, { "type": "null" } ] }
},
"required": [ "submissionId", "status", "templateSlug", "url" ],
"additionalProperties": false
}400 — The request does not match its schema.
401 — No valid session or API key (auth.unauthenticated).
403 — Refused: insufficient role (auth.forbidden), missing scope (api_key.scope_missing, details.required names it) or a route closed to API keys (api_key.session_required).
429 — The API key exceeded its rate limit (api_key.rate_limited); Retry-After says when to retry.
This operation accepts an Idempotency-Key header: replaying the same request with the same key returns the original response instead of acting twice. See Idempotency.
Error codes — request.bad_request, gallery.disabled, gallery.not_linked, gallery.source_not_found, gallery.invalid_graph, gallery.invalid_token, gallery.rejected, gallery.unreachable. The common codes (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) apply to every route; see Errors.
GET /api/v1/gallery/templates
Browse the public gallery
The templates published in the public gallery, fetched by the instance (the browser never calls the gallery): full-text search, filters by category, integration and use case, sort by popularity or recency, pagination. Answers are cached for a minute. Without GALLERY_URL, 404 gallery.disabled.
Access — Member session or API key with scope templates:read.
Parameters
| Name | In | Type | Required |
|---|---|---|---|
q | query | string | no |
category | query | "triage" | "replies" | "extraction" | "follow-ups" | "approvals" | "sync" | "notifications" | "other" | no |
integration | query | string | no |
useCase | query | string | no |
sort | query | "popular" | "recent" | no |
page | query | integer | no |
Responses
200 — A page of templates.
| Field | Type | Required |
|---|---|---|
templates | object[] | yes |
page | integer | yes |
total | integer | yes |
pageCount | integer | yes |
JSON Schema
json
{
"type": "object",
"properties": {
"templates": {
"type": "array",
"items": {
"type": "object",
"properties": {
"slug": { "type": "string" },
"title": {
"type": "object",
"properties": { "en": { "type": "string" }, "fr": { "type": "string" } },
"required": [ "en", "fr" ],
"additionalProperties": false
},
"description": {
"type": "object",
"properties": { "en": { "type": "string" }, "fr": { "type": "string" } },
"required": [ "en", "fr" ],
"additionalProperties": false
},
"category": {
"type": "string",
"enum": [
"triage",
"replies",
"extraction",
"follow-ups",
"approvals",
"sync",
"notifications",
"other"
]
},
"useCases": { "type": "array", "items": { "type": "string" } },
"integrations": { "type": "array", "items": { "type": "string" } },
"nodeTypes": { "type": "array", "items": { "type": "string" } },
"importCount": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 },
"publishedAt": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"author": {
"type": "object",
"properties": {
"slug": { "type": "string" },
"name": { "type": "string" },
"official": { "type": "boolean" }
},
"required": [ "slug", "name", "official" ],
"additionalProperties": false
},
"pageUrl": {
"anyOf": [ { "type": "string", "format": "uri" }, { "type": "null" } ]
},
"documentUrl": { "type": "string", "format": "uri" }
},
"required": [
"slug",
"title",
"description",
"category",
"useCases",
"integrations",
"nodeTypes",
"importCount",
"publishedAt",
"author",
"pageUrl",
"documentUrl"
],
"additionalProperties": false
}
},
"page": { "type": "integer", "minimum": 1, "maximum": 9007199254740991 },
"total": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 },
"pageCount": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }
},
"required": [ "templates", "page", "total", "pageCount" ],
"additionalProperties": false
}400 — The request does not match its schema.
401 — No valid session or API key (auth.unauthenticated).
403 — Refused: insufficient role (auth.forbidden), missing scope (api_key.scope_missing, details.required names it) or a route closed to API keys (api_key.session_required).
429 — The API key exceeded its rate limit (api_key.rate_limited); Retry-After says when to retry.
Error codes — request.bad_request, gallery.disabled, gallery.unreachable. The common codes (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) apply to every route; see Errors.
GET /api/v1/gallery/templates/{slug}
A template of the public gallery
Its card, its document (the graph to preview) and what this instance would need to import it: prerequisites to complete, unknown nodes, version compatibility. Nothing is created; POST /api/v1/gallery/import with documentUrl creates the draft.
Access — Member session or API key with scope templates:read.
Parameters
| Name | In | Type | Required |
|---|---|---|---|
slug | path | string | yes |
Responses
200 — The template and its inspection.
| Field | Type | Required |
|---|---|---|
summary | object | yes |
template | object | yes |
inspection | object | yes |
JSON Schema
json
{
"type": "object",
"properties": {
"summary": {
"type": "object",
"properties": {
"slug": { "type": "string" },
"title": {
"type": "object",
"properties": { "en": { "type": "string" }, "fr": { "type": "string" } },
"required": [ "en", "fr" ],
"additionalProperties": false
},
"description": {
"type": "object",
"properties": { "en": { "type": "string" }, "fr": { "type": "string" } },
"required": [ "en", "fr" ],
"additionalProperties": false
},
"category": {
"type": "string",
"enum": [
"triage",
"replies",
"extraction",
"follow-ups",
"approvals",
"sync",
"notifications",
"other"
]
},
"useCases": { "type": "array", "items": { "type": "string" } },
"integrations": { "type": "array", "items": { "type": "string" } },
"nodeTypes": { "type": "array", "items": { "type": "string" } },
"importCount": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 },
"publishedAt": { "anyOf": [ { "type": "string" }, { "type": "null" } ] },
"author": {
"type": "object",
"properties": {
"slug": { "type": "string" },
"name": { "type": "string" },
"official": { "type": "boolean" }
},
"required": [ "slug", "name", "official" ],
"additionalProperties": false
},
"pageUrl": {
"anyOf": [ { "type": "string", "format": "uri" }, { "type": "null" } ]
},
"documentUrl": { "type": "string", "format": "uri" }
},
"required": [
"slug",
"title",
"description",
"category",
"useCases",
"integrations",
"nodeTypes",
"importCount",
"publishedAt",
"author",
"pageUrl",
"documentUrl"
],
"additionalProperties": false
},
"template": {
"type": "object",
"properties": {
"formatVersion": { "type": "number", "const": 1 },
"title": {
"type": "object",
"properties": {
"en": { "type": "string", "maxLength": 60 },
"fr": { "type": "string", "maxLength": 60 }
},
"required": [ "en", "fr" ],
"additionalProperties": false
},
"description": {
"type": "object",
"properties": {
"en": { "type": "string", "maxLength": 4000 },
"fr": { "type": "string", "maxLength": 4000 }
},
"required": [ "en", "fr" ],
"additionalProperties": false
},
"category": {
"type": "string",
"enum": [
"triage",
"replies",
"extraction",
"follow-ups",
"approvals",
"sync",
"notifications",
"other"
]
},
"useCases": {
"default": [],
"maxItems": 6,
"type": "array",
"items": {
"type": "string",
"maxLength": 60,
"pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$"
}
},
"integrations": {
"default": [],
"maxItems": 30,
"type": "array",
"items": {
"type": "string",
"maxLength": 80,
"pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$"
}
},
"nodeTypes": {
"default": [],
"maxItems": 200,
"type": "array",
"items": { "type": "string", "minLength": 1, "maxLength": 128 }
},
"minProductVersion": { "type": "string", "pattern": "^\\d+\\.\\d+\\.\\d+$" },
"placeholders": {
"default": [],
"maxItems": 500,
"type": "array",
"items": {
"type": "object",
"properties": {
"nodeId": { "type": "string", "minLength": 1, "maxLength": 64 },
"nodeType": { "type": "string", "minLength": 1, "maxLength": 128 },
"param": { "type": "string", "minLength": 1, "maxLength": 200 },
"kind": {
"type": "string",
"enum": [
"connection",
"mailbox",
"table",
"resource",
"address",
"secret"
]
},
"credentialType": { "type": "string", "maxLength": 80 },
"capability": { "type": "string", "maxLength": 80 },
"provider": { "type": "string", "maxLength": 80 },
"resource": { "type": "string", "maxLength": 80 }
},
"required": [ "nodeId", "nodeType", "param", "kind" ],
"additionalProperties": false
}
},
"graph": {
"type": "object",
"properties": {
"id": { "type": "string", "const": "template" },
"workflowId": { "type": "string", "const": "template" },
"nodes": {
"minItems": 1,
"maxItems": 200,
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {},
"type": { "type": "string", "minLength": 1, "maxLength": 128 },
"version": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
},
"name": { "type": "string", "minLength": 1, "maxLength": 200 },
"params": {
"default": {},
"type": "object",
"propertyNames": { "type": "string" },
"additionalProperties": {}
},
"onError": {
"default": "fail",
"type": "string",
"enum": [ "fail", "continue", "errorPort" ]
},
"retry": {
"type": "object",
"properties": {
"maxAttempts": { "type": "integer", "minimum": 1, "maximum": 10 },
"delayMs": { "type": "integer", "minimum": 1000, "maximum": 3600000 }
},
"required": [ "maxAttempts" ],
"additionalProperties": false
},
"timeoutMs": { "type": "integer", "minimum": 5000, "maximum": 1800000 },
"position": {
"type": "object",
"properties": { "x": { "type": "number" }, "y": { "type": "number" } },
"required": [ "x", "y" ],
"additionalProperties": false
},
"disabled": { "type": "boolean" },
"notes": { "type": "string", "maxLength": 2000 }
},
"required": [ "id", "type", "version", "name", "params", "onError" ],
"additionalProperties": false
}
},
"connections": {
"type": "array",
"items": {
"type": "object",
"properties": {
"from": {},
"output": { "type": "string" },
"to": {},
"input": { "type": "string" },
"kind": { "type": "string", "enum": [ "data", "service" ] }
},
"required": [ "from", "output", "to" ],
"additionalProperties": false
}
},
"notes": {
"maxItems": 50,
"type": "array",
"items": {
"type": "object",
"properties": {
"id": { "type": "string", "minLength": 1, "maxLength": 64 },
"text": { "default": "", "type": "string", "maxLength": 4000 },
"position": {
"type": "object",
"properties": { "x": { "type": "number" }, "y": { "type": "number" } },
"required": [ "x", "y" ],
"additionalProperties": false
},
"size": {
"default": { "width": 240, "height": 160 },
"type": "object",
"properties": {
"width": { "type": "number", "minimum": 120, "maximum": 2000 },
"height": { "type": "number", "minimum": 80, "maximum": 2000 }
},
"required": [ "width", "height" ],
"additionalProperties": false
},
"color": {
"default": "jaune",
"type": "string",
"enum": [ "jaune", "menthe", "ciel", "rose", "lavande" ]
}
},
"required": [ "id", "text", "position", "size", "color" ],
"additionalProperties": false
}
}
},
"required": [ "id", "workflowId", "nodes", "connections" ],
"additionalProperties": false
}
},
"required": [
"formatVersion",
"title",
"description",
"category",
"useCases",
"integrations",
"nodeTypes",
"minProductVersion",
"placeholders",
"graph"
],
"additionalProperties": false
},
"inspection": {
"type": "object",
"properties": {
"prerequisites": {
"type": "object",
"properties": {
"connections": {
"type": "array",
"items": {
"type": "object",
"properties": {
"nodeId": { "type": "string" },
"nodeType": { "type": "string" },
"param": { "type": "string" },
"kind": {
"type": "string",
"enum": [
"connection",
"mailbox",
"table",
"resource",
"address",
"secret"
]
},
"credentialType": { "type": "string" },
"capability": { "type": "string" },
"provider": { "type": "string" },
"resource": { "type": "string" }
},
"required": [ "nodeId", "nodeType", "param", "kind" ],
"additionalProperties": false
}
},
"mailboxes": {
"type": "array",
"items": {
"type": "object",
"properties": {
"nodeId": { "type": "string" },
"nodeType": { "type": "string" },
"param": { "type": "string" },
"kind": {
"type": "string",
"enum": [
"connection",
"mailbox",
"table",
"resource",
"address",
"secret"
]
},
"credentialType": { "type": "string" },
"capability": { "type": "string" },
"provider": { "type": "string" },
"resource": { "type": "string" }
},
"required": [ "nodeId", "nodeType", "param", "kind" ],
"additionalProperties": false
}
},
"tables": {
"type": "array",
"items": {
"type": "object",
"properties": {
"nodeId": { "type": "string" },
"nodeType": { "type": "string" },
"param": { "type": "string" },
"kind": {
"type": "string",
"enum": [
"connection",
"mailbox",
"table",
"resource",
"address",
"secret"
]
},
"credentialType": { "type": "string" },
"capability": { "type": "string" },
"provider": { "type": "string" },
"resource": { "type": "string" }
},
"required": [ "nodeId", "nodeType", "param", "kind" ],
"additionalProperties": false
}
},
"resources": {
"type": "array",
"items": {
"type": "object",
"properties": {
"nodeId": { "type": "string" },
"nodeType": { "type": "string" },
"param": { "type": "string" },
"kind": {
"type": "string",
"enum": [
"connection",
"mailbox",
"table",
"resource",
"address",
"secret"
]
},
"credentialType": { "type": "string" },
"capability": { "type": "string" },
"provider": { "type": "string" },
"resource": { "type": "string" }
},
"required": [ "nodeId", "nodeType", "param", "kind" ],
"additionalProperties": false
}
},
"addresses": {
"type": "array",
"items": {
"type": "object",
"properties": {
"nodeId": { "type": "string" },
"nodeType": { "type": "string" },
"param": { "type": "string" },
"kind": {
"type": "string",
"enum": [
"connection",
"mailbox",
"table",
"resource",
"address",
"secret"
]
},
"credentialType": { "type": "string" },
"capability": { "type": "string" },
"provider": { "type": "string" },
"resource": { "type": "string" }
},
"required": [ "nodeId", "nodeType", "param", "kind" ],
"additionalProperties": false
}
},
"secrets": {
"type": "array",
"items": {
"type": "object",
"properties": {
"nodeId": { "type": "string" },
"nodeType": { "type": "string" },
"param": { "type": "string" },
"kind": {
"type": "string",
"enum": [
"connection",
"mailbox",
"table",
"resource",
"address",
"secret"
]
},
"credentialType": { "type": "string" },
"capability": { "type": "string" },
"provider": { "type": "string" },
"resource": { "type": "string" }
},
"required": [ "nodeId", "nodeType", "param", "kind" ],
"additionalProperties": false
}
}
},
"required": [
"connections",
"mailboxes",
"tables",
"resources",
"addresses",
"secrets"
],
"additionalProperties": false
},
"unknownNodes": {
"type": "array",
"items": {
"type": "object",
"properties": {
"nodeId": { "type": "string" },
"nodeType": { "type": "string" },
"version": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"reason": { "type": "string", "enum": [ "type", "version" ] }
},
"required": [ "nodeId", "nodeType", "version", "reason" ],
"additionalProperties": false
}
},
"versionCompatible": { "type": "boolean" },
"minProductVersion": { "type": "string" },
"productVersion": { "type": "string" },
"ready": { "type": "boolean" }
},
"required": [
"prerequisites",
"unknownNodes",
"versionCompatible",
"minProductVersion",
"productVersion",
"ready"
],
"additionalProperties": false
}
},
"required": [ "summary", "template", "inspection" ],
"additionalProperties": false
}401 — No valid session or API key (auth.unauthenticated).
403 — Refused: insufficient role (auth.forbidden), missing scope (api_key.scope_missing, details.required names it) or a route closed to API keys (api_key.session_required).
429 — The API key exceeded its rate limit (api_key.rate_limited); Retry-After says when to retry.
Error codes — request.bad_request, gallery.disabled, gallery.template_not_found, gallery.invalid_template, gallery.unreachable. The common codes (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) apply to every route; see Errors.
POST /api/v1/gallery/import/preview
Inspect a template before importing it
From a gallery URL (template= of the import screen) or a pasted document: the prerequisites to complete (connections, mailboxes, tables…), the nodes this instance does not know, the version compatibility. Nothing is created.
Access — Member session or API key with scope templates:read.
Request body (application/json)
Type : object
json
{
"anyOf": [
{
"type": "object",
"properties": { "url": { "type": "string", "format": "uri" } },
"required": [ "url" ]
},
{
"type": "object",
"properties": { "template": {} },
"required": [ "template" ]
}
]
}Responses
200 — The inspection.
| Field | Type | Required |
|---|---|---|
template | object | yes |
inspection | object | yes |
sourceUrl | string (uri) | null | yes |
JSON Schema
json
{
"type": "object",
"properties": {
"template": {
"type": "object",
"properties": {
"formatVersion": { "type": "number", "const": 1 },
"title": {
"type": "object",
"properties": {
"en": { "type": "string", "maxLength": 60 },
"fr": { "type": "string", "maxLength": 60 }
},
"required": [ "en", "fr" ],
"additionalProperties": false
},
"description": {
"type": "object",
"properties": {
"en": { "type": "string", "maxLength": 4000 },
"fr": { "type": "string", "maxLength": 4000 }
},
"required": [ "en", "fr" ],
"additionalProperties": false
},
"category": {
"type": "string",
"enum": [
"triage",
"replies",
"extraction",
"follow-ups",
"approvals",
"sync",
"notifications",
"other"
]
},
"useCases": {
"default": [],
"maxItems": 6,
"type": "array",
"items": {
"type": "string",
"maxLength": 60,
"pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$"
}
},
"integrations": {
"default": [],
"maxItems": 30,
"type": "array",
"items": {
"type": "string",
"maxLength": 80,
"pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$"
}
},
"nodeTypes": {
"default": [],
"maxItems": 200,
"type": "array",
"items": { "type": "string", "minLength": 1, "maxLength": 128 }
},
"minProductVersion": { "type": "string", "pattern": "^\\d+\\.\\d+\\.\\d+$" },
"placeholders": {
"default": [],
"maxItems": 500,
"type": "array",
"items": {
"type": "object",
"properties": {
"nodeId": { "type": "string", "minLength": 1, "maxLength": 64 },
"nodeType": { "type": "string", "minLength": 1, "maxLength": 128 },
"param": { "type": "string", "minLength": 1, "maxLength": 200 },
"kind": {
"type": "string",
"enum": [
"connection",
"mailbox",
"table",
"resource",
"address",
"secret"
]
},
"credentialType": { "type": "string", "maxLength": 80 },
"capability": { "type": "string", "maxLength": 80 },
"provider": { "type": "string", "maxLength": 80 },
"resource": { "type": "string", "maxLength": 80 }
},
"required": [ "nodeId", "nodeType", "param", "kind" ],
"additionalProperties": false
}
},
"graph": {
"type": "object",
"properties": {
"id": { "type": "string", "const": "template" },
"workflowId": { "type": "string", "const": "template" },
"nodes": {
"minItems": 1,
"maxItems": 200,
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {},
"type": { "type": "string", "minLength": 1, "maxLength": 128 },
"version": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
},
"name": { "type": "string", "minLength": 1, "maxLength": 200 },
"params": {
"default": {},
"type": "object",
"propertyNames": { "type": "string" },
"additionalProperties": {}
},
"onError": {
"default": "fail",
"type": "string",
"enum": [ "fail", "continue", "errorPort" ]
},
"retry": {
"type": "object",
"properties": {
"maxAttempts": { "type": "integer", "minimum": 1, "maximum": 10 },
"delayMs": { "type": "integer", "minimum": 1000, "maximum": 3600000 }
},
"required": [ "maxAttempts" ],
"additionalProperties": false
},
"timeoutMs": { "type": "integer", "minimum": 5000, "maximum": 1800000 },
"position": {
"type": "object",
"properties": { "x": { "type": "number" }, "y": { "type": "number" } },
"required": [ "x", "y" ],
"additionalProperties": false
},
"disabled": { "type": "boolean" },
"notes": { "type": "string", "maxLength": 2000 }
},
"required": [ "id", "type", "version", "name", "params", "onError" ],
"additionalProperties": false
}
},
"connections": {
"type": "array",
"items": {
"type": "object",
"properties": {
"from": {},
"output": { "type": "string" },
"to": {},
"input": { "type": "string" },
"kind": { "type": "string", "enum": [ "data", "service" ] }
},
"required": [ "from", "output", "to" ],
"additionalProperties": false
}
},
"notes": {
"maxItems": 50,
"type": "array",
"items": {
"type": "object",
"properties": {
"id": { "type": "string", "minLength": 1, "maxLength": 64 },
"text": { "default": "", "type": "string", "maxLength": 4000 },
"position": {
"type": "object",
"properties": { "x": { "type": "number" }, "y": { "type": "number" } },
"required": [ "x", "y" ],
"additionalProperties": false
},
"size": {
"default": { "width": 240, "height": 160 },
"type": "object",
"properties": {
"width": { "type": "number", "minimum": 120, "maximum": 2000 },
"height": { "type": "number", "minimum": 80, "maximum": 2000 }
},
"required": [ "width", "height" ],
"additionalProperties": false
},
"color": {
"default": "jaune",
"type": "string",
"enum": [ "jaune", "menthe", "ciel", "rose", "lavande" ]
}
},
"required": [ "id", "text", "position", "size", "color" ],
"additionalProperties": false
}
}
},
"required": [ "id", "workflowId", "nodes", "connections" ],
"additionalProperties": false
}
},
"required": [
"formatVersion",
"title",
"description",
"category",
"useCases",
"integrations",
"nodeTypes",
"minProductVersion",
"placeholders",
"graph"
],
"additionalProperties": false
},
"inspection": {
"type": "object",
"properties": {
"prerequisites": {
"type": "object",
"properties": {
"connections": {
"type": "array",
"items": {
"type": "object",
"properties": {
"nodeId": { "type": "string" },
"nodeType": { "type": "string" },
"param": { "type": "string" },
"kind": {
"type": "string",
"enum": [
"connection",
"mailbox",
"table",
"resource",
"address",
"secret"
]
},
"credentialType": { "type": "string" },
"capability": { "type": "string" },
"provider": { "type": "string" },
"resource": { "type": "string" }
},
"required": [ "nodeId", "nodeType", "param", "kind" ],
"additionalProperties": false
}
},
"mailboxes": {
"type": "array",
"items": {
"type": "object",
"properties": {
"nodeId": { "type": "string" },
"nodeType": { "type": "string" },
"param": { "type": "string" },
"kind": {
"type": "string",
"enum": [
"connection",
"mailbox",
"table",
"resource",
"address",
"secret"
]
},
"credentialType": { "type": "string" },
"capability": { "type": "string" },
"provider": { "type": "string" },
"resource": { "type": "string" }
},
"required": [ "nodeId", "nodeType", "param", "kind" ],
"additionalProperties": false
}
},
"tables": {
"type": "array",
"items": {
"type": "object",
"properties": {
"nodeId": { "type": "string" },
"nodeType": { "type": "string" },
"param": { "type": "string" },
"kind": {
"type": "string",
"enum": [
"connection",
"mailbox",
"table",
"resource",
"address",
"secret"
]
},
"credentialType": { "type": "string" },
"capability": { "type": "string" },
"provider": { "type": "string" },
"resource": { "type": "string" }
},
"required": [ "nodeId", "nodeType", "param", "kind" ],
"additionalProperties": false
}
},
"resources": {
"type": "array",
"items": {
"type": "object",
"properties": {
"nodeId": { "type": "string" },
"nodeType": { "type": "string" },
"param": { "type": "string" },
"kind": {
"type": "string",
"enum": [
"connection",
"mailbox",
"table",
"resource",
"address",
"secret"
]
},
"credentialType": { "type": "string" },
"capability": { "type": "string" },
"provider": { "type": "string" },
"resource": { "type": "string" }
},
"required": [ "nodeId", "nodeType", "param", "kind" ],
"additionalProperties": false
}
},
"addresses": {
"type": "array",
"items": {
"type": "object",
"properties": {
"nodeId": { "type": "string" },
"nodeType": { "type": "string" },
"param": { "type": "string" },
"kind": {
"type": "string",
"enum": [
"connection",
"mailbox",
"table",
"resource",
"address",
"secret"
]
},
"credentialType": { "type": "string" },
"capability": { "type": "string" },
"provider": { "type": "string" },
"resource": { "type": "string" }
},
"required": [ "nodeId", "nodeType", "param", "kind" ],
"additionalProperties": false
}
},
"secrets": {
"type": "array",
"items": {
"type": "object",
"properties": {
"nodeId": { "type": "string" },
"nodeType": { "type": "string" },
"param": { "type": "string" },
"kind": {
"type": "string",
"enum": [
"connection",
"mailbox",
"table",
"resource",
"address",
"secret"
]
},
"credentialType": { "type": "string" },
"capability": { "type": "string" },
"provider": { "type": "string" },
"resource": { "type": "string" }
},
"required": [ "nodeId", "nodeType", "param", "kind" ],
"additionalProperties": false
}
}
},
"required": [
"connections",
"mailboxes",
"tables",
"resources",
"addresses",
"secrets"
],
"additionalProperties": false
},
"unknownNodes": {
"type": "array",
"items": {
"type": "object",
"properties": {
"nodeId": { "type": "string" },
"nodeType": { "type": "string" },
"version": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"reason": { "type": "string", "enum": [ "type", "version" ] }
},
"required": [ "nodeId", "nodeType", "version", "reason" ],
"additionalProperties": false
}
},
"versionCompatible": { "type": "boolean" },
"minProductVersion": { "type": "string" },
"productVersion": { "type": "string" },
"ready": { "type": "boolean" }
},
"required": [
"prerequisites",
"unknownNodes",
"versionCompatible",
"minProductVersion",
"productVersion",
"ready"
],
"additionalProperties": false
},
"sourceUrl": { "anyOf": [ { "type": "string", "format": "uri" }, { "type": "null" } ] }
},
"required": [ "template", "inspection", "sourceUrl" ],
"additionalProperties": false
}400 — The request does not match its schema.
401 — No valid session or API key (auth.unauthenticated).
403 — Refused: insufficient role (auth.forbidden), missing scope (api_key.scope_missing, details.required names it) or a route closed to API keys (api_key.session_required).
429 — The API key exceeded its rate limit (api_key.rate_limited); Retry-After says when to retry.
Error codes — request.bad_request, gallery.disabled, gallery.untrusted_url, gallery.template_not_found, gallery.invalid_template, gallery.unreachable. The common codes (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) apply to every route; see Errors.
POST /api/v1/gallery/import
Import a template as a new draft
Creates a draft workflow owned by the member from the template; placeholders stay empty for the editor to flag. A template using nodes unknown to this instance is refused (409 gallery.not_importable). Each import from a gallery URL is counted once per instance.
Access — Member session or API key with scope workflows:write.
Request body (application/json)
Type : object
json
{
"anyOf": [
{
"type": "object",
"properties": {
"url": { "type": "string", "format": "uri" },
"name": { "type": "string", "minLength": 1, "maxLength": 200 }
},
"required": [ "url" ]
},
{
"type": "object",
"properties": {
"template": {},
"name": { "type": "string", "minLength": 1, "maxLength": 200 }
},
"required": [ "template" ]
}
]
}Responses
201 — The id of the new workflow.
| Field | Type | Required |
|---|---|---|
workflowId | string | yes |
JSON Schema
json
{
"type": "object",
"properties": { "workflowId": { "type": "string" } },
"required": [ "workflowId" ],
"additionalProperties": false
}400 — The request does not match its schema.
401 — No valid session or API key (auth.unauthenticated).
403 — Refused: insufficient role (auth.forbidden), missing scope (api_key.scope_missing, details.required names it) or a route closed to API keys (api_key.session_required).
429 — The API key exceeded its rate limit (api_key.rate_limited); Retry-After says when to retry.
This operation accepts an Idempotency-Key header: replaying the same request with the same key returns the original response instead of acting twice. See Idempotency.
Error codes — request.bad_request, gallery.disabled, gallery.untrusted_url, gallery.template_not_found, gallery.invalid_template, gallery.not_importable, gallery.unreachable. The common codes (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) apply to every route; see Errors.