Hanzo AI

Gateway

Live control of the policy your API applies to every incoming request: CORS, rate limits, cache TTL and allowed methods, changed without a redeploy.

Also for this capability: API · CLI · MCP · SDKs

Live control of the policy your API applies to every incoming request: CORS, rate limits, cache TTL and allowed methods, changed without a redeploy.

Base URLhttps://api.hanzo.ai
Operations3
AuthAuthorization: Bearer $HANZO_API_KEY

Specification

HIP-1127 · Gateway — Live Edge Policy — Draft · read the specification →

/v1/gateway is live control of the policy the API applies to every incoming request — CORS, rate limits, cache TTL, allowed methods — changed without a redeploy. The gateway itself is plumbing: the trust boundary that validates the IAM JWT, strips client-supplied identity and re-mints the org header, compiled into the cloud binary rather than deployed as a network hop (apps/gateway/gateway.go:5-9). Plumbing earns no prefix; what earns this one is the thing a customer actually calls, the runtime config plane, implemented in hanzoai/cloud at apps/gateway.

Motivation

The edge knobs used to be baked into an image, so retuning a CORS allowlist or a flood cap was a rebuild and a rollout — the slowest possible response to the fastest-moving class of problem. The config plane serves GET/PUT over the same store the edge middleware reads live (apps/gateway/gateway.go:11-16), so a change is effective on the next request.

Specification

The key words MUST, MUST NOT, SHOULD, SHOULD NOT and MAY are to be interpreted as in RFC 2119.

§1 The store is shared, not owned

The policy store is owned by the composition root (deps.GatewayPolicy) and shared with the enforcement middleware; this subsystem opens nothing and closes nothing (apps/gateway/gateway.go:37-40, gateway.go:80-82). One store, one source of truth: the row an operator writes here is the row the edge evaluates, with no propagation step to fail. Per-project rate scoping is deliberately not here — it stays the commerce-configured domain of the scoped limiter.

§2 The addresses

Three typed operations, the whole surface (apps/gateway/gateway.go:104-110, manifest/apps.go:365): GET /v1/gateway/config, PUT /v1/gateway/config, and GET /v1/gateway/traffic, which reports who is calling the org's API right now.

§3 Two scopes, and the one field that crosses them

Policy splits on whether a tenant exists at evaluation time (apps/gateway/gateway.go:18-35):

  1. Platform policy — CORS origins, the pre-auth per-IP cap and window — is evaluated before any tenant is known and MUST be writable only by a SuperAdmin. A PUT carrying any platform field routes to the platform row explicitly, so it lands correctly even when the SuperAdmin is org-switched.
  2. Per-org policy — the authenticated rate ceiling, cache TTL and paths, the accepted-method allowlist — is a tenant's own self-service row. An org admin writes its own, with the org from the validated principal (apps/gateway/gateway.go:122, HIP-0026), never a raw header; a SuperAdmin MAY target any tenant by query.
  3. Mode — the abuse gate's posture — lives on a tenant's row but is NOT self-service: a control's subject may not switch the control off, so writing it requires SuperAdmin whichever row it lands on. It is the one field whose scope and whose authority are different questions.

§4 Money, events, telemetry

gateway is free, in those words (plugin/gateway/main.go:21, cloud.Free; not in spend.go:275). It publishes no events on the bus, and emits nothing to observability beyond the request span every route gets — the traffic operation is a read of the edge's live counters, not an emission.

§5 Stage

gateway is ga: the platform core's edge, part of the agentic OS.

§6 Upstream

gateway derives from none. hanzoai/gateway is the Hanzo repository the trust boundary lives in, and its own routing law — one routing source of truth, cloud's mount table, never a second map — is why this capability is a config plane and not a router (apps/gateway/gateway.go:8-10).

Rationale

One shared store read live, rather than a config service the edge polls, means there is no window in which the operator's view and the enforced policy disagree — the alternative's failure mode is precisely the one an abuse response cannot afford. Splitting authority by evaluation time, rather than by field list alone, gives the rule a reason the next field can be tested against: if no tenant exists when the knob is evaluated, no tenant may turn it.

Security Considerations

This surface configures the defenses, so the wrong implementation disarms them. The three failure shapes are each closed by a scope rule: a tenant widening platform CORS or the pre-auth flood cap (platform fields are SuperAdmin-only), a tenant raising another tenant's ceiling (the org comes from the validated principal, and cross-org targeting requires SuperAdmin), and an abuser switching off their own abuse gate (mode requires SuperAdmin on any row). The store being deps-owned also means a compromised subsystem cannot substitute a second policy source — there is nothing here to swap.

Four surfaces

SurfaceReaches this capability asCoverage
RESTgateway at its own prefix3 operations
CLIhanzo gateway …3 of 3
SDKGatewayApi in every published client3 methods
MCPtool gateway on https://api.hanzo.ai/v1/mcp3 operations, 2 under the document's own id — ask describe for the rest

Quickstart

export HANZO_API_KEY=sk-...   # console.hanzo.ai → API keys

Then the first call — a read that needs nothing but the key. GET /v1/gateway/config, operation get_gateway_config:

hanzo gateway config get

Answers 200 with object — ok.

Endpoints

EndpointWhat it does
GET /v1/gateway/configRead returns the EFFECTIVE edge policy the caller is subject to: the platform CORS allowlist and pre-auth per-IP flood cap in force, plus the…
PUT /v1/gateway/configWrite updates one policy scope and returns the policy in force after the write.
GET /v1/gateway/trafficReport who is calling this org's API right now

All Hanzo APIs · Interactive reference

How is this guide?