Workflow HTTP routes start at /api/workflow, all declared by [GenerateEndpoint] on Platform Application commands and queries and grouped by tag: Workflow-Runtime / Workflow-Tasks / Workflow-History / Workflow-Definitions / Workflow-Management / Workflow-Metadata / Workflow-Reports. Write commands carry RateLimitPolicy="userPolicy" plus RequestTimeoutPolicy="WorkflowCommand"/"StandardCommand"; the generator registers them conditionally via RequireService=IWorkflowEngine (IWorkflowTaskCenterStore for the task center) — on hosts without a composed persistence adapter these endpoints simply do not exist. The OpenAPI document from the current build remains the request/response schema source of truth.
1. Common pipeline
Every generated route requires authentication and passes through IAuthorizedRequest module/resource/action authorization; rate-limit and timeout policies come from each command attribute, with runtime writes using the longer WorkflowCommand timeout. No hand-written entry point bypasses the pipeline — new capabilities are new commands or queries, never extra endpoint files.
2. Definitions
| Method | Route | Purpose |
|---|---|---|
| POST | /api/workflow/definitions/ | deploy snapshot |
| POST | /api/workflow/definitions/validate | static validation |
| POST | /api/workflow/definitions/simulate | in-memory preview |
| GET | /api/workflow/definitions/schema | designer schema |
| GET | /api/workflow/definitions/{key}/versions | version list |
| GET | /api/workflow/definitions/versions/{definitionId} | one version |
| GET | /api/workflow/definitions/{key}/active | active definition |
| GET | /api/workflow/definitions/{key}/deployments | bindings |
| POST | /api/workflow/definitions/{key}/deployments | publish |
| POST | /api/workflow/definitions/{key}/deployments/grayscale | switch active and retain previous |
| POST | /api/workflow/definitions/{key}/deployments/complete-grayscale | status promotion |
| POST | /api/workflow/definitions/{key}/deployments/rollback | restore previous |
| GET | /api/workflow/definitions/designer-schema | designer metadata (node ConfigFields/resolver/handler catalogs) |
| GET | /api/workflow/definitions/{key}/draft | read draft revision |
| PUT | /api/workflow/definitions/{key}/draft | save draft (optimistic Revision) |
| DELETE | /api/workflow/definitions/{key}/draft | delete draft |
| POST | /api/workflow/definitions/{key}/draft/validate | validate saved draft |
| POST | /api/workflow/definitions/{key}/draft/simulate | simulate draft path |
| POST | /api/workflow/definitions/{key}/draft/publish | authoritative validation, immutable version + binding update |
Grayscale is not percentage routing, and only draft/publish closes the full validation loop — the legacy POST /api/workflow/definitions/ still requires merely compilable JSON.
3. Runtime
| Method | Route | Purpose |
|---|---|---|
| POST | /api/workflow/runtime/instances | start |
| POST | /api/workflow/runtime/instances/start-at-node | start at mapped node |
| GET | /api/workflow/runtime/instances/{id}/progress | progress graph |
| POST | /api/workflow/runtime/tasks/{taskId}/complete | approve |
| POST | /api/workflow/runtime/tasks/{taskId}/reject | reject |
| POST | /api/workflow/runtime/tasks/{taskId}/transfer | transfer |
| POST | /api/workflow/runtime/tasks/{taskId}/delegate | delegate |
| POST | /api/workflow/runtime/tasks/{taskId}/add-participant | add signer |
| POST | /api/workflow/runtime/tasks/batch-complete | proxy-complete without process advance |
| POST | /api/workflow/runtime/instances/{id}/withdraw | withdraw |
| POST | /api/workflow/runtime/instances/{id}/resubmit | resubmit |
| POST | /api/workflow/runtime/instances/{id}/terminate | terminate |
| POST | /api/workflow/runtime/instances/{id}/cancel | cancel |
| POST | /api/workflow/runtime/instances/{id}/reset | reset node |
| POST | /api/workflow/runtime/instances/{id}/suspend | suspend |
| POST | /api/workflow/runtime/instances/{id}/resume | resume |
| POST | /api/workflow/runtime/instances/{id}/remind | remind |
| POST | /api/workflow/runtime/instances/{id}/priority | update priority |
| POST | /api/workflow/runtime/instances/{id}/transfer-applicant | transfer applicant |
Actor comes from CurrentUser. There is no HTTP Idempotency-Key contract.
4. Tasks
| Method | Route | Purpose |
|---|---|---|
| GET | /api/workflow/tasks/todo | todo page |
| GET | /api/workflow/tasks/todo/count | badge count |
| GET | /api/workflow/tasks/done | done page |
| GET | /api/workflow/tasks/{taskId} | detail |
| POST | /api/workflow/tasks/{taskId}/mark-read | read marker |
Detail is affected by the empty-user defect. Todo defaults to the full-memory data-scope path. Count intentionally omits data scope.
5. History
| Method | Route | Purpose |
|---|---|---|
| GET | /api/workflow/history/instances/{id}/timeline | timeline |
| GET | /api/workflow/history/instances/{id} | history summary |
| GET | /api/workflow/history/instances/{id}/trail | activity trail |
| POST | /api/workflow/history/instances/{id}/archive | archive |
| GET | /api/workflow/history/business/{businessKey}/timeline | aggregate timeline |
| GET | /api/workflow/history/business/{businessKey}/status | aggregate status |
Tenant scope for business-key reads comes from server context and store filters.
6. Reports
/api/workflow/reports includes instances, task-duration, approvers, bottlenecks, rejects, trends, and deployments. Generated endpoints use QUERY and provide /_query POST fallbacks. Trends use QUERY /api/workflow/reports/trends: From and To are both required and From must not be later than To; a missing or reversed range returns Workflow.Report.PeriodInvalid. TenantId comes only from CurrentUser, DefinitionKey is optional, and an unrecognized Granularity currently falls back to Daily. Missing QueryStore can still produce empty success, and trend average duration remains zero.
7. Management
| Method | Route | Purpose |
|---|---|---|
| POST | /api/workflow/management/import | import one legacy instance |
| GET | /api/workflow/management/statistics | engine statistics |
| DELETE | /api/workflow/management/definitions/{id} | delete definition |
| DELETE | /api/workflow/management/instances/{id} | delete terminal instance |
| POST | /api/workflow/management/tasks/{id}/refresh-candidates | refresh task candidates |
| POST | /api/workflow/management/roles/{id}/refresh-candidates | refresh by role |
Definition deletion does not check references. Import trusts body TenantId and lacks transaction/idempotency. Restrict and audit these operations.
8. Request example
POST /api/workflow/runtime/tasks/task-123/completeAuthorization: Bearer {token}Content-Type: application/json
{ "comment": "Approved", "variables": { "financeApproved": true }}ProblemDetails mapping is owned by WorkflowResultExtensions and ProblemDetailsMapper. Clients should use stable error identifiers rather than localized detail text.
9. Security checks
- resource-level authorization on every ID route;
- trusted tenant and office context;
- page, time-range, variable, comment, and request-body limits;
- enhanced audit for delete, reset, start-at-node, import, and transfer;
- rate limit and timeout on generated as well as hand-written routes.
The workflow.runtime feature is now enforced by WorkflowRuntimeLicenseGuard before every workflow write and background job; this item is delivered.
10. Source and OpenAPI checks
rg -n "GenerateEndpoint|Map(Get|Post|Delete)" src/Platform/Workflow src/Hosts/BitzOrcas.Api/Endpoints/Workflow -g '*.cs'
dotnet run --project src/Hosts/BitzOrcas.Api