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

SurfaceBase URL
Local boundaryhttp://127.0.0.1:7714
Local API serverhttp://127.0.0.1:8080
OpenAI-compatible proxyhttp://127.0.0.1:9090/v1

Public Route Families

FamilyRoutes
HealthGET /api/health
Demo proofPOST /api/demo/run, POST /api/demo/verify, POST /api/demo/tamper
EvaluatePOST /api/v1/evaluate
ReceiptsGET /api/v1/receipts, GET /api/v1/receipts/tail, GET /api/v1/receipts/{receipt_id}
EvidencePOST /api/v1/evidence/export, POST /api/v1/evidence/verify
BoundaryGET /api/v1/boundary/status
ConformanceGET /api/v1/conformance/negative
MCP approvalsGET /api/v1/mcp/registry, POST /api/v1/mcp/scan, POST /api/v1/mcp/authorize-call
OpenAI proxyPOST /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

ClassBehavior
publicNo runtime admin credential required
tenant_scopedRequires Authorization: Bearer $HELM_ADMIN_API_KEY and matching tenant/principal context
admin / authenticatedRequires Authorization: Bearer $HELM_ADMIN_API_KEY
service_internalRequires 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:

HeaderMeaning
X-Helm-Decision-IDBoundary decision id
X-Helm-Receipt-IDReceipt id
X-Helm-Reason-CodeReason code
X-Helm-StatusBoundary status
X-Helm-Output-HashHash 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.