HTTP API
August 11, 2026 ยท View on GitHub
The public HTTP surface is for local proof, boundary evaluation, receipts, evidence export, conformance checks, MCP authorization, and the OpenAI-compatible proxy.
Use the CLI first. Use HTTP when you need a local client or generated types.
Base URLs
| Surface | Base URL |
|---|---|
| Local boundary | http://127.0.0.1:7714 |
| Local API server | http://127.0.0.1:8080 |
| OpenAI-compatible proxy | http://127.0.0.1:9090/v1 |
Public Route Families
| Family | Routes |
|---|---|
| Health | GET /api/health |
| Demo proof | POST /api/demo/run, POST /api/demo/verify, POST /api/demo/tamper |
| Evaluate | POST /api/v1/evaluate |
| Receipts | GET /api/v1/receipts, GET /api/v1/receipts/tail, GET /api/v1/receipts/{receipt_id} |
| Evidence | POST /api/v1/evidence/export, POST /api/v1/evidence/verify |
| Boundary | GET /api/v1/boundary/status |
| Conformance | GET /api/v1/conformance/negative |
| MCP approvals | GET /api/v1/mcp/registry, POST /api/v1/mcp/scan, POST /api/v1/mcp/authorize-call |
| OpenAI proxy | POST /v1/chat/completions |
Protected runtime, identity, trust-key mutation, billing, console diagnostics, direct MCP execution, onboarding, and unpublished operations are not part of the public docs surface.
Auth Classes
| Class | Behavior |
|---|---|
public | No runtime admin credential required |
tenant_scoped | Requires Authorization: Bearer $HELM_ADMIN_API_KEY and matching tenant/principal context |
admin / authenticated | Requires Authorization: Bearer $HELM_ADMIN_API_KEY |
service_internal | Requires Authorization: Bearer $HELM_SERVICE_API_KEY |
When HELM_EMERGENCY_STOP_FENCE_ENABLED=1, POST /api/v1/evaluate
additionally requires an authenticated tenant matching the server-owned
HELM_RUNTIME_TENANT_ID and X-Helm-Workspace-ID matching the server-owned
HELM_RUNTIME_WORKSPACE_ID. A request body cannot choose either scope
binding. This is a dispatch fence only; it does not cancel already running
work.
The unauthenticated OpenAI-compatible proxy (POST /v1/chat/completions) is
unavailable while this fence is enabled because request JSON is not an
authoritative tenant/workspace binding.
Receipt Headers
Some routes return HELM decision metadata:
| Header | Meaning |
|---|---|
X-Helm-Decision-ID | Boundary decision id |
X-Helm-Receipt-ID | Receipt id |
X-Helm-Reason-Code | Reason code |
X-Helm-Status | Boundary status |
X-Helm-Output-Hash | Hash binding governed output |
If a client hides headers, inspect receipts through the CLI or receipt routes.
OpenAPI
Generate clients from:
api/openapi/helm.openapi.yaml
Validate route drift locally:
cd core
go test ./cmd/helm-ai-kernel -run 'Test.*Route|Test.*OpenAPI|Test.*Receipt|Test.*Boundary' -count=1
v0.8 client migration (source target)
First-party SDKs now send a canonical EvaluateRequest: non-blank top-level
tool, effect_level, and session_id. The runtime records the authenticated
principal; request-body principal and agent_id do not establish identity.
Direct-daemon callers may temporarily retain the legacy action/resource
shape only when context.session_id is non-blank. That compatibility path is
not an SDK contract. Migrate SDK clients to the canonical request and typed
EvaluateResponse before relying on the v0.8 release target.
Do not mix the two forms with different values. If canonical and legacy aliases
are both present, tool/action, effect_level/resource, and top-level
session_id/context.session_id must match after trimming. The runtime rejects
conflicts before policy evaluation or receipt issuance.
Request context is not an identity or scope authority. The daemon removes
caller-supplied principal, tenant, and workspace authority spellings before
Guardian evaluation, then adds only the canonical values bound by the
authenticated request. Other context fields are preserved.
Receipt reads are tenant-scoped. Prefer session_id; legacy agent is an
alias for that signed session ID and is never an executor filter. A session
listing accepts since=lamport:<n>. A tenant-wide listing must continue with
the opaque v1.<base64url> next_cursor (or SSE event ID), because scalar
Lamport clocks can collide across signed sessions.