{"openapi":"3.1.0","info":{"title":"Ferrogate Admin API","description":"Control plane for the Ferrogate API gateway: probes, metrics, config, upstream health and hot reload. When admin.auth_token is configured, every /api/v1 endpoint requires it as a bearer token.","license":{"name":"Apache-2.0"},"version":"0.3.0"},"paths":{"/api/v1/api-keys":{"get":{"tags":["gateway"],"summary":"API key inventory (metadata only — digests are never exposed).","operationId":"api_keys","responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ApiKeySummary"}}}}}}}},"/api/v1/apis":{"get":{"tags":["registration"],"summary":"List all registered APIs.","operationId":"list_apis","responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RegisteredApiSummary"}}}}},"501":{"description":"Registration disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_token":[]}]}},"/api/v1/apis/{id}":{"put":{"tags":["registration"],"summary":"Register or update an API. The body is a registration (upstreams + routes);\nthe `{id}` path segment is authoritative and overrides any `id` in the body.\nThe combined config is validated before the registration is persisted — an\ninvalid registration is rejected with 422 and nothing is written.","operationId":"register_api","parameters":[{"name":"id","in":"path","description":"API id ([a-z0-9-_], 1-64 chars)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterResponse"}}}},"401":{"description":"Missing/invalid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"422":{"description":"Registration invalid; nothing written","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"501":{"description":"Registration disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_token":[]}]},"delete":{"tags":["registration"],"summary":"Remove a registered API.","operationId":"unregister_api","parameters":[{"name":"id","in":"path","description":"API id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterResponse"}}}},"404":{"description":"No such registration","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"501":{"description":"Registration disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_token":[]}]}},"/api/v1/catalog":{"get":{"tags":["catalog"],"summary":"Discover registered APIs. Supports `q` (free text over id/title/description/\ntags), `tag`, `team`, and `visibility` filters. This is the machine-facing\nsearch an AI agent uses to find APIs to call.","operationId":"list_catalog","parameters":[{"name":"q","in":"query","description":"free-text search","required":false,"schema":{"type":"string"}},{"name":"tag","in":"query","description":"filter by tag","required":false,"schema":{"type":"string"}},{"name":"team","in":"query","description":"filter by owning team","required":false,"schema":{"type":"string"}},{"name":"visibility","in":"query","description":"internal | public","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CatalogEntry"}}}}},"501":{"description":"Catalog disabled (no registrations_dir)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_token":[]}]}},"/api/v1/config":{"get":{"tags":["gateway"],"summary":"Effective configuration with secrets redacted.","operationId":"get_config","responses":{"200":{"description":"Redacted effective configuration (JSON)"}}}},"/api/v1/info":{"get":{"tags":["gateway"],"summary":"Gateway build/runtime information.","operationId":"info","responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InfoResponse"}}}}}}},"/api/v1/reload":{"post":{"tags":["gateway"],"summary":"Hot-reload configuration from disk. Requires the admin bearer token.","operationId":"reload","responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReloadResponse"}}}},"401":{"description":"Missing/invalid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Mutations disabled (no token configured)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"422":{"description":"New config is invalid; old config kept","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_token":[]}]}},"/api/v1/routes":{"get":{"tags":["gateway"],"summary":"Configured routes in matching-priority order.","operationId":"routes","responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RouteSummary"}}}}}}}},"/api/v1/upgrade":{"post":{"tags":["gateway"],"summary":"Zero-downtime over-the-air upgrade: stage a digest-verified binary and\nhand traffic over to it. Requires the admin role AND\n`admin.upgrades_enabled: true` (fail-closed — enabling it makes the admin\ntoken equivalent to code execution on this host).","operationId":"upgrade","responses":{"202":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpgradeResponse"}}}},"403":{"description":""},"409":{"description":""},"422":{"description":""}}}},"/api/v1/upstreams":{"get":{"tags":["gateway"],"summary":"Upstream pools with per-target health and circuit-breaker state.","operationId":"upstreams","responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/UpstreamSummary"}}}}}}}},"/healthz":{"get":{"tags":["probes"],"summary":"Liveness probe.","operationId":"healthz","responses":{"200":{"description":"Process is alive"}}}},"/readyz":{"get":{"tags":["probes"],"summary":"Readiness probe — 503 until listeners are up, and during shutdown.","operationId":"readyz","responses":{"200":{"description":"Ready to receive traffic"},"503":{"description":"Not ready","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}}},"components":{"schemas":{"ApiKeySummary":{"type":"object","required":["id","enabled"],"properties":{"enabled":{"type":"boolean"},"id":{"type":"string"},"owner":{"type":["string","null"]}}},"CatalogEntry":{"type":"object","description":"A discoverable listing in the catalog / Store — either a native gateway API\n(`kind: \"api\"`) or a federated governed agent (`kind: \"agent\"`).","required":["id","title","kind","tags","visibility","paths","methods","auth"],"properties":{"auth":{"type":"array","items":{"type":"string"},"description":"Auth types required across the API's routes (none/jwt/api_key)."},"description":{"type":["string","null"]},"docs_url":{"type":["string","null"]},"governance":{"type":["string","null"],"description":"Governance regime enforcing this listing (`reins` for federated agents).\nAbsent on native APIs — they carry only coarse per-route edge auth."},"id":{"type":"string"},"kind":{"type":"string","description":"Listing kind: `api` for native gateway APIs, `agent` for federated\ngoverned agents."},"methods":{"type":"array","items":{"type":"string"},"description":"Union of HTTP methods across the API's routes (empty = any)."},"owner":{"type":["string","null"]},"paths":{"type":"array","items":{"type":"string"},"description":"Route match patterns this API exposes at the gateway edge."},"required_scopes":{"type":"array","items":{"type":"string"},"description":"Scopes a caller must hold to invoke a governed agent. Empty for native\nAPIs."},"skills":{"type":"array","items":{"$ref":"#/components/schemas/CatalogSkill"},"description":"Skills a governed agent exposes. Empty for native APIs."},"tags":{"type":"array","items":{"type":"string"}},"team":{"type":["string","null"]},"title":{"type":"string"},"upstream_auth":{"type":["string","null"],"description":"Upstream credential model: `none` = reachable with just a Ferrogate key;\n`apikey`/`oauth`/`varies` = bring-your-own-key (upstream needs the\nconsumer's own credential, which Ferrogate injects)."},"visibility":{"type":"string"}}},"CatalogSkill":{"type":"object","description":"A skill a governed agent exposes (projected from a Reins AgentCard intent).","required":["name","mutating"],"properties":{"description":{"type":["string","null"]},"mutating":{"type":"boolean","description":"Whether invoking the skill mutates state (write/side-effecting)."},"name":{"type":"string"}}},"InfoResponse":{"type":"object","required":["name","version","uptime_secs","config_generation","routes","upstreams","ready","pid"],"properties":{"config_generation":{"type":"integer","format":"int64","description":"Monotonic config generation (increments on every successful reload).","minimum":0},"name":{"type":"string","description":"Product name."},"pid":{"type":"integer","format":"int32","description":"Process id — changes across a zero-downtime upgrade handover.","minimum":0},"ready":{"type":"boolean"},"routes":{"type":"integer","minimum":0},"upstreams":{"type":"integer","minimum":0},"uptime_secs":{"type":"integer","format":"int64","description":"Seconds since process start.","minimum":0},"version":{"type":"string"}}},"ProblemDetails":{"type":"object","description":"RFC 9457 problem details, the error envelope for all admin endpoints.","required":["title","status","detail"],"properties":{"detail":{"type":"string"},"status":{"type":"integer","format":"int32","minimum":0},"title":{"type":"string"}}},"RegisterResponse":{"type":"object","required":["id","generation","message"],"properties":{"generation":{"type":"integer","format":"int64","minimum":0},"id":{"type":"string"},"message":{"type":"string"}}},"RegisteredApiSummary":{"type":"object","description":"A self-service API registration as surfaced by `GET /api/v1/apis`.","required":["id","upstreams","routes"],"properties":{"description":{"type":["string","null"]},"id":{"type":"string"},"owner":{"type":["string","null"]},"routes":{"type":"integer","minimum":0},"upstreams":{"type":"integer","minimum":0}}},"ReloadResponse":{"type":"object","required":["generation","message"],"properties":{"generation":{"type":"integer","format":"int64","minimum":0},"message":{"type":"string"}}},"RouteSummary":{"type":"object","required":["id","methods","hosts","upstream","auth","rate_limited","cors"],"properties":{"auth":{"type":"string"},"cors":{"type":"boolean"},"hosts":{"type":"array","items":{"type":"string"}},"id":{"type":"string"},"methods":{"type":"array","items":{"type":"string"}},"path":{"type":["string","null"]},"prefix":{"type":["string","null"]},"rate_limited":{"type":"boolean"},"upstream":{"type":"string"}}},"TargetSummary":{"type":"object","required":["url","weight","healthy","active_connections"],"properties":{"active_connections":{"type":"integer","minimum":0},"healthy":{"type":"boolean"},"url":{"type":"string"},"weight":{"type":"integer","format":"int32","minimum":0}}},"UpgradeResponse":{"type":"object","description":"Response for an accepted zero-downtime upgrade.","required":["staged_sha256","source","message"],"properties":{"message":{"type":"string"},"source":{"type":"string","description":"Where the binary came from (release/url/path)."},"staged_sha256":{"type":"string","description":"SHA-256 of the staged binary (verified before acceptance)."}}},"UpstreamSummary":{"type":"object","required":["name","load_balancer","circuit_breaker","healthy_targets","targets"],"properties":{"circuit_breaker":{"type":"string"},"healthy_targets":{"type":"integer","minimum":0},"load_balancer":{"type":"string"},"name":{"type":"string"},"targets":{"type":"array","items":{"$ref":"#/components/schemas/TargetSummary"}}}}},"securitySchemes":{"bearer_token":{"type":"http","scheme":"bearer"}}}}