Manage SaaS package release lifecycle, desktop distribution, container deployments, feature flags, campaigns, automation rules, time triggers, workflows, and change management.
GET /v1/automation-rules
List automation rules
Returns automation rules for the authenticated organization. Supports optional filters: `is_enabled` (`true`/`false`), `trigger_type`, `action_type`, `page`, `page_size` (max 200).
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
is_enabled | query | string (enum) | no | Filter by enabled state. |
trigger_type | query | string | no | Filter by trigger type string. |
action_type | query | string | no | Filter by action type string. |
page | query | integer | no | Page number (1-based). |
page_size | query | integer | no | Results per page (max 200). |
Responses
| Status | Description |
200 | Automation rule list. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
200 response body: data fields
| Field | Type | Description |
rules | array of object | |
total_count | integer | |
page | integer | |
page_size | integer | |
POST /v1/automation-rules
Create an automation rule
Creates an automation rule. For `webhook` action types `action_config.url` must use HTTPS and `action_config.method` must be present. For `run_ai_session` action types `action_config.prompt` must be a non-empty string. For `cron` trigger types `trigger_config.expression` must be a valid 5-field cron expression.
Auth Session JWT (Bearer)
Request Body
| Field | Type | Required | Description |
name | string | yes | |
description | string | no | |
trigger_type | string | yes | |
trigger_config | object | yes | |
action_type | string | yes | |
action_config | object | yes | |
is_enabled | boolean | no | |
Responses
| Status | Description |
201 | Automation rule created. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
409 | `CONFLICT` — a rule with the same name already exists. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
201 response body: data fields
| Field | Type | Description |
id | string<uuid> | |
org_id | string<uuid> | |
name | string | |
description | string | null | |
trigger_type | string | |
trigger_config | object | |
action_type | string | |
action_config | object | |
is_enabled | boolean | |
created_at | string<date-time> | |
GET /v1/automation-rules/{ruleId}
Get an automation rule
Returns a single automation rule by ID.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
ruleId | path | string<uuid> | yes | Automation rule identifier (UUIDv7). |
Responses
| Status | Description |
200 | Automation rule record. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
200 response body: data fields
| Field | Type | Description |
id | string<uuid> | |
org_id | string<uuid> | |
name | string | |
description | string | null | |
trigger_type | string | |
trigger_config | object | |
action_type | string | |
action_config | object | |
is_enabled | boolean | |
created_at | string<date-time> | |
PUT /v1/automation-rules/{ruleId}
Update an automation rule
Updates an automation rule. All fields are optional; same validation rules as create apply to `action_config` and `trigger_config`.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
ruleId | path | string<uuid> | yes | Automation rule identifier (UUIDv7). |
Request Body
| Field | Type | Required | Description |
name | string | no | |
description | string | no | |
trigger_type | string | no | |
trigger_config | object | no | |
action_type | string | no | |
action_config | object | no | |
is_enabled | boolean | no | |
Responses
| Status | Description |
200 | Automation rule updated. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
409 | `CONFLICT` — another rule with the same name already exists. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
200 response body: data fields
| Field | Type | Description |
id | string<uuid> | |
org_id | string<uuid> | |
name | string | |
description | string | null | |
trigger_type | string | |
trigger_config | object | |
action_type | string | |
action_config | object | |
is_enabled | boolean | |
created_at | string<date-time> | |
DELETE /v1/automation-rules/{ruleId}
Delete an automation rule
Permanently deletes an automation rule.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
ruleId | path | string<uuid> | yes | Automation rule identifier (UUIDv7). |
Responses
| Status | Description |
200 | Automation rule deleted. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
POST /v1/automation-rules/{ruleId}/execute
Manually execute an automation rule
Enqueues an immediate execution of the rule. The rule must belong to the caller's organization (cross-tenant IDOR prevention is enforced). Requires the `automation.manage` permission.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
ruleId | path | string<uuid> | yes | Automation rule identifier (UUIDv7). |
Responses
| Status | Description |
200 | Rule execution enqueued. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | `FORBIDDEN` — caller lacks the `automation.manage` permission, or the rule does not belong to the caller's organization. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
GET /v1/automation-rules/{ruleId}/executions
List executions for an automation rule
Returns execution history for the specified automation rule. Supports optional `status` filter and `page`/`page_size` pagination.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
ruleId | path | string<uuid> | yes | Automation rule identifier (UUIDv7). |
status | query | string | no | Filter by execution status (up to 50 characters). |
page | query | integer | no | Page number (1-based, max 100,000). |
page_size | query | integer | no | Results per page (1–200). |
Responses
| Status | Description |
200 | Rule execution history. |
400 | `INVALID_ID_FORMAT` — `ruleId` is not a valid UUID; or `VALIDATION_ERROR` — query params are invalid. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
GET /v1/campaigns
List campaigns
Returns all campaigns for the authenticated organization. Supports optional `status` and `type` query filters.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
status | query | string (enum) | no | Filter by campaign status: `active` or `paused`. |
type | query | string (enum) | no | Filter by campaign type. |
limit | query | integer | no | Maximum number of records to return. Default and ceiling are endpoint-specific (commonly default 25–50, max 100). |
offset | query | integer | no | Number of records to skip for offset pagination. |
Responses
| Status | Description |
200 | Campaign list. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
200 response body: data fields
| Field | Type | Description |
campaigns | array of object | |
total_count | integer | |
POST /v1/campaigns
Create a campaign
Creates a new campaign for the authenticated organization.
Auth Session JWT (Bearer)
Request Body
| Field | Type | Required | Description |
name | string | yes | |
description | string | no | |
campaign_type | string (enum) dripsequenceone_shot | yes | |
trigger | object | no | Trigger configuration JSON. |
is_active | boolean | no | Whether the campaign is active. Defaults to `false`. |
starts_at | string<date-time> | no | |
ends_at | string<date-time> | no | |
metadata | object | no | |
Responses
| Status | Description |
201 | Campaign created. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
201 response body: data fields
| Field | Type | Description |
id | string<uuid> | |
org_id | string<uuid> | |
name | string | |
description | string | null | |
campaign_type | string (enum) dripsequenceone_shot | |
status | string (enum) activepaused | |
starts_at | string | null | |
ends_at | string | null | |
created_at | string<date-time> | |
GET /v1/campaigns/{id}
Get a campaign
Returns a campaign by ID.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
id | path | string<uuid> | yes | Campaign identifier (UUIDv7). |
Responses
| Status | Description |
200 | Campaign record. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
200 response body: data fields
| Field | Type | Description |
id | string<uuid> | |
org_id | string<uuid> | |
name | string | |
description | string | null | |
campaign_type | string (enum) dripsequenceone_shot | |
status | string (enum) activepaused | |
starts_at | string | null | |
ends_at | string | null | |
created_at | string<date-time> | |
PUT /v1/campaigns/{id}
Update a campaign
Updates campaign metadata. All fields are optional.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
id | path | string<uuid> | yes | Campaign identifier (UUIDv7). |
Request Body
| Field | Type | Required | Description |
name | string | no | |
description | string | no | |
campaign_type | string (enum) dripsequenceone_shot | no | |
trigger | object | no | |
is_active | boolean | no | |
starts_at | string<date-time> | no | |
ends_at | string<date-time> | no | |
metadata | object | no | |
Responses
| Status | Description |
200 | Campaign updated. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
200 response body: data fields
| Field | Type | Description |
id | string<uuid> | |
org_id | string<uuid> | |
name | string | |
description | string | null | |
campaign_type | string (enum) dripsequenceone_shot | |
status | string (enum) activepaused | |
starts_at | string | null | |
ends_at | string | null | |
created_at | string<date-time> | |
DELETE /v1/campaigns/{id}
Delete a campaign
Permanently deletes a campaign.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
id | path | string<uuid> | yes | Campaign identifier (UUIDv7). |
Responses
| Status | Description |
200 | Campaign deleted. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
GET /v1/campaigns/{id}/enrollments
List enrollments for a campaign
Returns enrollments for the specified campaign, optionally filtered by `status`. Supports pagination via `limit`/`offset`.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
id | path | string<uuid> | yes | Campaign identifier (UUIDv7). |
status | query | string (enum) | no | Filter by enrollment status. |
limit | query | integer | no | Max records to return (1–100, default 25). |
offset | query | integer | no | Zero-based offset for pagination. |
Responses
| Status | Description |
200 | Enrollment list. |
400 | `INVALID_ID_FORMAT` — `id` is not a valid UUID; or `VALIDATION_ERROR` — query params are invalid. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
200 response body: data fields
| Field | Type | Description |
enrollments | array of object | |
total_count | integer | |
POST /v1/campaigns/{id}/enrollments
Enroll a user in a campaign
Enrolls a target user in the campaign. Requires the `campaign.enroll` permission.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
id | path | string<uuid> | yes | Campaign identifier (UUIDv7). |
Request Body
| Field | Type | Required | Description |
campaign_id | string<uuid> | yes | |
target_user_id | string<uuid> | yes | User to enroll. |
trigger_data | object | no | |
metadata | object | no | |
Responses
| Status | Description |
201 | User enrolled in campaign. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | `FORBIDDEN` — caller lacks the `campaign.enroll` permission. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
GET /v1/campaigns/{id}/steps
List steps for a campaign
Returns all steps for the specified campaign, ordered by `step_number`.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
id | path | string<uuid> | yes | Campaign identifier (UUIDv7). |
Responses
| Status | Description |
200 | Campaign step list. |
400 | `INVALID_ID_FORMAT` — `id` is not a valid UUID. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
200 response body: data fields
| Field | Type | Description |
steps | array of object | |
total_count | integer | |
POST /v1/campaigns/{id}/steps
Add a step to a campaign
Adds a step (email, notification, delay, condition, or action) to an existing campaign at the specified position (0-based, converted to 1-based `step_number` internally).
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
id | path | string<uuid> | yes | Campaign identifier (UUIDv7). |
Request Body
| Field | Type | Required | Description |
campaign_id | string<uuid> | yes | |
name | string | yes | |
step_type | string (enum) emailnotificationdelayconditionaction | yes | |
position | integer | yes | 0-based position. Converted to 1-based `step_number` internally. |
config | object | no | |
delay_seconds | integer | no | |
template_id | string<uuid> | no | |
metadata | object | no | |
Responses
| Status | Description |
201 | Campaign step created. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
201 response body: data fields
| Field | Type | Description |
id | string<uuid> | |
campaign_id | string<uuid> | |
name | string | |
step_type | string (enum) emailnotificationdelayconditionaction | |
position | integer | 0-based display order. |
config | object | |
delay_seconds | integer | |
template_id | string | null | |
PUT /v1/campaigns/{id}/steps/{stepId}
Update a campaign step
Updates one or more fields of an existing campaign step. At least one field must be provided.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
id | path | string<uuid> | yes | Campaign identifier (UUIDv7). |
stepId | path | string<uuid> | yes | Step identifier (UUIDv7). |
Request Body
| Field | Type | Required | Description |
name | string | no | Step display name. |
position | integer | no | 0-based position in the step sequence (converted to 1-based `step_number` internally). |
config | object | no | Action configuration for the step. |
delay_seconds | integer | no | Delay before the step executes, in seconds (converted to `delay_minutes` internally). |
template_id | string<uuid> | no | Optional linked template identifier. |
metadata | object | no | Arbitrary metadata / conditions object. |
Responses
| Status | Description |
200 | Campaign step updated. |
400 | `INVALID_ID_FORMAT` — `id` or `stepId` is not a valid UUID; or `VALIDATION_ERROR` — body is invalid. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
200 response body: data fields
| Field | Type | Description |
id | string<uuid> | |
campaign_id | string<uuid> | |
name | string | |
step_type | string (enum) emailnotificationdelayconditionaction | |
position | integer | 0-based display order. |
config | object | |
delay_seconds | integer | |
template_id | string | null | |
DELETE /v1/campaigns/{id}/steps/{stepId}
Delete a campaign step
Permanently removes a step from the campaign.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
id | path | string<uuid> | yes | Campaign identifier (UUIDv7). |
stepId | path | string<uuid> | yes | Step identifier (UUIDv7). |
Responses
| Status | Description |
200 | Campaign step deleted. Returns `{ deleted: true }`. |
400 | `INVALID_ID_FORMAT` — `id` or `stepId` is not a valid UUID. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
200 response body: data fields
| Field | Type | Description |
deleted | boolean | |
GET /v1/change-mgmt/approvals
List change approvals
Returns approval decisions, optionally filtered by `changeset_id` and/or `decision`.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
changeset_id | query | string<uuid> | no | Filter by changeset identifier (UUIDv7). |
decision | query | string (enum) | no | Filter by approval decision. |
limit | query | integer | no | Maximum number of records to return. Default and ceiling are endpoint-specific (commonly default 25–50, max 100). |
offset | query | integer | no | Number of records to skip for offset pagination. |
Responses
| Status | Description |
200 | Approval list. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
200 response body: data fields
| Field | Type | Description |
approvals | array of object | |
total_count | integer | |
POST /v1/change-mgmt/approvals
Record a change approval decision
Records an approval, rejection, or change-request decision against a changeset.
Auth Session JWT (Bearer)
Request Body
| Field | Type | Required | Description |
changeset_id | string<uuid> | yes | |
decision | string (enum) approverejectrequest_changes | yes | |
comment | string | no | |
conditions | array of string | no | Optional list of conditions attached to this decision. |
Responses
| Status | Description |
201 | Approval decision recorded. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
GET /v1/change-mgmt/changesets
List changesets
Returns changesets for the authenticated organization. Supports optional filters: `project_id`, `status`, `changeset_type`, `search`.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
project_id | query | string<uuid> | no | Filter by project identifier (UUIDv7). |
status | query | string (enum) | no | Filter by changeset status. |
changeset_type | query | string (enum) | no | Filter by changeset type. |
search | query | string | no | Free-text search across title/description (max 200 chars). |
limit | query | integer | no | Maximum number of records to return. Default and ceiling are endpoint-specific (commonly default 25–50, max 100). |
offset | query | integer | no | Number of records to skip for offset pagination. |
Responses
| Status | Description |
200 | Changeset list. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
200 response body: data fields
| Field | Type | Description |
changesets | array of object | |
total_count | integer | |
POST /v1/change-mgmt/changesets
Create a changeset
Creates a new changeset to group related changes before review and deployment.
Auth Session JWT (Bearer)
Request Body
| Field | Type | Required | Description |
title | string | yes | |
description | string | no | |
project_id | string<uuid> | no | |
changeset_type | string (enum) featurebugfixhotfixrefactorconfig | no | Defaults to `feature` when omitted. |
priority | string (enum) lownormalhighcritical | no | Defaults to `normal` when omitted. |
metadata | object | no | |
Responses
| Status | Description |
201 | Changeset created. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
201 response body: data fields
| Field | Type | Description |
id | string<uuid> | |
org_id | string<uuid> | |
title | string | |
description | string | null | |
project_id | string | null | |
changeset_type | string (enum) featurebugfixhotfixrefactorconfig | |
priority | string (enum) lownormalhighcritical | |
status | string | Current lifecycle status. |
changes | array of object | |
created_at | string<date-time> | |
GET /v1/change-mgmt/changesets/{id}
Get a changeset
Returns a changeset including its individual changes.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
id | path | string<uuid> | yes | Changeset identifier (UUIDv7). |
Responses
| Status | Description |
200 | Changeset record. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
200 response body: data fields
| Field | Type | Description |
id | string<uuid> | |
org_id | string<uuid> | |
title | string | |
description | string | null | |
project_id | string | null | |
changeset_type | string (enum) featurebugfixhotfixrefactorconfig | |
priority | string (enum) lownormalhighcritical | |
status | string | Current lifecycle status. |
changes | array of object | |
created_at | string<date-time> | |
PUT /v1/change-mgmt/changesets/{id}
Update a changeset
Updates changeset fields. The `status` field is **not accepted here** — use the dedicated lifecycle endpoints (`/submit`, `/approve`, `/reject`, `/apply`, `/revert`). Sending `status` returns `400 VALIDATION_ERROR` with a redirect hint.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
id | path | string<uuid> | yes | Changeset identifier (UUIDv7). |
Request Body
| Field | Type | Required | Description |
title | string | no | |
description | string | no | |
priority | string (enum) lownormalhighcritical | no | |
metadata | object | no | |
Responses
| Status | Description |
200 | Changeset updated. |
400 | `VALIDATION_ERROR` — field validation failed, or the request included `status` (use lifecycle endpoints instead). |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
200 response body: data fields
| Field | Type | Description |
id | string<uuid> | |
org_id | string<uuid> | |
title | string | |
description | string | null | |
project_id | string | null | |
changeset_type | string (enum) featurebugfixhotfixrefactorconfig | |
priority | string (enum) lownormalhighcritical | |
status | string | Current lifecycle status. |
changes | array of object | |
created_at | string<date-time> | |
GET /v1/change-mgmt/changesets/{id}/changes
List changes in a changeset
Returns all individual resource changes within the specified changeset.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
id | path | string<uuid> | yes | Changeset identifier (UUIDv7). |
Responses
| Status | Description |
200 | Change list. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
200 response body: data fields
| Field | Type | Description |
changes | array of object | |
total_count | integer | |
POST /v1/change-mgmt/changesets/{id}/changes
Add a change to a changeset
Adds an individual resource change to the specified changeset. `change_type` determines the recorded operation: `create` → INSERT, `update`/`move`/`rename` → UPDATE, `delete` → DELETE.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
id | path | string<uuid> | yes | Changeset identifier (UUIDv7). |
Request Body
| Field | Type | Required | Description |
change_type | string (enum) createupdatedeletemoverename | yes | `create` → INSERT, `update`/`move`/`rename` → UPDATE, `delete` → DELETE. |
resource_type | string | yes | |
resource_id | string<uuid> | no | |
before_state | object | no | |
after_state | object | no | |
diff | object | no | |
description | string | no | |
metadata | object | no | |
Responses
| Status | Description |
201 | Change added to changeset. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
201 response body: data fields
| Field | Type | Description |
id | string<uuid> | |
changeset_id | string<uuid> | |
change_type | string (enum) createupdatedeletemoverename | |
resource_type | string | |
resource_id | string | null | |
before_state | object | null | |
after_state | object | null | |
diff | object | null | |
description | string | null | |
created_at | string<date-time> | |
POST /v1/deployments/approval-policy
Set a deployment approval policy
Creates or replaces the approval policy for a deployment environment. The policy specifies which roles must approve a run to `production` or `preprod` and minimum approval quorums.
Auth Session JWT (Bearer)
Request Body
| Field | Type | Required | Description |
environment | string (enum) productionpreprod | yes | Target deployment environment. |
role_keys | array of string | yes | Role keys that are eligible approvers (1–32, each max 64 chars). |
min_total_approvals | integer | no | Minimum total approvals required (minimum 2). Optional. |
min_roles_represented | integer | no | Minimum distinct roles that must be represented in the approvals (minimum 2). Optional. |
Responses
| Status | Description |
200 | Approval policy set. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
POST /v1/deployments/approvals
Approve or reject a deployment run
Records an approval or rejection decision for a pending deployment run. The `action` field determines the decision. Dual-approval rules (BB-03) are enforced by the stored procedure; a second approver in the same role is required for production deployments when the policy requires it.
Auth Session JWT (Bearer)
Request Body
| Field | Type | Required | Description |
environment_id | string<uuid> | yes | Deployment environment identifier. |
commit_sha | string | yes | Commit SHA being approved. |
action | string (enum) approvereject | yes | Approval decision. |
Responses
| Status | Description |
200 | Approval or rejection recorded. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
409 | `CONFLICT` — dual-approval requirement not yet satisfied; or another approval gate conflict. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
POST /v1/deployments/configs
Upsert a deployment config
Creates or updates a deployment configuration record. The config links a repository to the deployment system via vault and encryption key references.
Auth Session JWT (Bearer)
Request Body
| Field | Type | Required | Description |
repo_id | string<uuid> | yes | Repository identifier (UUIDv7). |
vault_ref | string | yes | Vault reference for secret injection. |
dek_secret_ref | string | yes | Data-encryption key secret reference. |
webhook_secret_ref | string | no | Optional webhook signing secret reference. |
dek_epoch | integer | no | Optional DEK epoch for key rotation tracking (min 1). |
Responses
| Status | Description |
200 | Config created or updated. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
POST /v1/deployments/environments
Upsert a deployment environment
Creates or updates a deployment environment within a config. Environments define the branch, deploy commands, container size, and secret exposure.
Auth Session JWT (Bearer)
Request Body
| Field | Type | Required | Description |
config_id | string<uuid> | yes | Parent deployment config identifier. |
name | string | yes | Environment name (e.g. `production`, `staging`). |
branch | string | yes | Git branch to deploy from. |
working_dir | string | no | Optional working directory within the repository. |
deploy_commands | array of string | no | Ordered list of deploy commands to execute (max 64). |
container_size | string (enum) basicstandard-1standard-2standard-3standard-4 | no | Deploy container size. |
exposed_secret_keys | array of string | no | List of secret item UUIDs to inject as environment variables (max 128). |
github_token_secret_ref | string | no | Optional GitHub token secret reference for private repo access. |
egress_allowlist | array of string | no | Optional network egress allowlist (max 64 entries). |
auto_deploy | boolean | no | Whether to auto-trigger a deploy on branch push. |
Responses
| Status | Description |
200 | Environment created or updated. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
POST /v1/deployments/runs
Start a deployment run
Creates a queued deployment run for the given environment and commit SHA, then best-effort provisions a deploy container. The run record is created regardless of container provisioning success. If provisioning fails, `orchestrated: false` is returned and the run can be retried. Requires the `deployment.trigger` permission.
Auth Session JWT (Bearer)
Request Body
| Field | Type | Required | Description |
environment_id | string<uuid> | yes | Deployment environment identifier. |
commit_sha | string | yes | Commit SHA to deploy. |
trigger | string (enum) manualwebhookpollerretry | no | What triggered this run. Optional. |
instance_token_id | string<uuid> | no | Optional pre-created instance token identifier. |
Responses
| Status | Description |
200 | Run queued. `orchestrated: true` if the container was successfully started. If `orchestrated: false`, `orchestration_error` contains a non-fatal reason. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
409 | `CONFLICT` — dual-approval gate not met; submit approvals first. |
429 | 429 Too Many Requests — a rate limit or usage quota was exceeded. Retry after the indicated window. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
200 response body: data fields
| Field | Type | Description |
run_id | string<uuid> | |
orchestrated | boolean | `true` if the deploy container was successfully started. |
orchestration_error | string | null | Non-fatal message if the container could not be started. The run record still exists and can be retried. |
POST /v1/deployments/runs/{runId}/cancel
Cancel a deployment run
Cancels a queued or running deployment run.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
runId | path | string<uuid> | yes | Deployment run identifier (UUIDv7). |
Request Body
| Field | Type | Required | Description |
reason | string | no | Optional cancellation reason. |
Responses
| Status | Description |
200 | Run cancelled. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
GET /v1/deployments/runs/{runId}/events
List deployment run events
Returns the progress/error log for a deployment run. Supports incremental polling via `?after_seq=` to fetch only events since the last poll.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
runId | path | string<uuid> | yes | Deployment run identifier (UUIDv7). |
after_seq | query | string | no | Return only events with a sequence number greater than this value. |
Responses
| Status | Description |
200 | Run event log. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
POST /v1/deployments/runs/{runId}/events
Record a deployment run event (container only)
Records a structured progress/status event for a deployment run. This endpoint is called **only** by the deploy container using its per-run instance token (`apiKeyAuth`). A human session JWT is rejected. When the container reports a terminal status (`succeeded`, `failed`, or `cancelled`), the instance token is revoked automatically.
Auth API key (Bearer bb_live_…)
Parameters
| Name | In | Type | Required | Description |
runId | path | string<uuid> | yes | Deployment run identifier (UUIDv7). |
Request Body
| Field | Type | Required | Description |
client_event_id | string | yes | Client-generated idempotency key for this event. |
level | string (enum) infowarnerror | no | Log level. Optional. |
phase | string | no | Deployment phase (e.g. `checkout`, `build`, `deploy`). Optional. |
error_class | string | no | Error class or type for error-level events. Optional. |
sqlstate | string | no | 5-char PostgreSQL SQLSTATE code for DB errors. Optional. |
failing_migration | string | no | Migration filename that triggered the failure. Optional. |
wrangler_binding | string | no | Cloudflare wrangler binding name involved in a failure. Optional. |
message | string | no | Event message. Optional. |
status | string (enum) queuedprovisioningrunningsucceededfailedcancelled | no | Overall run status at the time of this event. Terminal statuses (`succeeded`, `failed`, `cancelled`) revoke the instance token. Optional. |
Responses
| Status | Description |
200 | Event recorded. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | `FORBIDDEN` — the token is not a valid deployment instance token or is not bound to this run. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
POST /v1/deployments/runs/{runId}/retry
Retry a deployment run
Retries a failed or cancelled deployment run.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
runId | path | string<uuid> | yes | Deployment run identifier (UUIDv7). |
Responses
| Status | Description |
200 | Run retry queued. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
GET /v1/deployments/secret-keys
List secret keys available to this run (container only)
Returns the list of escrow secret item IDs that the running deploy container is authorized to fetch. This endpoint requires a deployment instance token (`apiKeyAuth`); a user JWT is rejected. Use the returned IDs with `POST /v1/deployments/secret-value` to retrieve decrypted values.
Auth API key (Bearer bb_live_…)
Responses
| Status | Description |
200 | List of authorized secret item IDs. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | `FORBIDDEN` — caller is not a deployment instance token. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
POST /v1/deployments/secret-value
Get a decrypted secret value (container only)
Authorizes and returns the decrypted plaintext value of the specified secret item. This endpoint requires a deployment instance token (`apiKeyAuth`); a user JWT is rejected. The value is decrypted in the API worker — never in the database — and returned over TLS. The container is expected to hold values in memory only.
Auth API key (Bearer bb_live_…)
Request Body
| Field | Type | Required | Description |
item_id | string<uuid> | yes | Escrow secret item identifier (UUIDv7). |
Responses
| Status | Description |
200 | Decrypted secret value. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | `FORBIDDEN` — caller is not a deployment instance token, or is not authorized to access this secret for this run. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
200 response body: data fields
| Field | Type | Description |
name | string | null | Secret name. |
value | string | Decrypted plaintext value. |
GET /v1/deployments/setup
Get deployment setup
Returns the deployment configuration for the authenticated organization (configs, environments, approval policies, and run summary). Pass `config_id` to scope the response to a single configuration.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
config_id | query | string<uuid> | no | Deployment config identifier (UUIDv7) to filter the response. |
Responses
| Status | Description |
200 | Deployment setup record. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
POST /v1/deployments/solo-mode
Set solo-operator mode
Enables or disables solo-operator mode for a deployment config. In solo mode a single-person organization can deploy without a second approver.
Auth Session JWT (Bearer)
Request Body
| Field | Type | Required | Description |
config_id | string<uuid> | yes | Deployment config identifier. |
enabled | boolean | no | Whether to enable solo-operator mode. Optional; SP applies its own default when omitted. |
Responses
| Status | Description |
200 | Solo-operator mode updated. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
GET /v1/feature-flags/effective
Get effective feature flags for caller
Returns the effective (resolved) feature flag state for the authenticated user and their organization. Available to any authenticated user; does not require super-admin.
Auth Session JWT (Bearer)
Responses
| Status | Description |
200 | Resolved feature flag states for the caller's organization. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
200 response body: data fields
| Field | Type | Description |
org_id | string<uuid> | |
feature_flags | object | Resolved feature flag state map. |
GET /v1/releases/{slug}/current
Get the current release version (public)
Returns the latest published version for the product and channel visible to the given organization. This is the update-check endpoint called by installed desktop clients. No authentication is required; `org_id` must be supplied as a query parameter to scope the lookup.
Public Public: no authentication
Parameters
| Name | In | Type | Required | Description |
slug | path | string | yes | Product slug. |
org_id | query | string<uuid> | yes | Organization identifier (UUIDv7) — required because no session is present. |
channel | query | string | no | Distribution channel (1–50 chars). Defaults to the product's primary channel when omitted. |
current_version | query | string | no | The client's installed version string. Included in telemetry; does not change the response. |
install_id_hash | query | string | no | Pseudonymous install ID hash (≤256 chars) for analytics. Never linked to a user. |
Responses
| Status | Description |
200 | Current release version record. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
200 response body: data fields
| Field | Type | Description |
version | string | |
channel | string | |
release_notes_url | string | null | |
required_upgrade | boolean | |
artefacts | array of object | |
manifest_sha256_hex | string | |
published_at | string<date-time> | |
PUT /v1/releases/products/{slug}
Upsert a release product
Creates or updates a desktop release product definition for the authenticated organization. A product groups versions across channels for a single distributable tool.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
slug | path | string | yes | Product slug (lowercase alphanumeric with dots, hyphens, or underscores; 1–100 chars). |
Request Body
| Field | Type | Required | Description |
base_tool | string | yes | Base tool identifier for this product. |
display_name | string | yes | Human-readable product name. |
branding_config_id | string<uuid> | no | Optional branding config identifier. |
custom_domain | string | no | Optional custom domain for release downloads (max 253 chars). |
data_residency | string (enum) useu | no | Data residency region for release artefacts. Optional. |
Responses
| Status | Description |
200 | Product created or updated. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | `FORBIDDEN` — caller lacks the `releases.manage` permission. |
409 | `CONFLICT` — the custom domain is already taken by another product. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
200 response body: data fields
| Field | Type | Description |
slug | string | Product slug. |
org_id | string<uuid> | |
base_tool | string | |
display_name | string | |
branding_config_id | string | null | |
custom_domain | string | null | |
data_residency | string (enum) useu | |
created_at | string<date-time> | |
POST /v1/releases/products/{slug}/versions
Start a release version publish
Opens a new version staging record for the product. Call this before uploading artefacts. Returns the staging version ID used for subsequent `/artefacts`, `/complete`, and `/finalize` calls.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
slug | path | string | yes | Product slug. |
Request Body
| Field | Type | Required | Description |
version | string | yes | Version string (e.g. `1.2.3`). |
channel | string | no | Distribution channel (e.g. `stable`, `beta`, `nightly`). Optional. |
publisher_token_hash_hex | string | no | Hex-encoded hash of the publisher token for this publish flow. Optional. |
Responses
| Status | Description |
201 | Staging version created. Returns the staging release record including the version ID. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | `FORBIDDEN` — caller lacks the `releases.publish` permission. |
404 | `NOT_FOUND` — product slug not found. |
409 | `CONFLICT` — a version with this version string already exists for the product. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
201 response body: data fields
| Field | Type | Description |
id | string<uuid> | |
product_slug | string | |
version | string | |
channel | string | |
state | string (enum) stagingcompletefinalizedyanked | |
created_at | string<date-time> | |
POST /v1/releases/signing-keys
Register a signing key
Registers an Ed25519 public signing key for the organization's release pipeline. The key is identified by `key_id` (human-readable); `public_key_hex` is the 32-byte raw Ed25519 public key as 64 hex chars. Optionally chains from a prior key via `signed_by_key_id` and `successor_signature_hex`.
Auth Session JWT (Bearer)
Request Body
| Field | Type | Required | Description |
key_id | string | yes | Human-readable key identifier (e.g. `prod-2025-01`). |
public_key_hex | string | yes | Hex-encoded 32-byte Ed25519 public key (exactly 64 hex chars). |
signed_by_key_id | string | no | Optional key_id of the predecessor key that signs the succession. |
successor_signature_hex | string | no | Optional hex-encoded 64-byte Ed25519 signature of this key's public_key_hex by the `signed_by_key_id` key (exactly 128 hex chars). |
Responses
| Status | Description |
201 | Signing key registered. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | `FORBIDDEN` — caller lacks the `releases.manage_keys` permission. |
409 | `CONFLICT` — a key with this `key_id` already exists. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
201 response body: data fields
| Field | Type | Description |
key_id | string | |
org_id | string<uuid> | |
public_key_hex | string | |
is_active | boolean | |
revoked_at | string | null | |
signed_by_key_id | string | null | |
successor_signature_hex | string | null | |
created_at | string<date-time> | |
POST /v1/releases/signing-keys/{id}/revoke
Revoke a signing key
Revokes the signing key identified by `id` (the textual `key_id`, not a UUID). Revoked keys are retained for historical verification but are excluded from the active key chain.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
id | path | string | yes | The signing key's textual `key_id` (1–200 chars, not a UUID). |
Request Body
| Field | Type | Required | Description |
reason | string | yes | Mandatory reason for revocation (audit trail). |
Responses
| Status | Description |
200 | Signing key revoked. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | `FORBIDDEN` — caller lacks the `releases.manage_keys` permission. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
409 | `CONFLICT` — the key is already revoked. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
GET /v1/releases/signing-keys/chain
Get the signing key chain (public)
Returns the full chain of active and revoked public signing keys for the organization. Clients use this to verify the integrity and authenticity of release manifests. No authentication is required; `org_id` must be supplied as a query parameter.
Public Public: no authentication
Parameters
| Name | In | Type | Required | Description |
org_id | query | string<uuid> | yes | Organization identifier (UUIDv7). |
Responses
| Status | Description |
200 | Signing key chain. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
DELETE /v1/releases/versions/{id}
Cancel a staged release version
Cancels and removes a staged (not-yet-finalized) release version. Returns `VALIDATION_ERROR` if the version has already been finalized.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
id | path | string<uuid> | yes | Staged release version identifier (UUIDv7). |
Responses
| Status | Description |
200 | Staged version cancelled. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | `FORBIDDEN` — caller lacks the `releases.publish` permission. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
422 | `VALIDATION_ERROR` — the version is already finalized and cannot be cancelled. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
POST /v1/releases/versions/{id}/artefacts
Add an artefact to a staged version
Registers a platform-specific binary artefact (OS + arch combination) against a staged release version. The artefact must have already been uploaded to R2; this call records its `r2_key`, `sha256_hex`, and optional platform-signed digest.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
id | path | string<uuid> | yes | Staged release version identifier (UUIDv7). |
Request Body
| Field | Type | Required | Description |
os | string | yes | Target operating system (e.g. `linux`, `darwin`, `windows`). |
arch | string | yes | Target CPU architecture (e.g. `x86_64`, `aarch64`). |
r2_key | string | yes | R2 object key where the binary was uploaded. |
archive_format | string | yes | Archive format (e.g. `zip`, `tar.gz`). |
sha256_hex | string | yes | Lowercase hex-encoded SHA-256 of the artefact binary (exactly 64 chars). |
size_bytes | integer | yes | Artefact file size in bytes. |
os_signature | object | no | Optional OS-level code-signing signature object (structure is OS-dependent). |
Responses
| Status | Description |
200 | Artefact registered. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | `FORBIDDEN` — caller lacks the `releases.publish` permission. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
422 | `VALIDATION_ERROR` — the staging version is in an invalid state (e.g. already finalized or yanked). |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
POST /v1/releases/versions/{id}/complete
Complete a staged version
Marks the artefact upload phase as complete, records optional release notes URL, minimum OS requirements, and whether this is a forced upgrade.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
id | path | string<uuid> | yes | Staged release version identifier (UUIDv7). |
Request Body
| Field | Type | Required | Description |
release_notes_url | string<uri> | no | URL to the release notes page (max 2048 chars). |
min_supported_os | object | no | Minimum OS version map (e.g. `{windows: '10', macos: '12.0'}`). |
required_upgrade | boolean | no | Whether this is a forced upgrade. Clients below this version will be blocked. |
Responses
| Status | Description |
200 | Version marked complete. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | `FORBIDDEN` — caller lacks the `releases.publish` permission. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
422 | `VALIDATION_ERROR` — no artefacts have been registered or the version state is invalid. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
POST /v1/releases/versions/{id}/finalize
Finalize a staged version
Finalizes the staged version by recording the manifest SHA-256 hash and an Ed25519 signature over the manifest. The version is published and becomes visible to update checks after this call.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
id | path | string<uuid> | yes | Staged release version identifier (UUIDv7). |
Request Body
| Field | Type | Required | Description |
manifest_sha256_hex | string | yes | Hex-encoded SHA-256 of the release manifest (exactly 64 chars). |
manifest_sig_hex | string | yes | Hex-encoded Ed25519 signature over the manifest hash (exactly 128 chars / 64 bytes). |
Responses
| Status | Description |
200 | Version finalized and published. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | `FORBIDDEN` — caller lacks the `releases.publish` permission. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
422 | `VALIDATION_ERROR` — the version is not in the `complete` state, or the active signing key is missing. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
PATCH /v1/releases/versions/{id}/rollout
Set rollout percentage for a version
Sets the rollout percentage for a published version. A percentage of `0` pauses rollout; `100` completes it. Requires both `product_slug` and `version` in the body.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
id | path | string<uuid> | yes | Release version surrogate identifier (UUIDv7). |
Request Body
| Field | Type | Required | Description |
product_slug | string | yes | Product slug. |
version | string | yes | Version string. |
percentage | integer | yes | Rollout percentage. `0` pauses rollout; `100` completes it. |
Responses
| Status | Description |
200 | Rollout percentage updated. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | `FORBIDDEN` — caller lacks the `releases.publish` permission. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
422 | `VALIDATION_ERROR` — the version has been yanked. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
POST /v1/releases/versions/{id}/yank
Yank a release version
Yanks a published version so that update checks no longer offer it to clients. Requires both `product_slug` and `version` in the body alongside the path `id`. A reason is mandatory for audit purposes.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
id | path | string<uuid> | yes | Release version surrogate identifier (UUIDv7). |
Request Body
| Field | Type | Required | Description |
product_slug | string | yes | Product slug to identify the release. |
version | string | yes | Version string to yank. |
reason | string | yes | Mandatory reason for yanking (audit trail). |
Responses
| Status | Description |
200 | Version yanked. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | `FORBIDDEN` — caller lacks the `releases.yank` permission. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
422 | `VALIDATION_ERROR` — the version is already yanked. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
GET /v1/saas-packages/{packageId}/approval-policies
Get approval policies
Returns all approval policies for the SaaS package.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
packageId | path | string<uuid> | yes | SaaS package identifier (UUIDv7). |
Responses
| Status | Description |
200 | List of approval policies. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
POST /v1/saas-packages/{packageId}/approval-policies
Create an approval policy
Creates an approval policy for the SaaS package. The `rules` field must be a top-level branch node (`{operator, conditions}`) — bare leaf conditions at the top level are rejected. The conditions tree is limited to 5 levels of nesting. The request body is limited to 8 KiB to guard against deeply-nested rule trees.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
packageId | path | string<uuid> | yes | SaaS package identifier (UUIDv7). |
Request Body
| Field | Type | Required | Description |
category | string (enum) staging_promotionpreprod_promotionproduction_deploymentsecurity_reviewcompliance_reviewrollback_authorization | yes | Policy category. |
name | string | yes | Policy name. |
description | string | no | Optional policy description. |
rules | any | yes | A node in the approval condition tree. The top-level `rules` field must be a branch node (`operator` + `conditions`). Leaf nodes specify a specific_users, role, group, or cross_role condition. Maximum tree depth is 5; each branch may have 1–10 children. |
Responses
| Status | Description |
201 | Approval policy created. |
400 | `INVALID_JSON`, `VALIDATION_ERROR` (field validation or rules tree exceeds depth limit), or `PAYLOAD_TOO_LARGE` (body > 8 KiB). |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | `FORBIDDEN` — caller lacks the `approval_policy.create` permission. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
409 | `CONFLICT` — a policy with this category is already active for the package. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
201 response body: data fields
| Field | Type | Description |
id | string<uuid> | |
package_id | string<uuid> | |
category | string (enum) staging_promotionpreprod_promotionproduction_deploymentsecurity_reviewcompliance_reviewrollback_authorization | |
name | string | |
description | string | null | |
rules | any | A node in the approval condition tree. The top-level `rules` field must be a branch node (`operator` + `conditions`). Leaf nodes specify a specific_users, role, group, or cross_role condition. Maximum tree depth is 5; each branch may have 1–10 children. |
is_active | boolean | |
created_at | string<date-time> | |
updated_at | string<date-time> | |
DELETE /v1/saas-packages/{packageId}/approval-policies/{policyId}
Deactivate an approval policy
Soft-deactivates an approval policy. A deactivated policy is no longer enforced for new approval requests.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
packageId | path | string<uuid> | yes | SaaS package identifier (UUIDv7). |
policyId | path | string<uuid> | yes | Approval policy identifier (UUIDv7). |
Responses
| Status | Description |
200 | Policy deactivated. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | `FORBIDDEN` — caller lacks the `approval_policy.delete` permission. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
409 | `CONFLICT` — policy is currently in use by a pending approval and cannot be deactivated. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
GET /v1/saas-packages/{packageId}/environments
Get environment deployment status
Returns the currently deployed release for each environment (development, staging, preprod, production) for the given SaaS package.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
packageId | path | string<uuid> | yes | SaaS package identifier (UUIDv7). |
Responses
| Status | Description |
200 | Per-environment deployment status. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
GET /v1/saas-packages/{packageId}/environments/history
Get deployment history
Returns the paginated deployment history for a SaaS package, optionally filtered by environment.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
packageId | path | string<uuid> | yes | SaaS package identifier (UUIDv7). |
environment | query | string (enum) | no | Filter by environment. |
page | query | integer | no | 1-based page number. |
limit | query | integer | no | Records per page (1–100). |
Responses
| Status | Description |
200 | Paginated deployment history. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
GET /v1/saas-packages/{packageId}/releases
List releases
Returns paginated releases for a SaaS package, optionally filtered by status.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
packageId | path | string<uuid> | yes | SaaS package identifier (UUIDv7). |
status | query | string (enum) | no | Filter by release status. |
page | query | integer | no | 1-based page number (default 1). |
limit | query | integer | no | Records per page (1–100). |
Responses
| Status | Description |
200 | Paginated list of releases. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
POST /v1/saas-packages/{packageId}/releases
Create a release
Creates a new draft release for the given SaaS package. The release name must be unique within the package. Returns the full release record.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
packageId | path | string<uuid> | yes | SaaS package identifier (UUIDv7). |
Request Body
| Field | Type | Required | Description |
release_name | string | yes | Human-readable release name, unique within the package. |
release_notes | string | no | Optional markdown release notes. |
Responses
| Status | Description |
201 | Release created. The full release record is returned under `data`. |
400 | `INVALID_JSON` or `VALIDATION_ERROR` (name missing, exceeds 200 chars, or invalid package ID) or `INVALID_ID_FORMAT` (malformed packageId). |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | `FORBIDDEN` — caller lacks the `saas_release.create` permission. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
201 response body: data fields
| Field | Type | Description |
id | string<uuid> | Release identifier (UUIDv7). |
package_id | string<uuid> | Owning SaaS package identifier. |
release_name | string | Human-readable release name. |
release_notes | string | null | Optional markdown release notes. |
status | string (enum) drafttestingapprovedrejectedarchived | Current lifecycle status. |
created_at | string<date-time> | |
updated_at | string<date-time> | |
GET /v1/saas-packages/{packageId}/releases/{releaseId}
Get a release
Returns a single release record by ID.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
packageId | path | string<uuid> | yes | SaaS package identifier (UUIDv7). |
releaseId | path | string<uuid> | yes | Release identifier (UUIDv7). |
Responses
| Status | Description |
200 | Release record. |
400 | `INVALID_ID_FORMAT` — malformed packageId or releaseId. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
200 response body: data fields
| Field | Type | Description |
id | string<uuid> | Release identifier (UUIDv7). |
package_id | string<uuid> | Owning SaaS package identifier. |
release_name | string | Human-readable release name. |
release_notes | string | null | Optional markdown release notes. |
status | string (enum) drafttestingapprovedrejectedarchived | Current lifecycle status. |
created_at | string<date-time> | |
updated_at | string<date-time> | |
GET /v1/saas-packages/{packageId}/releases/{releaseId}/approval-status
Evaluate approval policy status
Evaluates the current approval policy for the release and environment, returning whether approval requirements are satisfied, the individual approver decisions, and which approvers are still outstanding.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
packageId | path | string<uuid> | yes | SaaS package identifier (UUIDv7). |
releaseId | path | string<uuid> | yes | Release identifier (UUIDv7). |
environment | query | string (enum) | yes | Environment to evaluate approval for. |
Responses
| Status | Description |
200 | Approval policy evaluation result. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
200 response body: data fields
| Field | Type | Description |
approved | boolean | |
pending_conditions | array of string | |
approvers | array of object | |
POST /v1/saas-packages/{packageId}/releases/{releaseId}/approve
Approve a release
Records an approval decision for the release targeting the specified environment. Separation-of-duties is enforced: the approver must not be the requester (when the package policy requires it).
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
packageId | path | string<uuid> | yes | SaaS package identifier (UUIDv7). |
releaseId | path | string<uuid> | yes | Release identifier (UUIDv7). |
Request Body
| Field | Type | Required | Description |
environment | string (enum) stagingpreprodproduction | yes | Target environment being approved. |
comment | string | no | Optional approval comment. |
Responses
| Status | Description |
200 | Approval recorded. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | `FORBIDDEN` — caller lacks the `saas_release.approve` permission. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
422 | `VALIDATION_ERROR` — separation-of-duties violation, wrong release state, or no active approval request. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
POST /v1/saas-packages/{packageId}/releases/{releaseId}/compliance-check
Run a compliance check
Evaluates the release against compliance requirements for the target environment (approval status, mandatory tests, change-window restrictions, etc.). Returns a structured compliance result indicating pass/fail per check.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
packageId | path | string<uuid> | yes | SaaS package identifier (UUIDv7). |
releaseId | path | string<uuid> | yes | Release identifier (UUIDv7). |
Request Body
| Field | Type | Required | Description |
target_environment | string (enum) stagingpreprodproduction | yes | Environment to evaluate compliance for. |
Responses
| Status | Description |
200 | Compliance check result. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | `FORBIDDEN` — caller lacks the `saas_release.compliance` permission. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
POST /v1/saas-packages/{packageId}/releases/{releaseId}/deploy
Deploy a release
Deploys the release to the specified environment. Supports four rollout strategies: `immediate` (all tenants at once), `targeted` (explicit list of org IDs), `percentage` (a random sample), and `progressive` (staged percentage ramp-up with configurable wait periods). A progressive deploy with `rollout_stages` starts the rollout scheduler automatically. Invalidates the application-config KV cache on success.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
packageId | path | string<uuid> | yes | SaaS package identifier (UUIDv7). |
releaseId | path | string<uuid> | yes | Release identifier (UUIDv7). |
Request Body
| Field | Type | Required | Description |
environment | string (enum) developmentstagingpreprodproduction | yes | Target deployment environment. |
notes | string | no | Optional deployment notes. |
rollout_strategy | string (enum) immediatetargetedpercentageprogressive | no | Rollout strategy. Defaults to `immediate` when omitted. |
target_org_ids | array of string | no | Specific organization IDs for `targeted` strategy. |
target_percentage | integer | no | Rollout percentage for the `percentage` strategy. |
rollout_stages | array of object | no | Stage definitions for `progressive` strategy (1–20). |
Responses
| Status | Description |
200 | Deployment initiated. Returns the deployment record. If a `progressive` strategy was requested, `rollout_plan_id` is included. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | `FORBIDDEN` — caller lacks the `saas_release.deploy` permission. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
409 | `CONFLICT` — an active deployment already exists for this environment, or the release is in an invalid state for deployment. |
422 | `VALIDATION_ERROR` — the release cannot be deployed (e.g. approval required, compliance check required, or rejection in place). |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
200 response body: data fields
| Field | Type | Description |
deployment_id | string<uuid> | |
environment | string | |
status | string | |
deployed_at | string | null | |
POST /v1/saas-packages/{packageId}/releases/{releaseId}/import-to-draft
Import a release to draft
Imports the specified release's configuration into a new draft for the package. Used to create a new release pre-populated from an existing one (e.g. to re-apply a deployed config as a baseline for new changes).
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
packageId | path | string<uuid> | yes | SaaS package identifier (UUIDv7). |
releaseId | path | string<uuid> | yes | Release identifier to import (UUIDv7). |
Request Body
| Field | Type | Required | Description |
environment | string (enum) developmentstagingpreprodproduction | yes | Source environment to import the current deployment state from. |
Responses
| Status | Description |
200 | Import completed. Returns the new draft release. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | `FORBIDDEN` — caller lacks the `saas_release.import` permission. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
200 response body: data fields
| Field | Type | Description |
id | string<uuid> | Release identifier (UUIDv7). |
package_id | string<uuid> | Owning SaaS package identifier. |
release_name | string | Human-readable release name. |
release_notes | string | null | Optional markdown release notes. |
status | string (enum) drafttestingapprovedrejectedarchived | Current lifecycle status. |
created_at | string<date-time> | |
updated_at | string<date-time> | |
GET /v1/saas-packages/{packageId}/releases/{releaseId}/items
List release manifest items
Returns the version-pinned manifest items for the release. Each item represents a configuration artifact (screen, seed, connector, etc.) pinned at a specific version in this release snapshot.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
packageId | path | string<uuid> | yes | SaaS package identifier (UUIDv7). |
releaseId | path | string<uuid> | yes | Release identifier (UUIDv7). |
Responses
| Status | Description |
200 | Release manifest items. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
POST /v1/saas-packages/{packageId}/releases/{releaseId}/reject
Reject a release
Records a rejection decision for a pending approval. The `reason` field is required for audit purposes.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
packageId | path | string<uuid> | yes | SaaS package identifier (UUIDv7). |
releaseId | path | string<uuid> | yes | Release identifier (UUIDv7). |
Request Body
| Field | Type | Required | Description |
environment | string (enum) stagingpreprodproduction | yes | Target environment being rejected. |
reason | string | yes | Mandatory rejection reason. |
Responses
| Status | Description |
200 | Rejection recorded. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | `FORBIDDEN` — caller lacks the `saas_release.approve` permission. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
422 | `VALIDATION_ERROR` — no active approval request to reject, or wrong release state. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
POST /v1/saas-packages/{packageId}/releases/{releaseId}/request-approval
Request approval for a release
Submits an approval request for the release targeting the specified environment. Requires an active approval policy to exist for the target environment category; if none exists, returns `409 CONFLICT`.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
packageId | path | string<uuid> | yes | SaaS package identifier (UUIDv7). |
releaseId | path | string<uuid> | yes | Release identifier (UUIDv7). |
Request Body
| Field | Type | Required | Description |
environment | string (enum) stagingpreprodproduction | yes | Target environment for which approval is requested. |
Responses
| Status | Description |
200 | Approval request submitted. Returns the approval request record. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | `FORBIDDEN` — caller lacks the `saas_release.update` permission. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
409 | `CONFLICT` — no active approval policy exists for the target environment category. |
422 | `VALIDATION_ERROR` — the release is not in a state from which approval can be requested. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
POST /v1/saas-packages/{packageId}/releases/{releaseId}/rollback
Rollback a release
Rolls back the active deployment in the specified environment to the previously deployed release. Only `staging`, `preprod`, and `production` environments support rollback.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
packageId | path | string<uuid> | yes | SaaS package identifier (UUIDv7). |
releaseId | path | string<uuid> | yes | Release identifier (UUIDv7). |
Request Body
| Field | Type | Required | Description |
environment | string (enum) stagingpreprodproduction | yes | Target environment to roll back. |
notes | string | no | Optional rollback notes. |
Responses
| Status | Description |
200 | Rollback initiated. Returns the new deployment record. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | `FORBIDDEN` — caller lacks the `saas_release.rollback` permission. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
422 | `VALIDATION_ERROR` — no prior deployment exists to roll back to, or the transition is otherwise invalid. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
200 response body: data fields
| Field | Type | Description |
deployment_id | string<uuid> | |
environment | string | |
status | string | |
deployed_at | string | null | |
PATCH /v1/saas-packages/{packageId}/releases/{releaseId}/status
Update release status
Transitions the release to the specified status. Valid transitions are enforced server-side; an invalid transition returns `422 VALIDATION_ERROR`.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
packageId | path | string<uuid> | yes | SaaS package identifier (UUIDv7). |
releaseId | path | string<uuid> | yes | Release identifier (UUIDv7). |
Request Body
| Field | Type | Required | Description |
status | string (enum) testingapprovedrejectedarchived | yes | Target status. `draft` is omitted because you cannot manually transition back to draft. |
reason | string | no | Optional reason for the transition (required for `rejected` by convention). |
Responses
| Status | Description |
200 | Release status updated. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
422 | `VALIDATION_ERROR` — the requested status transition is invalid for the release's current state (e.g. transition preconditions not met). |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
200 response body: data fields
| Field | Type | Description |
id | string<uuid> | Release identifier (UUIDv7). |
package_id | string<uuid> | Owning SaaS package identifier. |
release_name | string | Human-readable release name. |
release_notes | string | null | Optional markdown release notes. |
status | string (enum) drafttestingapprovedrejectedarchived | Current lifecycle status. |
created_at | string<date-time> | |
updated_at | string<date-time> | |
POST /v1/saas-packages/{packageId}/releases/{releaseId}/undeploy
Undeploy a release
Removes the current deployment from the specified environment, leaving the environment with no active release. Only `staging`, `preprod`, and `production` environments are supported.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
packageId | path | string<uuid> | yes | SaaS package identifier (UUIDv7). |
releaseId | path | string<uuid> | yes | Release identifier (UUIDv7). |
Request Body
| Field | Type | Required | Description |
environment | string (enum) stagingpreprodproduction | yes | Target environment to undeploy from. |
notes | string | no | Optional undeploy notes. |
Responses
| Status | Description |
200 | Release undeployed. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | `FORBIDDEN` — caller lacks the `saas_release.deploy` permission. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
422 | `VALIDATION_ERROR` — no active deployment in the requested environment. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
GET /v1/saas-packages/{packageId}/releases/diff
Diff two releases
Returns a semantic diff of the version-pinned manifest between two releases of the same package. Both `from` and `to` must be UUIDs of releases that belong to this package.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
packageId | path | string<uuid> | yes | SaaS package identifier (UUIDv7). |
from | query | string<uuid> | yes | Release ID to diff from (UUIDv7). |
to | query | string<uuid> | yes | Release ID to diff to (UUIDv7). |
Responses
| Status | Description |
200 | Diff result. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
POST /v1/saas-packages/{packageId}/rollouts
Create a rollout plan
Creates a rollout plan for an existing active deployment. The plan defines how the release is progressively distributed across tenants. Requires `saas_release.deploy` permission.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
packageId | path | string<uuid> | yes | SaaS package identifier (UUIDv7). |
Request Body
| Field | Type | Required | Description |
deployment_id | string<uuid> | yes | Deployment identifier to roll out. |
strategy | string (enum) immediatetargetedpercentageprogressive | yes | Rollout strategy. |
target_org_ids | array of string | no | Specific organizations for `targeted` strategy (max 1000). |
stages | array of object | no | Stage definitions for `progressive` strategy (max 20). |
Responses
| Status | Description |
201 | Rollout plan created. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | `FORBIDDEN` — caller lacks the `saas_release.deploy` permission. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
409 | `CONFLICT` — a rollout plan already exists for this deployment. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
201 response body: data fields
| Field | Type | Description |
id | string<uuid> | |
deployment_id | string<uuid> | |
strategy | string (enum) immediatetargetedpercentageprogressive | |
current_stage | integer | |
status | string | |
stages | array of object | |
created_at | string<date-time> | |
GET /v1/saas-packages/{packageId}/rollouts/{rolloutId}
Get rollout status
Returns the current rollout plan status including per-stage progress.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
packageId | path | string<uuid> | yes | SaaS package identifier (UUIDv7). |
rolloutId | path | string<uuid> | yes | Rollout plan identifier (UUIDv7). |
Responses
| Status | Description |
200 | Rollout plan with per-stage progress. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
200 response body: data fields
| Field | Type | Description |
id | string<uuid> | |
deployment_id | string<uuid> | |
strategy | string (enum) immediatetargetedpercentageprogressive | |
current_stage | integer | |
status | string | |
stages | array of object | |
created_at | string<date-time> | |
POST /v1/saas-packages/{packageId}/rollouts/{rolloutId}/advance
Advance rollout to next stage
Manually advances a progressive rollout to the next stage without waiting for the scheduled wait period to expire.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
packageId | path | string<uuid> | yes | SaaS package identifier (UUIDv7). |
rolloutId | path | string<uuid> | yes | Rollout plan identifier (UUIDv7). |
Responses
| Status | Description |
200 | Rollout advanced to the next stage. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | `FORBIDDEN` — caller lacks the `saas_release.deploy` permission. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
422 | `VALIDATION_ERROR` — rollout is not in a state that can be advanced (e.g. already complete or cancelled). |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
POST /v1/saas-packages/{packageId}/rollouts/{rolloutId}/cancel
Cancel a rollout
Cancels a progressive rollout. The rollout is terminated and no further stages will be executed. An optional `reason` can be provided.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
packageId | path | string<uuid> | yes | SaaS package identifier (UUIDv7). |
rolloutId | path | string<uuid> | yes | Rollout plan identifier (UUIDv7). |
Request Body
| Field | Type | Required | Description |
reason | string | no | Optional reason for the rollout action (pause, resume, cancel). |
Responses
| Status | Description |
200 | Rollout cancelled. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | `FORBIDDEN` — caller lacks the `saas_release.deploy` permission. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
POST /v1/saas-packages/{packageId}/rollouts/{rolloutId}/pause
Pause a rollout
Pauses a progressive rollout at the current stage. An optional `reason` can be provided. The rollout can be resumed by advancing to the next stage.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
packageId | path | string<uuid> | yes | SaaS package identifier (UUIDv7). |
rolloutId | path | string<uuid> | yes | Rollout plan identifier (UUIDv7). |
Request Body
| Field | Type | Required | Description |
reason | string | no | Optional reason for the rollout action (pause, resume, cancel). |
Responses
| Status | Description |
200 | Rollout paused. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | `FORBIDDEN` — caller lacks the `saas_release.deploy` permission. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
GET /v1/time-triggers
List time triggers
Returns time-based automation triggers for the authenticated organization.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
page | query | integer | no | Page number (1-based). |
page_size | query | integer | no | Results per page (max 200). |
Responses
| Status | Description |
200 | Time trigger list. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
200 response body: data fields
| Field | Type | Description |
triggers | array of object | |
total_count | integer | |
POST /v1/time-triggers
Create a time trigger
Creates a cron-based time trigger. The `cron_expression` must be a valid 5-field cron expression (minute hour day-of-month month day-of-week).
Auth Session JWT (Bearer)
Request Body
| Field | Type | Required | Description |
name | string | yes | |
cron_expression | string | yes | Valid 5-field cron expression. |
action_type | string | yes | |
action_config | object | yes | |
is_enabled | boolean | no | |
next_run_at | string<date-time> | no | |
Responses
| Status | Description |
201 | Time trigger created. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
201 response body: data fields
| Field | Type | Description |
id | string<uuid> | |
org_id | string<uuid> | |
name | string | |
cron_expression | string | 5-field cron expression (minute hour day-of-month month day-of-week). |
action_type | string | |
action_config | object | |
is_enabled | boolean | |
next_run_at | string | null | |
created_at | string<date-time> | |
PUT /v1/time-triggers/{id}
Update a time trigger
Updates a time trigger. All fields are optional.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
id | path | string<uuid> | yes | Time trigger identifier (UUIDv7). |
Request Body
| Field | Type | Required | Description |
name | string | no | |
cron_expression | string | no | Valid 5-field cron expression. |
action_type | string | no | |
action_config | object | no | |
is_enabled | boolean | no | |
next_run_at | string<date-time> | no | |
Responses
| Status | Description |
200 | Time trigger updated. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
200 response body: data fields
| Field | Type | Description |
id | string<uuid> | |
org_id | string<uuid> | |
name | string | |
cron_expression | string | 5-field cron expression (minute hour day-of-month month day-of-week). |
action_type | string | |
action_config | object | |
is_enabled | boolean | |
next_run_at | string | null | |
created_at | string<date-time> | |
DELETE /v1/time-triggers/{id}
Delete a time trigger
Permanently deletes a time trigger.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
id | path | string<uuid> | yes | Time trigger identifier (UUIDv7). |
Responses
| Status | Description |
200 | Time trigger deleted. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
GET /v1/time-triggers/{id}/logs
Get time trigger execution log
Returns execution logs for the specified time trigger with optional `status` filter and pagination.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
id | path | string<uuid> | yes | Time trigger identifier (UUIDv7). |
status | query | string | no | Filter by execution status (max 50 chars). |
page | query | integer | no | Page number (1-based). |
page_size | query | integer | no | Results per page (max 200). |
Responses
| Status | Description |
200 | Trigger execution log. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
200 response body: data fields
| Field | Type | Description |
logs | array of object | |
total_count | integer | |
GET /v1/workflows
List approval workflows
Returns approval workflows for the authenticated organization. When called via the `/v1/org/{orgId}/workflows` or `/v1/organizations/{orgId}/workflows` alias paths, `data` is a plain array rather than the paginated `{workflows, total_count}` object.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
status | query | string (enum) | no | Filter by workflow status. |
trigger_type | query | string (enum) | no | Filter by trigger type. |
search | query | string | no | Free-text search (max 200 chars). |
limit | query | integer | no | Maximum number of records to return. Default and ceiling are endpoint-specific (commonly default 25–50, max 100). |
offset | query | integer | no | Number of records to skip for offset pagination. |
Responses
| Status | Description |
200 | Workflow list. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
200 response body: data fields
| Field | Type | Description |
workflows | array of object | |
total_count | integer | |
POST /v1/workflows
Create an approval workflow
Creates a new approval workflow with up to 100 steps (each step defines a state transition and the role required to execute it).
Auth Session JWT (Bearer)
Request Body
| Field | Type | Required | Description |
name | string | yes | |
description | string | no | |
entity_type_id | string<uuid> | no | |
status | string (enum) activedraftarchived | no | |
trigger_type | string (enum) manualeventschedulewebhookcondition | no | |
steps | array of object | no | Up to 100 steps can be provided at creation time. |
Responses
| Status | Description |
201 | Workflow created. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
201 response body: data fields
| Field | Type | Description |
id | string<uuid> | |
org_id | string<uuid> | |
name | string | |
description | string | null | |
entity_type_id | string | null | |
status | string (enum) activedraftarchived | |
trigger_type | string (enum) manualeventschedulewebhookcondition | |
steps | array of object | |
created_at | string<date-time> | |
GET /v1/workflows/{workflowId}
Get an approval workflow
Returns a single approval workflow including its steps.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
workflowId | path | string<uuid> | yes | Workflow identifier (UUIDv7). |
Responses
| Status | Description |
200 | Workflow record. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
200 response body: data fields
| Field | Type | Description |
id | string<uuid> | |
org_id | string<uuid> | |
name | string | |
description | string | null | |
entity_type_id | string | null | |
status | string (enum) activedraftarchived | |
trigger_type | string (enum) manualeventschedulewebhookcondition | |
steps | array of object | |
created_at | string<date-time> | |
PUT /v1/workflows/{workflowId}
Update an approval workflow
Updates workflow metadata. At least one non-`changelog` field must be provided. `changelog` alone is insufficient and returns 400.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
workflowId | path | string<uuid> | yes | Workflow identifier (UUIDv7). |
Request Body
| Field | Type | Required | Description |
name | string | no | |
description | string | no | |
entity_type_id | string | null | no | |
is_active | boolean | no | |
status | string (enum) activedraftarchived | no | |
trigger_type | string (enum) manualeventschedulewebhookcondition | no | |
changelog | string | no | Optional change summary for audit purposes only (max 500 chars). Not a substitute for a data-field update. |
Responses
| Status | Description |
200 | Workflow updated. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
200 response body: data fields
| Field | Type | Description |
id | string<uuid> | |
org_id | string<uuid> | |
name | string | |
description | string | null | |
entity_type_id | string | null | |
status | string (enum) activedraftarchived | |
trigger_type | string (enum) manualeventschedulewebhookcondition | |
steps | array of object | |
created_at | string<date-time> | |
DELETE /v1/workflows/{workflowId}
Delete an approval workflow
Permanently deletes an approval workflow.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
workflowId | path | string<uuid> | yes | Workflow identifier (UUIDv7). |
Responses
| Status | Description |
200 | Workflow deleted. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
POST /v1/workflows/{workflowId}/steps
Add a step to a workflow
Adds a state-transition step to the workflow. Each step defines `from_state_id`, `to_state_id`, and the `required_role` that can execute the transition.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
workflowId | path | string<uuid> | yes | Workflow identifier (UUIDv7). |
Request Body
| Field | Type | Required | Description |
from_state_id | string<uuid> | yes | Source workflow state. |
to_state_id | string<uuid> | yes | Target workflow state. |
required_role | string | no | Role required to execute this transition. |
required_group_id | string<uuid> | no | Optional group required to execute this transition. |
Responses
| Status | Description |
201 | Workflow step added. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
201 response body: data fields
| Field | Type | Description |
id | string<uuid> | |
workflow_id | string<uuid> | |
from_state_id | string<uuid> | |
to_state_id | string<uuid> | |
required_role | string | null | |
required_group_id | string | null | |
sort_order | integer | |
PUT /v1/workflows/{workflowId}/steps/{stepId}
Update a workflow step
Updates a workflow step. At least one non-`changelog` field must be provided.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
workflowId | path | string<uuid> | yes | Workflow identifier (UUIDv7). |
stepId | path | string<uuid> | yes | Step identifier (UUIDv7). |
Request Body
| Field | Type | Required | Description |
from_state_id | string<uuid> | no | |
to_state_id | string<uuid> | no | |
required_role | string | null | no | |
required_group_id | string | null | no | |
sort_order | integer | no | |
changelog | string | no | Optional change summary for audit purposes only (max 500 chars). |
Responses
| Status | Description |
200 | Workflow step updated. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
200 response body: data fields
| Field | Type | Description |
id | string<uuid> | |
workflow_id | string<uuid> | |
from_state_id | string<uuid> | |
to_state_id | string<uuid> | |
required_role | string | null | |
required_group_id | string | null | |
sort_order | integer | |
DELETE /v1/workflows/{workflowId}/steps/{stepId}
Delete a workflow step
Removes a state-transition step from the workflow.
Auth Session JWT (Bearer)
Parameters
| Name | In | Type | Required | Description |
workflowId | path | string<uuid> | yes | Workflow identifier (UUIDv7). |
stepId | path | string<uuid> | yes | Step identifier (UUIDv7). |
Responses
| Status | Description |
200 | Workflow step deleted. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
404 | 404 Not Found — the requested resource does not exist or is not visible to the caller. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
GET /v1/workflows/states
List workflow states
Returns all workflow states for the authenticated organization.
Auth Session JWT (Bearer)
Responses
| Status | Description |
200 | Workflow state list. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
POST /v1/workflows/states
Create a workflow state
Creates a new workflow state. `color` must be a valid 7-char hex color (e.g. `#4CAF50`). `position` is 0-based display order.
Auth Session JWT (Bearer)
Request Body
| Field | Type | Required | Description |
name | string | yes | |
description | string | no | |
color | string | no | 7-char hex color code (e.g. `#4CAF50`). Optional. |
position | integer | no | 0-based display order. Optional. |
is_initial | boolean | no | |
is_terminal | boolean | no | |
metadata | object | no | |
Responses
| Status | Description |
201 | Workflow state created. |
400 | 400 Bad Request — a request parameter, body field, or the JSON body itself failed validation. |
401 | 401 Unauthorized — missing, expired, malformed, or revoked credentials. |
403 | 403 Forbidden — authenticated but lacking the required membership, role, permission, MFA step-up, or feature entitlement. |
500 | 500 Internal Server Error — an unexpected server-side error. The message is sanitized; the correlation id is logged server-side. |
201 response body: data fields
| Field | Type | Description |
id | string<uuid> | |
org_id | string<uuid> | |
name | string | |
description | string | null | |
color | string | 7-char hex color code. |
position | integer | |
is_initial | boolean | |
is_terminal | boolean | |
metadata | object | null | |
created_at | string<date-time> | |