REST API Reference
Full HTTP API surface of the AEGIS Orchestrator — all routes, request/response schemas, and authentication.
REST API Reference
The AEGIS Orchestrator exposes an HTTP API on port 8080 (default). All request and response bodies are JSON unless otherwise noted.
Authentication
| Route group | Mechanism |
|---|---|
| Most endpoints | Keycloak Bearer JWT: Authorization: Bearer <token> |
POST /v1/webhooks/{source} | HMAC-SHA256 signature: X-Aegis-Signature: sha256=<hex> |
POST /v1/dispatch-gateway | Internal — no external auth (agent containers only) |
GET /health | None |
Service Account Tenant Delegation
Service accounts (M2M clients using client credentials) may include an X-Tenant-Id: {tenant-slug} request header to scope operations to a specific user tenant. Without this header, service account requests scope to the aegis-system tenant by default.
This header is ignored for all other identity types (consumer users, operator users).
Agents
GET /v1/agents/lookup/{name}
Look up a deployed agent by its unique name. Returns the agent's ID and manifest metadata.
Path parameters:
| Parameter | Description |
|---|---|
name | The unique name of the agent (e.g. code-reviewer) |
Request headers:
| Header | Required | Description |
|---|---|---|
Authorization | ✓ | Bearer JWT |
X-Tenant-Id | No | For service accounts: scope the lookup to this tenant instead of the default aegis-system tenant |
Response 200:
{
"agent_id": "agt-uuid",
"name": "code-reviewer",
"tenant_id": "tenant-slug"
}Errors:
| HTTP | Body | Cause |
|---|---|---|
404 | {"error": "Agent not found"} | No agent with that name exists in the resolved tenant |
GET /v1/agents
List all deployed agents visible to the caller's resolved tenant context.
Request headers:
| Header | Required | Description |
|---|---|---|
Authorization | ✓ | Bearer JWT |
X-Tenant-Id | No | For service accounts: scope the listing to this tenant instead of the default aegis-system tenant |
Response 200:
{
"agents": [
{
"agent_id": "agt-uuid",
"name": "code-reviewer",
"tenant_id": "tenant-slug"
}
]
}Executions
POST /v1/executions
Start an agent execution. Returns immediately with the execution_id; use the SSE stream to follow progress.
Request headers:
| Header | Required | Description |
|---|---|---|
Authorization | ✓ | Bearer JWT |
X-Tenant-Id | No | For service accounts: scope the execution to this tenant instead of the default aegis-system tenant |
Request body:
{
"agent_id": "agt-uuid",
"input": "Write a function that checks if a number is prime."
}| Field | Type | Required | Description |
|---|---|---|---|
agent_id | string (UUID) | ✓ | ID of a deployed agent |
input | string | ✓ | Task input passed to the agent |
Response 200:
{
"execution_id": "exec-uuid"
}Errors:
| HTTP | Body | Cause |
|---|---|---|
400 | {"error": "Invalid agent ID"} | agent_id is not a valid UUID |
500 | {"error": "<message>"} | Execution failed to start |
GET /v1/executions/{id}/stream
Stream execution events as Server-Sent Events (SSE). Returns Content-Type: text/event-stream.
Each data: line is a JSON-encoded ExecutionEvent object. Events match the types defined in the gRPC API reference.
Example stream:
data: {"execution_started":{"execution_id":"exec-uuid","agent_id":"agt-uuid","started_at":"2026-03-05T14:00:00Z"}}
data: {"iteration_started":{"execution_id":"exec-uuid","iteration_number":1,"action":"Write a primality check","started_at":"2026-03-05T14:00:01Z"}}
data: {"iteration_completed":{"execution_id":"exec-uuid","iteration_number":1,"output":"def is_prime(n): ...","completed_at":"2026-03-05T14:00:15Z"}}
data: {"execution_completed":{"execution_id":"exec-uuid","final_output":"def is_prime(n): ...","total_iterations":1,"completed_at":"2026-03-05T14:00:15Z"}}Example (JavaScript EventSource):
const es = new EventSource(
`https://your-aegis-node/v1/executions/${executionId}/stream`,
{ headers: { Authorization: `Bearer ${token}` } }
);
es.onmessage = (e) => {
const event = JSON.parse(e.data);
if (event.execution_completed) {
console.log('Output:', event.execution_completed.final_output);
es.close();
}
};Human Approvals
GET /v1/human-approvals
List all pending human approval requests.
Response 200:
{
"pending_requests": [
{
"id": "req-uuid",
"execution_id": "exec-uuid",
"prompt": "Review the draft and approve or reject.",
"created_at": "2026-03-05T14:00:00Z",
"timeout_seconds": 86400
}
]
}GET /v1/human-approvals/{id}
Get a specific pending approval request.
Response 200:
{
"request": {
"id": "req-uuid",
"execution_id": "exec-uuid",
"prompt": "Review the draft and approve or reject.",
"created_at": "2026-03-05T14:00:00Z",
"timeout_seconds": 86400
}
}Errors:
| HTTP | Body | Cause |
|---|---|---|
400 | {"error": "Invalid request ID"} | Not a valid UUID |
200 | {"error": "Request not found or already completed"} | Request expired or already resolved |
POST /v1/human-approvals/{id}/approve
Approve a pending request and resume the workflow.
Request:
{
"feedback": "Looks good, approved for production.",
"approved_by": "alice@example.com"
}Both fields are optional.
Response 200:
{ "status": "approved" }POST /v1/human-approvals/{id}/reject
Reject a pending request and transition the workflow to the rejection path.
Request:
{
"reason": "Needs more citations.",
"rejected_by": "bob@example.com"
}reason is required. rejected_by is optional.
Response 200:
{ "status": "rejected" }SEAL Endpoints
POST /v1/seal/attest
Attestation handshake — used by bootstrap.py at the start of each agent execution to establish an SEAL session.
Request:
{
"agent_id": "agt-uuid",
"execution_id": "exec-uuid",
"container_id": "container-hash",
"agent_public_key": "<base64-encoded Ed25519 public key>"
}Response 200:
{
"security_token": "<JWT>",
"session_id": "session-uuid",
"expires_at": "2026-03-05T15:00:00Z"
}See SEAL Architecture for the full attestation flow.
POST /v1/seal/invoke
SEAL-wrapped tool invocation. Called by bootstrap.py to invoke a tool through the orchestrator proxy. The body is a SealEnvelope containing a signed MCP tool call.
POST /v1/seal/invoke is the spec-compliant path. POST /v1/invoke is also registered as a convenience alias and remains fully functional.
See Tool Routing for the three routing paths and wire format.
Dispatch Gateway
POST /v1/dispatch-gateway
The inner-loop communication endpoint between bootstrap.py and the orchestrator. Handles the full LLM → tool call → LLM cycle.
This endpoint is called by bootstrap.py inside agent containers. It is bound to the internal Docker network and is not exposed externally.
Request — initial generate:
{
"type": "generate",
"agent_id": "agt-uuid",
"execution_id": "exec-uuid",
"iteration_number": 1,
"model_alias": "default",
"prompt": "Task: Write a primality check\n\nInput: in Python",
"messages": []
}Request — dispatch result:
{
"type": "dispatch_result",
"execution_id": "exec-uuid",
"dispatch_id": "dispatch-uuid",
"exit_code": 0,
"stdout": "All tests passed.\n",
"stderr": "",
"duration_ms": 1243,
"truncated": false
}Response — final:
{
"type": "final",
"content": "def is_prime(n): ...",
"tool_calls_executed": 2,
"conversation": [...]
}Response — dispatch a command:
{
"type": "dispatch",
"dispatch_id": "dispatch-uuid",
"action": "exec",
"command": "python",
"args": ["-m", "pytest", "test_prime.py"],
"cwd": "/workspace",
"env_additions": {},
"timeout_secs": 60,
"max_output_bytes": 524288
}Stimulus Ingestion
POST /v1/stimuli
Ingest a stimulus from an internal service or operator. Authenticated by Keycloak Bearer JWT.
Request:
{
"source": "http_api",
"content": "Deploy release v2.1.0 to production.",
"idempotency_key": "deploy-v2.1.0"
}| Field | Type | Required | Description |
|---|---|---|---|
source | string | ✓ | Source identifier. Use "http_api" or a custom source name. |
content | string | ✓ | Stimulus payload — natural language or JSON string. |
idempotency_key | string | — | Deduplication key. Scoped to (source, key) with 24-hour TTL. |
Response 200:
{
"stimulus_id": "stim-uuid",
"workflow_execution_id": "wfex-uuid"
}Errors:
| HTTP | Code | Cause |
|---|---|---|
409 | idempotent_duplicate | Already processed within TTL window |
422 | classification_failed | RouterAgent confidence below threshold |
422 | no_router_configured | No direct route and no RouterAgent |
500 | workflow_error | Workflow execution failed to start |
POST /v1/webhooks/{source}
Ingest a webhook from an external system. Authenticated by HMAC-SHA256.
Required headers:
| Header | Format | Description |
|---|---|---|
X-Aegis-Signature | sha256=<hex> | HMAC-SHA256 of the raw body using the source's shared secret |
X-Idempotency-Key | any string | Optional — enables duplicate delivery detection |
Body: Any content type. The raw body bytes are used for HMAC verification and forwarded as the stimulus content.
Response 200:
{
"stimulus_id": "stim-uuid",
"workflow_execution_id": "wfex-uuid"
}Errors:
| HTTP | Code | Cause |
|---|---|---|
401 | missing_signature | X-Aegis-Signature header absent |
401 | invalid_signature | HMAC digest mismatch |
401 | secret_not_found | AEGIS_WEBHOOK_SECRET_<SOURCE> not set |
400 | malformed_signature | Header not in sha256=<hex> format |
409 | idempotent_duplicate | Same delivery already processed |
422 | classification_failed | RouterAgent confidence below threshold |
Workflow Definitions and Executions
Workflow definition and execution management endpoints are available under /v1/workflows. The key response fields related to output schemas are documented below.
Workflow Definition Response Fields
When retrieving a workflow definition, the response includes the full manifest metadata:
| Field | Type | Description |
|---|---|---|
metadata.output_schema | object | JSON Schema declaring the workflow's output shape (if declared). |
metadata.output_template | map[string, string] | Handlebars expressions for extracting final output (if declared). |
These fields appear alongside existing metadata fields (name, version, input_schema, etc.).
Workflow Execution Response Fields
When retrieving a workflow execution (e.g. GET /v1/workflows/executions/{id}), the response includes:
| Field | Type | Description |
|---|---|---|
final_output | object | Structured output produced at workflow completion, if the workflow declares output_template. null when the workflow has no output template or has not yet completed. |
The final_output value is the rendered and type-coerced result of evaluating the workflow's output_template against the final Blackboard. It is also returned as last_output in aegis.workflow.wait tool responses.
Billing
All billing endpoints require a valid Keycloak Bearer JWT (Authorization: Bearer <token>). They return 501 Not Implemented if STRIPE_SECRET_KEY is not configured on the orchestrator.
GET /v1/billing/prices
List all available pricing tiers with their Stripe price IDs.
Response 200:
{
"tiers": [
{
"tier": "pro",
"product_id": "prod_xxx",
"name": "Pro",
"description": "For professionals and small teams",
"included_seats": 1,
"monthly": { "price_id": "price_xxx", "amount": 2900, "currency": "usd" },
"annual": { "price_id": "price_yyy", "amount": 29000, "currency": "usd" },
"seat_monthly": { "price_id": "price_seat_m", "amount": 1500, "currency": "usd" },
"seat_annual": { "price_id": "price_seat_a", "amount": 15000, "currency": "usd" }
}
]
}| Field | Type | Description |
|---|---|---|
tiers[].tier | string | Tier slug (pro, business, enterprise) |
tiers[].product_id | string | Stripe Product ID |
tiers[].name | string | Human-readable tier name |
tiers[].description | string | Tier description |
tiers[].included_seats | integer | Number of seats included in the base price |
tiers[].monthly | object or null | Monthly price (price_id, amount in cents, currency) |
tiers[].annual | object or null | Annual price |
tiers[].seat_monthly | object or null | Monthly per-seat price |
tiers[].seat_annual | object or null | Annual per-seat price |
POST /v1/billing/checkout
Create a Stripe Checkout Session for subscribing to a plan.
Request body:
{
"price_id": "price_xxx",
"seat_price_id": "price_seat_xxx",
"seats": 5
}| Field | Type | Required | Description |
|---|---|---|---|
price_id | string | Yes | Stripe Price ID from GET /v1/billing/prices |
seat_price_id | string | No | Stripe Price ID for per-seat billing |
seats | integer | No | Number of additional seats |
Response 200:
{
"url": "https://checkout.stripe.com/c/pay/cs_live_..."
}Redirect the user's browser to the returned url to complete payment.
POST /v1/billing/portal
Create a Stripe Customer Portal session for managing payment methods, viewing invoices, and cancelling subscriptions.
Response 200:
{
"url": "https://billing.stripe.com/p/session/..."
}GET /v1/billing/subscription
Get the current user's subscription details.
Response 200:
{
"tier": "pro",
"status": "active",
"current_period_end": "2026-05-15T00:00:00Z",
"cancel_at_period_end": false,
"stripe_customer_id": "cus_..."
}| Field | Type | Description |
|---|---|---|
tier | string | Current subscription tier (free, pro, business, enterprise) |
status | string | Stripe subscription status (active, past_due, canceled, trialing, etc.) |
current_period_end | string (ISO 8601) | End of the current billing period |
cancel_at_period_end | boolean | Whether the subscription will cancel at period end |
stripe_customer_id | string | The Stripe Customer ID associated with this user |
GET /v1/billing/invoices
List invoices for the current user.
Response 200:
{
"invoices": [
{
"id": "in_...",
"amount": 2900,
"currency": "usd",
"status": "paid",
"created": "2026-04-01T00:00:00Z",
"pdf_url": "https://pay.stripe.com/invoice/..."
}
]
}| Field | Type | Description |
|---|---|---|
id | string | Stripe Invoice ID |
amount | integer | Invoice amount in the smallest currency unit (e.g., cents) |
currency | string | Three-letter ISO currency code |
status | string | Invoice status (draft, open, paid, void, uncollectible) |
created | string (ISO 8601) | Invoice creation timestamp |
pdf_url | string | URL to download the invoice PDF |
Health
GET /health
Liveness probe. Returns 200 OK when the orchestrator is running.
Response 200:
{ "status": "ok" }See Also
- gRPC API Reference — Temporal-worker-facing streaming transport
- Configuring Webhooks — setting up HMAC secrets and routes
- Human Approvals — using the approval gate in workflows
- SEAL Architecture — signed tool invocation protocol