Publish a workflow version
Publish a workflow version.
Publish a saved definition from its draft or an ad hoc run as a reusable version for named runs or triggers, validating the definition and locking dependencies. To test unpublished code, use praxis.automation.runs.create with source and language instead. Use draft.revision from create or retrieve as expected_draft_revision. The draft must match expected_draft_revision; an ad hoc run requires from_run and expected_source_sha256. The same version and contents return the existing version; different contents return VERSION_EXISTS, prereleases require an explicit tag (not latest, URL-safe characters only, not a version or range; violations return TAG_REQUIRED or TAG_INVALID with the complete rules in hint), and invalid definitions return DEFINITION_INVALID. Stable releases automatically advance latest only above the highest existing stable version; workflows becoming latest synchronize their declared schedule. String and object run.workflow/run.script references share version resolution and dependency locking. Publishing removes +build metadata from the version number.
POST /automation/v1/workflows/{ns}/{name}/versions
Authentication
Authorization: Bearer $PRAXIS_API_KEY
Request fields
| Parameter | Type | Description |
|---|---|---|
| path: ns | string | required; Namespace, folded to lowercase; matches [a-z0-9][a-z0-9._-]{0,63}. praxis is read-only. |
| path: name | string | required; Name, folded to lowercase; matches [a-z0-9][a-z0-9._-]{0,63}. |
| header: Idempotency-Key | string | optional; Optional; 1–256 characters. Within 24 hours, the same key replays the first response with Idempotent-Replayed: true; a different request body returns 422; an in-flight request returns 409. minLength: 1; maxLength: 256 |
application/json
| Field | Type | Description |
|---|---|---|
| (variant 1).version | string | required; An exact canonical semantic version, such as 1.2.0 or 1.3.0-beta.1, not a range. |
| (variant 1).expected_draft_revision | string | required; Draft revision to publish, matching the current draft; alternative to publishing from_run. |
| (variant 1).tag | string | optional; Distribution tag. A prerelease (such as 1.3.0-beta.1) requires a tag and it cannot be latest; a tag may only use URL-safe characters (letters, digits and - _ . ! ~ * ' ( )), no spaces or / ? # and no leading or trailing whitespace; it cannot be a version or a version range (such as 1.2.3, ^1, 1.x, *); any other name such as beta, next or debug is allowed. Violations return TAG_INVALID or TAG_REQUIRED with the complete rules in hint. |
| (variant 2).version | string | required; An exact canonical semantic version, such as 1.2.0 or 1.3.0-beta.1, not a range. |
| (variant 2).from_run | string | required; Ad hoc run ID providing the source snapshot; published-target runs currently have no snapshot usable by this endpoint. Requires expected_source_sha256 and excludes expected_draft_revision. |
| (variant 2).expected_source_sha256 | string | required; SHA-256 digest of the run source, matching the snapshot. |
| (variant 2).tag | string | optional; Distribution tag. A prerelease (such as 1.3.0-beta.1) requires a tag and it cannot be latest; a tag may only use URL-safe characters (letters, digits and - _ . ! ~ * ' ( )), no spaces or / ? # and no leading or trailing whitespace; it cannot be a version or a version range (such as 1.2.3, ^1, 1.x, *); any other name such as beta, next or debug is allowed. Violations return TAG_INVALID or TAG_REQUIRED with the complete rules in hint. |
Examples
Set these environment variables to your own resources:
| Variable | Source |
|---|---|
| WORKFLOW_NAME | name returned by creating a workflow |
| DRAFT_REVISION | Current draft.revision |
: "${WORKFLOW_NAME:?Set WORKFLOW_NAME}"
: "${DRAFT_REVISION:?Set DRAFT_REVISION}"
BODY=$(jq -n --arg DRAFT_REVISION "$DRAFT_REVISION" '{
"version": "1.0.0",
"expected_draft_revision": $DRAFT_REVISION
}')
curl --fail-with-body -X POST "https://api.deepraxis.ai/automation/v1/workflows/docs-samples/${WORKFLOW_NAME}/versions" \
-H "Authorization: Bearer $PRAXIS_API_KEY" \
-H "Content-Type: application/json" \
--data "$BODY"import { createAutomationClient } from '@deepraxis/sdk/automation';
function env(name: string): string {
const value = process.env[name];
if (!value) throw new Error(`Set ${name}`);
return value;
}
const automation = createAutomationClient({
apiKey: env('PRAXIS_API_KEY'),
baseUrl: 'https://api.deepraxis.ai',
maxRetries: 0,
timeoutMs: 90_000,
});
const result = await automation.workflows.versions.publish({
"path": {
"ns": "docs-samples",
"name": env("WORKFLOW_NAME")
},
"body": {
"version": "1.0.0",
"expected_draft_revision": env("DRAFT_REVISION")
}
});
console.log(result);Response
HTTP 200
Success
| Header | Type | Description |
|---|---|---|
| Idempotent-Replayed | boolean | Present and true when replaying the first response for this key. |
application/json
| Field | Type | Description |
|---|---|---|
| id | string | required; Version id, prefixed scv_ for scripts and wfv_ for workflows. |
| kind | "script" / "workflow" | required; Orchestration kind. script is a TypeScript script that executes once; workflow is a YAML workflow made of steps that can wait for events, timers or child runs and can be suspended. |
| version | string | required; Version number (semver, with +build metadata removed). |
| digest | string | required; Content digest of the source and contract. |
| source | string | required; Full source of this version. Version lists omit it unless expand=source is given. |
| input_schema | object | required; Any JSON object whose keys are strings and whose values are any JSON value. |
| input_schema.* (variant 5) | object | Recursive JSON value. |
| input_schema.* (variant 6)[] | null / string / number / boolean / object / JSON[] | Recursive JSON value. |
| output_schema | object | required; Inferred from script return types, including Promise unwrapping, Record, intersections and Date (date-time); unresolved types yield an empty schema with a warning in /validate warnings. |
| output_schema.* (variant 5) | object | Recursive JSON value. |
| output_schema.* (variant 6)[] | null / string / number / boolean / object / JSON[] | Recursive JSON value. |
| references | object[] | required; Actions, platform APIs, scripts and workflows this version depends on. Script and workflow dependencies are locked to exact versions at publication. |
| references[].kind | "action" / "script" / "workflow" / "platform_api" / "run" | required; Dependency kind. action is an action; platform_api is a platform API operation; script is a script; workflow is a workflow; run is the child-run target of an invoke("ns/name") call in a script (a script or workflow, resolved at publication). |
| references[].name | string | required; Referenced item: ns/name for an action, the operation name for a platform API, ns/name for a script or workflow. |
| references[].range | string | optional; Version range or tag as written in the reference (npm rules); absent when none was written. |
| references[].locked_version | string | optional; Exact version locked at publication; only script and workflow dependencies have it, actions and platform APIs are not locked. |
| outline | null / object[] | required; Step outline of a workflow as OutlineNode entries generated statically by the parser; null for scripts. |
| outline (variant 2)[].name | string | required; Step name, the key of the step in the workflow YAML. |
| outline (variant 2)[].reference | string | required; JSON Pointer of the step in the workflow document, for example /do/0/start; equals Task.reference at run time. |
| outline (variant 2)[].kind | "run" / "call" / "wait" / "set" / "for" / "fork" / "try" / "switch" / "emit" / "raise" / "listen" / "do" | required; Workflow step kind. call invokes an action; run starts a child script or workflow; wait pauses for a duration; set assigns variables; for loops; fork runs parallel branches; try is a block with catch; switch branches on conditions; emit publishes an event; raise throws an error; listen waits for an event; do is a block of sequential steps. |
| outline (variant 2)[].target | string | optional; Target of the step: the action ns/name for a call step, ns/name@range for a run step; absent for other kinds. |
| outline (variant 2)[].wait | object | optional; Summary of a waiting step: the duration (seconds or duration) or the event type being awaited (event). no additional fields. |
| outline (variant 2)[].wait.until | string | optional; Absolute instant at which the wait ends, given only when it is statically known; the outline does not populate it today. |
| outline (variant 2)[].wait.seconds | number | optional; Wait in seconds when statically convertible, including duration objects and convertible ISO durations. |
| outline (variant 2)[].wait.event | string | optional; Event type a listen step waits for. |
| outline (variant 2)[].wait.duration | string | optional; Original duration or runtime expression that cannot be statically converted to seconds. |
| outline (variant 2)[].loop | object | optional; Loop information {each, in} of a for step. no additional fields. |
| outline (variant 2)[].loop.each | string | required; Loop variable name; item when not specified. |
| outline (variant 2)[].loop.in | string | required; Verbatim expression of the collection being iterated. |
| outline (variant 2)[].children | object[] | optional; Nested child steps (inside do, fork branches, try and catch). |
| outline (variant 2)[].children[] | object | Recursive JSON value. |
| sdk_version | null / string | required; SDK version used when publishing a script; null for workflows. |
| published_at | string | required; Publication time (RFC 3339 UTC). |
| published_by | object | required; Principal {type, id} injected by the gateway that says who initiated or acted. This service does not resolve names; the console resolves them in batches. no additional fields. |
| published_by.type | "user" / "api_key" / "agent" / "run" / "trigger" | required; Principal type. user is a signed-in user; api_key is a platform API key; agent is an agent; run is an action performed by a run itself (for example a parent run); trigger is a trigger. |
| published_by.id | string | required; Principal identifier whose meaning follows type: a user, API key, agent, run or trigger id. Treat it as an opaque string. |
| deprecated | null / string | required; Deprecation message, or null when not deprecated. A deprecated version still runs, but resolving a range or tag prefers versions that are not deprecated. |
| deprecated_at | null / string | required; Time the version was deprecated (RFC 3339 UTC), or null. |
| deprecated_by | null / object | required; Principal that deprecated the version, or null. |
| deprecated_by (variant 2).type | "user" / "api_key" / "agent" / "run" / "trigger" | required; Principal type. user is a signed-in user; api_key is a platform API key; agent is an agent; run is an action performed by a run itself (for example a parent run); trigger is a trigger. |
| deprecated_by (variant 2).id | string | required; Principal identifier whose meaning follows type: a user, API key, agent, run or trigger id. Treat it as an opaque string. |
Measured response
HTTP 200
{
"id": "wfv_00mv67m6x5409408c354944fa8a960d207eb33c297",
"kind": "workflow",
"version": "1.0.0",
"digest": "ea7352d51087eca0113ee82230848ce1506fd97d27aad4c7b1911e5c4ef9b5fb",
"input_schema": {},
"output_schema": {},
"references": [],
"outline": [
{
"name": "answer",
"reference": "/do/0/answer",
"kind": "set"
}
],
"sdk_version": null,
"published_at": "2026-10-13T04:57:32.297Z",
"published_by": {
"type": "api_key",
"id": "key_3e00b8984967"
},
"deprecated": null,
"deprecated_at": null,
"deprecated_by": null,
"source": "document:\n dsl: '1.0.3'\n namespace: docs-samples\n name: sample-workflows-1791867412840-b05e8a\n version: '1.0.0'\ndo:\n - answer:\n set:\n answer: 42\n"
}Errors
| HTTP | Codes and description |
|---|---|
| 400 | INVALID_PARAMS: Invalid request parameters, path, cursor, or body format. TAG_REQUIRED: A prerelease version requires an explicit publication tag (for example beta, not latest); the response hint lists the complete rules. TAG_INVALID: The tag is invalid: a prerelease cannot use latest; a tag may only use URL-safe characters (no spaces or / ? #); it cannot be a version or range; latest cannot be deleted. The response hint lists the complete rules. DEFINITION_INVALID: The source failed definition validation. INPUT_INVALID: The input does not satisfy the target contract or validation rules. SCHEDULE_INVALID: The schedule or time boundaries are invalid. TIMEZONE_INVALID: The timezone is not a valid IANA timezone. INTERVAL_TOO_SHORT: The schedule interval is shorter than one minute. |
| 403 | NAMESPACE_FORBIDDEN: The namespace is read-only, or the run token does not permit this call. |
| 404 | TARGET_NOT_FOUND: The target does not exist or has an incompatible type. RUN_NOT_FOUND: The run does not exist or is not visible to this tenant. |
| 409 | IDEMPOTENCY_IN_FLIGHT: A request with the same idempotency key is still in progress. TARGET_ARCHIVED: The target is archived and cannot be used for this operation; action execution error detail includes ns/name. VERSION_EXISTS: The version already exists with different source content. |
| 412 | PRECONDITION_FAILED: The revision, source digest, or concurrent write precondition does not match. |
| 422 | IDEMPOTENCY_KEY_MISMATCH: The idempotency key was already used for different request content. DEFINITION_IDENTITY_MISMATCH: The source identity or runtime language does not match the publication target. NO_MATCHING_VERSION: No published version matches the requested tag, version, or range. CYCLE_DETECTED: Publication would create a dependency cycle (A depends on B and B depends on A); the detail names the cycle path. |
| 429 | TRIGGER_LIMIT: The tenant has reached the limit of 100 enabled triggers. |
| default | RFC 9457 automation problem. 429 includes Retry-After. |
Authentication and common errors · Retain the X-Request-Id response header for troubleshooting.