Create Template Api V1 Workstreams Templates Post
post
/api/v1/workstreams/templatesCreate workflow template
Create a new workflow template.
Templates define reusable workflow steps that can be instantiated
as client-specific blueprints.
**Authentication Required:** JWT Bearer token
Request bodyapplication/json
| Field | Type | Description |
|---|---|---|
namerequired | string | Template name |
description | string | null | Template description |
category | "compliance" | "advisory" | "audit" | "bookkeeping" | "tax" | "internal" | null | Template category (closed taxonomy; off-taxonomy input is mapped) |
steps | TaskStepDefinition | ToolCallStepDefinition | ArchieQueryStepDefinition | NotifyStepDefinition | ConditionalStepDefinition | LoopStepDefinition | ParallelStepDefinition | ApprovalStepDefinition | DocumentUploadStepDefinition | StageStepDefinition | GotoStepDefinition | SubWorkStreamStepDefinition | DeterministicExtractionStepDefinition | VerificationStepDefinition | EmailSendStepDefinition | WaitForReplyStepDefinition | SkillStepDefinition | AgentRunStepDefinition[] | WDL step definitions |
default_config | object | Default configurationshow nestedEmpty object. |
tags | string[] | Template tags |
input_schema | object[] | Declared workstream inputs (array of InputDef: name/type/required/...).item shapeEmpty object. |
output_schema | object[] | Declared workstream outputs (array of OutputDef: name/label/type/format/...).item shapeEmpty object. |
Responses
201Template created successfully
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | Template UUID |
slug | string | null | Human-readable URL key (e.g. 'asc-606-review'). Stable + globally unique; resolvable by GET /templates/{id}. Link the FE here, not the UUID. |
permakey | string | null | Stable opaque short id (7-char); the cross-entity permalink, also resolvable. |
namerequired | string | Template name |
description | string | null | Template description |
category | "compliance" | "advisory" | "audit" | "bookkeeping" | "tax" | "internal" | null | Template category (closed taxonomy: compliance/advisory/audit/bookkeeping/tax/internal). NULL = genuinely uncategorised (no category set); 'internal' = an off-taxonomy value mapped to the catch-all bucket — the two are distinct (NULL is NOT coerced to 'internal'). |
steps | object[] | WDL step definitionsitem shapeEmpty object. |
default_config | object | Default configurationshow nestedEmpty object. |
tags | string[] | Template tags |
input_schema | object[] | Declared workstream inputs (array of InputDef: name/type/required/...).item shapeEmpty object. |
output_schema | object[] | Declared workstream outputs for the Outputs tab (array of OutputDef: name/label/type/format/...). Empty ⇒ no Outputs tab.item shapeEmpty object. |
forked_from | object | null | Provenance: parent recipe {name, version} this was forked from. NULL when not a fork. |
upstream_update | object | null | {version, note} when the fork's parent has advanced past the fork point. NULL when none/uncomputable. |
is_template | boolean | Always true for templates |
domain | string | null | DomainAgent knowledge-key backing this recipe (e.g. 'ita_2007_eis'), resolved from the linked job_definition.domain via its most-recent cycle and surfaced ONLY when it maps to a real DomainAgent persona. NULL for fixed-step recipes and generic agentic containers (the 'workstream'/'general' placeholder domains) — which are NOT WorkPlan-able. The WorkPlan-create picker filters to `domain != null`. |
statusrequired | "draft" | "active" | "paused" | "archived" | Status for workstream entities.draftactivepausedarchived |
version | integer | Template version, incremented on each update |
active_blueprint_count | integer | Number of active linked workplans for this template |
total_runs | integer | Count of cycles ever launched from this template (run count). |
total_instances | integer | Aggregate instance count across all cycles. Each backend cycle is one instance run, so this equals total_runs today; kept distinct so the FE contract is stable if job-level fan-out grouping lands later. |
last_run_at | string (date-time) | null | Start (or creation) timestamp of the most recent cycle. NULL if never run. |
last_run_state | "created" | "planning" | "queued" | "running" | "paused" | "blocked" | "completed" | "failed" | "cancelled" | "skipped" | null | Status of the most recent cycle, for the 'last run' badge. NULL if never run. |
avg_instance_cost | number | Average customer-facing cost (GBP) across runs: mean of £19/hr x elapsed per cycle. Mirrors CycleResponse.customer_cost_gbp. |
cycle_ids | string (uuid)[] | Cycle ids that have run this template, most recent first (capped). |
created_byrequired | string (uuid) | Creator user ID |
created_by_name | string | null | Creator display name |
created_atrequired | string (date-time) | Creation timestamp |
updated_atrequired | string (date-time) | Last update timestamp |
scope | string | Distribution scope: gallery|firm|team|user|plan (provenance pill). |
is_catalog | boolean | True for curated public library recipes (the seeded catalog). |
owning_team_id | string (uuid) | null | The team a `scope='team'` workstream belongs to — lets the FE group the My WorkStreams list under the team name (#170). NULL for firm/user-scoped rows. |
400Invalid request data
401Unauthorized
422Validation Error
| Field | Type | Description |
|---|---|---|
detail | ValidationError[] | —item shape |
curl https://api.dev.arch.ie/api/v1/workstreams/templates \
-X POST \
-H "Authorization: Bearer sk_..." \
-H "Content-Type: application/json" \
-d '{
"category": "reconciliation",
"description": "Automated month-end close process",
"name": "Monthly Close Reconciliation",
"steps": [
{
"agent": "data_extraction",
"id": "fetch-data",
"impact_level": "low",
"instruction": "Fetch trial balance for period {{ context.parameters.period }}",
"name": "Fetch Trial Balance",
"run_mode": "auto_run",
"type": "task"
},
{
"agent": "validation",
"depends_on": [
"fetch-data"
],
"id": "validate-data",
"impact_level": "low",
"instruction": "Validate the fetched data for completeness",
"name": "Validate Balances",
"run_mode": "auto_run",
"type": "task"
},
{
"actions": {
"approve": {
"label": "Approve",
"next": "complete"
},
"reject": {
"label": "Reject",
"require_reason": true
}
},
"depends_on": [
"validate-data"
],
"id": "approval-gate",
"impact_level": "high",
"name": "Review & Approve",
"summary": {
"description": "Review data before proceeding",
"title": "Month-End Close Review"
},
"type": "approval"
}
],
"tags": [
"month-end",
"reconciliation"
]
}'