API reference
7 operations in automations. Raw spec: openapi.json.
/api/v1/automation-rulesGET /api/automation-rules
Responses
| Status | Description |
|---|---|
200 |
Security: bearer
/api/v1/automation-rulesPOST /api/automation-rules — documents are validated through core-domain BEFORE storage, so stored rules are always well-formed (malformed rules can only arrive out-of-band and are skipped at evaluation time).
Request body
CreateRuleRequest
Responses
| Status | Description |
|---|---|
200 |
Security: bearer
/api/v1/automation-rules/draft-summaryPOST /api/v1/automation-rules/draft-summary — stream a one-sentence summary of the rule draft.
Admin-gated (Edit). NOT a write: it returns an SSE stream of frames and persists nothing. Refusals answer typed BEFORE any stream begins, so the client branches on the status code and renders a not-available state instead of a dead spinner.
Request body
AutomationDraftSummaryRequest
Responses
| Status | Description |
|---|---|
200 | SSE stream of summary frames (text/event-stream) |
400 | validation |
403 | typed refusal: ai_surface_not_granted | ai_surface_disabled | ai_model_not_allowed | ai_no_models_configured | ai_hard_cap_reached | ai_no_credential (the org master switch among them) |
Security: bearer
/api/v1/automation-rules/{id}PATCH /api/automation-rules/{id}
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes |
Request body
UpdateRuleRequest
Responses
| Status | Description |
|---|---|
200 |
Security: bearer
/api/v1/automation-rules/{id}DELETE /api/automation-rules/{id}
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes |
Responses
| Status | Description |
|---|---|
200 |
Security: bearer
/api/v1/automation-rules/{id}/test-runautomation_rules_test_run
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes |
Responses
| Status | Description |
|---|---|
200 | |
404 | rule not visible in scope |
422 | stored rule document is malformed |
Security: bearer
/api/v1/internal/effectsPOST /api/internal/effects — applies automation-rule effects to one ticket through the SAME write paths users go through (ticket patch, comment insert, notification fan-out), emitting every corresponding domain event tagged `via_automation` so evaluators never loop.
The subject may be ticket-less (Wave 43 lane 3): a board-scoped rule whose envelope carried no ticket. Then the board is resolved for scope and only subject-agnostic effects (notifications) run — every ticket-writing effect skips with a warn, never fails the batch, so one bad rule can never wedge the queue. # The batch runs as the rule's author (Wave 58 lane `p58-effects-seam`) The token is one deployment-wide bearer, so before this lane the request's `org_id` was both the RLS scope and the actor: the holder of the token could name any org and write there with no permission check. The principal is now the author recorded on `automation_rules.created_by`, resolved into a full [`Principal`] exactly as a session builds one, and the grant a manual write would need is applied before dispatch ([`effects_authority`]). A rule with no author is refused rather than attributed: the remedy is an admin re-saving it, which records the editor as the author. The batch's action list must be the rule's own, so a rule id authorises that rule's effects and not the author's whole authority. Every refusal is a typed 4xx with an `automation.effects_denied` audit row, and nothing the batch asked to write survives: the identity and matrix gates refuse before the write transaction opens, and a board denial rolls it back.
Request body
EffectsRequest
Responses
| Status | Description |
|---|---|
200 |