HTTP API
Call the gateway directly when your language has no SDK, or when a system you already run should speak REST. Node.js covers this whole contract. Python and Go cover workers. Paths have no version prefix.
When to use HTTP
| Situation | Path |
|---|---|
| Java, .NET, Ruby, PHP, or any language without a client in this release | This HTTP API |
| A custom gateway, BFF, or ESB | This HTTP API |
| Node.js or TypeScript automation, workers, and inbox BFFs | Node.js SDK |
| Go external workers | Go worker client |
| Python workers, jobs only | Python worker |
| People designing or operating processes | The console, not raw HTTP |
Base URL and gateway
The gateway is the supported public entry for Compose and Helm.
| Environment | Command writes | Query reads |
|---|---|---|
| Local Compose | http://localhost:9100/api | http://localhost:9100/api/query |
| Production example | https://app.example.com/api | https://app.example.com/api/query |
| Direct service, local debugging only | http://localhost:8080 | http://localhost:8081 |
The gateway rewrites GET /api/health to command /health, POST /api/instances to command /instances, and GET /api/query/instances to query /instances. Compatibility is the worker protocol header and the platform release.
OpenAPI, Swagger, and Postman
The machine-readable contract is OpenAPI 3.0.3 for release v1.1.0. It covers command, query, worker, inbox, and identity-administration routes. This guide and that file are the release contract. Generate clients from the OpenAPI file. The command service also serves a legacy Swaggo page at /api/swagger/index.html. That page needs a token and lists only annotated handlers, so it is not the complete contract.
- Swagger UI for the checked-in contract. Authorize with a bearer token and select the local server.
- OpenAPI document (
artificialflow-v1.1.0.yaml). The upstream copy is docs/openapi.yaml. - Postman collection (Collection v2.1, grouped by tag) and the local environment. Import both. Set
bearerTokento a short-lived machine access token.baseUrlishttp://localhost:9100/api.
On worker calls send X-Workflow-Worker-Protocol-Version: v1. On job complete, fail, and lock extension send a distinct Idempotency-Key of at most 128 characters. The narrative source is docs/API.md.
Authentication
Protected routes require Authorization: Bearer. Integrations use a machine identity that holds only artificialflow client. Obtain the token with client credentials from your OIDC provider. The audience is normally workflow-backend.
TOKEN=$(curl -sS -X POST "$TOKEN_URL" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=$CLIENT_ID" \
-d "client_secret=$CLIENT_SECRET" \
-d "audience=workflow-backend" \
| jq -r .access_token)
curl -sS "$API/identity/me" -H "Authorization: Bearer $TOKEN"| Role | API use |
|---|---|
artificialflow client | Workers, automation, and backends. Start instances, jobs, messages, signals, query reads, and inbox calls that carry acting-user headers. |
artificialflow modeler | Deploy and list workflows and decisions. This role cannot start instances or search projected instances. |
artificialflow admin | Delete workflows and instances, incidents, job retry, admin task claim, metrics, and identity administration. Keep this role off a long-lived worker. |
An inbox backend that holds both artificialflow client and artificialflow admin is rejected. Catalog letters below are A for admin, M for modeler, and C for client. GET /identity/me returns the principal for any valid token. GET /identity/config returns non-secret deployment settings: mode, issuers, claim paths, and standard roles.
Conventions
- JSON bodies use
Content-Type: application/json. Deploy BPMN withPOST /workflowsandContent-Type: application/xml. The body limit is about 20 MB. - Resource ids come back as JSON strings. Query instance ids and the
workflowIdfilter must be numeric strings. - Worker responses include
X-Workflow-Engine-Protocol-Version: v1. OptionalX-Correlation-IDtraces a request. - Query reads are eventually consistent. Read the command instance when the write must be visible immediately.
/healthonly proves the HTTP process is running. Sync health can return HTTP 200 while the worker is starting or degraded.
Error bodies are plain text. Read the body and treat any status outside 2xx as failure.
| Status | Typical meaning |
|---|---|
400 | Validation, a bad id, or an unsupported worker protocol version. |
401 | Missing or invalid token, issuer, audience, or expiry. |
403 | The token is valid and the role, or the inbox acting user, is rejected. |
404 | Unknown workflow, instance, or job. |
409 | Conflict, including a task claim state. |
413 | BPMN body larger than about 20 MB. |
500 | Server error. |
Quickstart
$API is the gateway command root. The query search in the last call is under the same origin.
export API=http://localhost:9100/api
export TOKEN=…
curl -sS "$API/identity/me" -H "Authorization: Bearer $TOKEN"
curl -sS -X POST "$API/workflows" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/xml" \
--data-binary @process.bpmn
curl -sS -X POST "$API/instances" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"workflow_id": "order_approval",
"context": { "orderId": "ord-1", "amount": 1500 }
}'
curl -sS -X POST "$API/jobs/activate" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-H "X-Workflow-Worker-Protocol-Version: v1" \
-d '{
"type": "payment",
"worker": "payments-1",
"maxJobs": 5,
"timeoutMs": 5000,
"lockDurationMs": 30000
}'
curl -sS -X POST "$API/jobs/$JOB_KEY/complete" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-H "X-Workflow-Worker-Protocol-Version: v1" \
-H "Idempotency-Key: complete-$JOB_KEY-1" \
-d '{ "worker": "payments-1", "variables": { "paid": true } }'
curl -sS "$API/query/instances?state=RUNNING&page=1&pageSize=20" \
-H "Authorization: Bearer $TOKEN"Command reference
Workflows
POST /workflows deploys raw BPMN 2.0 XML. Roles A, M, and C. The response is a workflow definition with string id, process_definition_id, version, and bpmn_xml. GET /workflows and GET /workflows/{id} use the same roles. {id} may be the numeric definition key or the BPMN process id. DELETE /workflows/{id} is admin only and returns 204.
Instances
POST /instances starts a process. Roles A and C. workflow_id is required and may be a numeric definition key or a BPMN process id. Optional version pins a version when workflow_id is a process id. Optional context is the initial variable map. The response status for a running instance is ACTIVE.
GET /instanceslists active instances from the command store. Modeler-only principals are blocked.GET /instances/history/completed?limit=defaults to a cap of 100.GET /instances/{id}returns the instance, executions, and task metadata.DELETE /instances/{id}is admin only and returns 204.POST /instances/{id}/variablessends{ "variables": { "approved": true } }.POST /instances/{id}/completeis legacy step completion bystep_id. Human tasks use the inbox.GET /instances/{id}/tasksreturns{ "tasks": [] }.
Admin task operations, not the end-user inbox:
| Method | Path | Roles |
|---|---|---|
| POST | /instances/{id}/tasks/{executionId}/claim | A |
| POST | /instances/{id}/tasks/{executionId}/complete | A |
| GET | /instances/{id}/jobs | A |
Messages, signals, and escalations
Roles A and C. Empty bodies are allowed. A successful publish often returns an empty JSON object.
curl -sS -X POST "$API/messages" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"message_name": "PaymentReceived",
"correlation_key": "ord-1",
"payload": { "amount": 1500 }
}'
curl -sS -X POST "$API/signals" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "signal_name": "GlobalCancel", "payload": {} }'
curl -sS -X POST "$API/escalations" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "escalation_code": "NeedManager", "payload": {} }'Decisions
POST /decisions and GET /decisions accept A, M, and C. The resource field is a string containing the JSON decision table. POST /decisions/{id}/evaluate accepts A and C. {id} is the decision id, and the body is { "inputs": { "amount": 1500 } }. See Decisions.
Incidents, retry, and metrics
| Method | Path | Roles |
|---|---|---|
| GET | /incidents?processInstanceKey=&limit= | A |
| POST | /jobs/{key}/retry | A, optional body { "retries": 3 } |
| GET | /internal/metrics | A, outbox and idempotency counters |
The Incidents console page is hidden in this release. The HTTP route remains.
Workers
External service tasks become lockable jobs. Protocol version is v1. Roles are A and C. The loop is GET /jobs/capabilities, then POST /jobs/activate, then complete, fail, or extend the lock. Idempotency scope is the operation plus the job key. Replay of the same key returns 200. Complete, fail, and extend-lock need distinct keys. Details and the lock fields are on Workers.
gRPC JobWorkerService listens on the command process at GRPC_ADDR, default :50051. The gateway does not publish it.
Inbox
A trusted backend holds the artificialflow client token and sends the signed-in person on each call. Subject or email is required. Acting roles must omit artificialflow admin and artificialflow client. A person using the browser Task Inbox, with no platform role, acts as themselves and omits these headers.
| Header | Purpose |
|---|---|
X-ArtificialFlow-Acting-Subject | Stable user id. Preferred. |
X-ArtificialFlow-Acting-Username | Username, used when subject is absent. |
X-ArtificialFlow-Acting-Email | Email. Subject or email is required. |
X-ArtificialFlow-Acting-Name | Display name. |
X-ArtificialFlow-Acting-Roles | Comma-separated roles and candidate groups. |
| Method | Path |
|---|---|
| GET | /inbox |
| GET | /inbox/history?limit= |
| GET | /inbox/instances/{id} |
| GET | /inbox/instances/{id}/tasks |
| POST | /inbox/instances/{id}/tasks/{executionId}/claim |
| POST | /inbox/instances/{id}/tasks/{executionId}/complete |
Query
Base {gateway}/api/query. GET /query/instances and GET /query/instances/{id} accept admin and client. workflowId is a numeric definition key. state=RUNNING maps to stored status ACTIVE. Other filters include COMPLETED and FAILED. page defaults to 1 and pageSize to 20. Projected instances omit the task tree. Use command GET /instances/{id} or the inbox for task detail. GET /query/workflows accepts admin, modeler, and client, and omits BPMN XML. GET /query/health is public. GET /query/identity/me inspects the same bearer principal.
Identity administration
These routes are in the v1.1.0 contract for trusted administrative automation. Every one requires artificialflow admin. Do not call them from browser code. Create and rotate responses can contain one-time secret material.
| Method | Path |
|---|---|
| GET, POST | /identity/management/clients |
| DELETE | /identity/management/clients/{id} |
| POST | /identity/management/clients/{id}/tokens |
| DELETE | /identity/management/clients/{id}/tokens/{tokenId} |
| POST | /identity/management/clients/{id}/keys |
| DELETE | /identity/management/clients/{id}/keys/{keyId} |
| GET, POST | /identity/management/users |
| PUT, DELETE | /identity/management/users/{id} |
| POST | /identity/management/users/{id}/terminate |
| POST | /identity/management/users/{id}/reactivate |
| GET, POST | /identity/management/roles |
| PUT, DELETE | /identity/management/roles/{roleKey} |
Command catalog
Paths are relative to /api.
| Method | Path | Roles |
|---|---|---|
| GET | /health | public |
| GET | /identity/me | auth |
| GET | /identity/config | auth |
| POST | /workflows | A, M, C |
| GET | /workflows | A, M, C |
| GET | /workflows/{id} | A, M, C |
| DELETE | /workflows/{id} | A |
| POST | /decisions | A, M, C |
| GET | /decisions | A, M, C |
| POST | /decisions/{id}/evaluate | A, C |
| POST | /instances | A, C |
| GET | /instances | scoped |
| GET | /instances/history/completed | scoped |
| GET | /instances/{id} | scoped |
| DELETE | /instances/{id} | A |
| POST | /instances/{id}/variables | A, C |
| POST | /instances/{id}/complete | A, C |
| GET | /instances/{id}/tasks | scoped |
| POST | /instances/{id}/tasks/{executionId}/claim | A |
| POST | /instances/{id}/tasks/{executionId}/complete | A |
| GET | /instances/{id}/jobs | A |
| GET | /incidents | A |
| POST | /jobs/{key}/retry | A |
| POST | /signals | A, C |
| POST | /messages | A, C |
| POST | /escalations | A, C |
| GET | /jobs/capabilities | A, C |
| POST | /jobs/activate | A, C |
| POST | /jobs/{key}/complete | A, C |
| POST | /jobs/{key}/fail | A, C |
| POST | /jobs/{key}/extend-lock | A, C |
| GET | /inbox | inbox |
| GET | /inbox/history | inbox |
| GET | /inbox/instances/{id} | inbox |
| GET | /inbox/instances/{id}/tasks | inbox |
| POST | /inbox/instances/{id}/tasks/{executionId}/claim | inbox |
| POST | /inbox/instances/{id}/tasks/{executionId}/complete | inbox |
| GET | /internal/metrics | A |
Query catalog
Paths are relative to /api/query.
| Method | Path | Roles |
|---|---|---|
| GET | /health | public |
| GET | /identity/me | auth |
| GET | /instances | A, C |
| GET | /instances/{id} | A, C |
| GET | /workflows | A, M, C |
Production checklist
- Use a dedicated machine identity with only
artificialflow client. - Keep client secrets in a secret manager. Obtain short-lived tokens on the server.
- Send
X-Correlation-IDand record it with your own request id. - Retry transient network failures and selected 5xx responses. Do not blindly retry instance starts or message publication. Reuse an
Idempotency-Keyonly for the same job operation and payload. - Set the worker lock longer than normal execution, and extend it before it expires.
- Read command
GET /instances/{id}when the write must be visible immediately. Poll query with a bounded timeout. - Pin the minor line, check
GET /jobs/capabilitiesat worker startup, and regenerate clients only from a reviewed OpenAPI diff.