API reference
The control plane serves REST on :8080. Every /v1/ endpoint takes a Bearer token: a dashboard JWT or an API key.
The dashboard, CLI and SDKs all call this API. Use this page to call it with curl. The SDKs wrap the same endpoints in typed methods. This page covers the core resources; the full route list is in services/control-plane/cmd/server/main.go.
Authentication
Section titled “Authentication”Pass your API key in the Authorization header on every request:
Authorization: Bearer hlx_live_your_api_key_hereCreate keys under Settings > API Keys. Keys start with hlx_live_ and carry scopes (read, write, admin, or fine-grained ones such as agents:write and runs:execute). Scope enforcement is off by default; set LANTERN_AUTHZ_ENFORCE=1 and a key missing the required scope gets 403.
Accounts
Section titled “Accounts”Sign-up, login, email verification, password reset, data export and workspace deletion (/auth/* and /v1/tenants/{id}) are documented on Accounts.
Agents
Section titled “Agents”List agents
Section titled “List agents”GET /v1/agents
Response: 200 OK — bare array[ { "name": "research-agent", "currentVersionId": "v1", "labels": {}, "createdAt": "2026-04-10T12:00:00Z" }]Get agent
Section titled “Get agent”GET /v1/agents/{name}
Response: 200 OK{ "name": "research-agent", "currentVersionId": "v1", "manifest": { "systemPrompt": "You are a research assistant...", "model": "auto" }, "labels": {}, "createdAt": "2026-04-10T12:00:00Z"}Create agent
Section titled “Create agent”POST /v1/agentsContent-Type: application/json
{ "name": "my-agent", "manifest": { "systemPrompt": "You are a helpful assistant...", "model": "auto" }}
Response: 201 Created{ "name": "my-agent" }Delete agent
Section titled “Delete agent”DELETE /v1/agents/{name}
Response: 204 No Content
PATCH /v1/agents/{name} — updateCreate a run
Section titled “Create a run”POST /v1/runsContent-Type: application/json
{ "agentName": "research-agent", "input": { "topic": "quantum computing" }}
Response: 201 Created{ "id": "550e8400-e29b-41d4-a716-446655440000", "agentName": "research-agent", "status": "queued", "input": { "topic": "quantum computing" }, "createdAt": "2026-04-12T10:00:00Z"}Get run
Section titled “Get run”GET /v1/runs/{id}
Response: 200 OK{ "id": "550e8400-...", "agentName": "research-agent", "status": "succeeded", "input": { "topic": "quantum computing" }, "output": { "summary": "..." }, "tokensIn": 820, "tokensOut": 2100, "costUsd": 0.0042, "createdAt": "2026-04-12T10:00:00Z", "updatedAt": "2026-04-12T10:00:08Z"}Run status values: queued, running, succeeded, failed, waiting, cancelled.
List runs
Section titled “List runs”GET /v1/runs?limit=20&agentName=research-agent
Response: 200 OK — bare array[ { "id": "...", "agentName": "...", "status": "succeeded", ... }]Stream run events (SSE)
Section titled “Stream run events (SSE)”GET /v1/runs/{id}/eventsAccept: text/event-stream
Response: Server-Sent EventsThe event name is the journal kind; data is JSON.
event: step_starteddata: {"seq":1,"kind":"step_started","stepId":"plan","runId":"550e...","at":"2026-04-12T10:00:01Z","payload":{}}
event: step_completeddata: {"seq":2,"kind":"step_completed","stepId":"plan","runId":"550e...","at":"2026-04-12T10:00:03Z","payload":{"output":"..."}}
event: step_starteddata: {"seq":3,"kind":"step_started","stepId":"search-0","runId":"550e...","at":"2026-04-12T10:00:03Z","payload":{}}
event: step_completeddata: {"seq":4,"kind":"step_completed","stepId":"search-0","runId":"550e...","at":"2026-04-12T10:00:06Z","payload":{"output":"..."}}
: heartbeatPossible event kinds on a run stream:
step_started: a step began executing.step_completed: a step finished with output.step_failed: a step errored; payload haserror.step_retrying: transient failure, will retry.step_waiting: waiting for human approval.confidence_evaluated: confidence gate scored a step.anomaly_detected: runtime anomaly reported by the harness.
Other run endpoints
Section titled “Other run endpoints”POST /v1/runs/{id}/cancel — cancel a runDELETE /v1/runs/{id} — delete a runPOST /v1/runs/{id}/receipt — issue a signed receiptPOST /v1/runs/{id}/feedback — score 1-5, optional commentForecast cost before running
Section titled “Forecast cost before running”POST /v1/runs/forecastContent-Type: application/json
{ "agentName": "research-agent", "input": { "topic": "..." } }
Response: 200 OK{ "estimatedTokensIn": 800, "estimatedTokensOut": 2000, "estimatedCostUsd": 0.004, "confidence": 0.82, "wouldExceedBudget": false}Sessions
Section titled “Sessions”Sessions are interactive multi-turn conversations. Send messages and stream the reply as it generates.
Create session
Section titled “Create session”POST /v1/sessionsContent-Type: application/json
{ "agentName": "my-agent" }
Response: 201 Created{ "id": "sess-uuid", "agentName": "my-agent", "status": "active", "createdAt": "..." }Send a message
Section titled “Send a message”POST /v1/sessions/{id}/messagesContent-Type: application/json
{ "content": "What is the capital of France?" }
Response: 200 OK{ "turnId": "turn-uuid", "text": "Paris.", "tokensIn": 12, "tokensOut": 4, "costUsd": 0.00001 }Stream session events
Section titled “Stream session events”GET /v1/sessions/{id}/eventsAccept: text/event-stream
event: message_deltadata: {"sessionId":"...","turnId":"...","seq":1,"delta":"Par"}
event: message_deltadata: {"sessionId":"...","turnId":"...","seq":2,"delta":"is."}
event: message_completeddata: {"turnId":"...","text":"Paris.","usage":{"tokensIn":12,"tokensOut":4,"costUsd":0.00001}}
A failed turn emits message_error.Other session endpoints
Section titled “Other session endpoints”GET /v1/sessions — list (bare array)GET /v1/sessions/{id} — getPOST /v1/sessions/{id}/stop — stop a running sessionDELETE /v1/sessions/{id} — delete sessionConnectors
Section titled “Connectors”Install a connector
Section titled “Install a connector”POST /v1/connectors/installContent-Type: application/json
{ "connectorId": "gmail", "config": { "userEmail": "you@example.com" }}
Response: 201 Created{ "connectorId": "gmail", "status": "installed" }List connectors
Section titled “List connectors”GET /v1/connectors
Response: 200 OK — bare array[ { "connectorId": "gmail", "status": "installed", "installedAt": "..." }]Execute a connector action
Section titled “Execute a connector action”POST /v1/connectors/{connectorId}/execute?action=send_emailContent-Type: application/json
{ "to": "friend@example.com", "subject": "Hello", "body": "..." }
Response: 200 OK{ "result": { "messageId": "..." } }Other connector endpoints
Section titled “Other connector endpoints”POST /v1/connectors/{id}/test — test connectionDELETE /v1/connectors/{id} — uninstallSchedules
Section titled “Schedules”Schedules trigger agent runs on a cron expression. They are a separate resource from agents: one agent can have multiple schedules.
Create schedule
Section titled “Create schedule”POST /v1/schedulesContent-Type: application/json
{ "agentName": "research-agent", "cronExpr": "0 9 * * 1-5", "timezone": "America/New_York", "config": { "input": { "mode": "daily-digest" } }, "enabled": true}
Response: 201 Created{ "id": "sched-uuid", "agentName": "research-agent", "cronExpr": "0 9 * * 1-5", ... }Other schedule endpoints
Section titled “Other schedule endpoints”GET /v1/schedules — list (bare array)PUT /v1/schedules/{id} — updateDELETE /v1/schedules/{id} — deleteTriggers
Section titled “Triggers”Inbound webhook triggers start a run of one agent when GitHub, Sentry, PagerDuty or a signed generic sender posts to a public URL. Setup, signatures and status codes are on Webhook triggers.
POST /v1/agents/{name}/triggers — create {provider, secret?, inputTemplate?}; 201, secret shown onceGET /v1/agents/{name}/triggers — list (bare array, no secrets)GET /v1/triggers/{id} — getPATCH /v1/triggers/{id} — {enabled?, secret?, inputTemplate?}DELETE /v1/triggers/{id} — 204POST /v1/hooks/{id} — public receiver, authenticated by HMAC signature, not a tokenLLM providers
Section titled “LLM providers”POST /v1/settings/llm-providersContent-Type: application/json
{ "provider": "anthropic", "apiKey": "sk-ant-..." }
Response: 200 OK{ "provider": "anthropic", "configured": true }
GET /v1/settings/llm-providers — list configured providers (bare array)POST /v1/settings/llm-providers/{provider}/test — test the keyErrors
Section titled “Errors”Errors use a flat JSON body:
// Most errors{ "error": "agent 'my-agent' not found" }
// Validation errors (may include field detail){ "error": "missing required field: agentName" }Common HTTP status codes:
400: bad request or validation failure.401: missing or invalid API key.403: insufficient scope or cross-tenant access.404: resource not found.402: budget exceeded (hard-fail policy).500: internal error.