HTTP API
The control-plane endpoints and the reconciliation-friendly conventions behind them.
The server exposes a small HTTP API under /api. Tunnel mutations follow
reconciliation-friendly conventions so the API is safe to drive from retrying clients and
IaC tooling.
Tunnel endpoints
| Method & path | Purpose |
|---|---|
PUT /api/tunnels/{slug} | Create or update a tunnel (idempotent upsert). |
GET /api/tunnels/{slug} | Read a single tunnel. |
GET /api/tunnels/ | List the caller's tunnels. |
DELETE /api/tunnels/{slug} | Remove a tunnel (idempotent). |
POST /api/tunnels/{slug}:rotate-connection-token | Issue a fresh connection token, invalidating the previous one. |
Supporting endpoints include GET /api/meta (build info), POST /api/keys (issue an API
key — OIDC only), and health probes at /health/live and /health/ready.
Protocol & L4 port pool
A tunnel carries a protocol (http, tcp, udp). HTTP tunnels are keyed by slug;
TCP/UDP tunnels reserve a remote port from a server-managed pool and are keyed by a
derived name (tcp-<port> / udp-<port>). The pool and HTTP-slug namespace also back the
CLI's availability helpers — ports (range / check / pick) and
slugs check.
Conventions
- Idempotent upsert —
PUTcarries the full desired spec; sending the same body twice yields the same state. Responses include achangedflag so callers can tell created from updated from no-op. - Spec / status / metadata split — responses separate the user-controlled
spec, the server-observedstatus, andmetadata(slug, timestamps, etag). - ETags &
If-Match— optimistic concurrency: clients may gate writes on anETag. The etag is computed from the spec only, so status changes don't invalidate it. - Idempotent delete —
DELETEreturns success whether or not the tunnel existed; the desired end-state ("absent") is reached either way.
PUT /api/tunnels/myapp
Content-Type: application/json
{ "targetPort": 8080, "enabled": true }Authentication
All /api/tunnels endpoints require a valid OIDC bearer token or an API key with the
appropriate permission. See Authentication.
The internal FRP plugin endpoint (/api/internal/frp) is not part of the public surface
and is protected by a separate shared-secret scheme used only by the trusted edge.