Docs / Admin API

Admin API Reference

REST API for managing proxies, consumers, plugins, and upstreams. Available in Database and Control Plane modes.

Authentication

All Admin API endpoints except /health, /status, and /metrics require a JWT in the Authorization: Bearer <token> header. Tokens are verified against your FERRUM_ADMIN_JWT_SECRET using HS256.

bash — generate JWT (example)
# Using jwt-cli (npm install -g jwt-cli)
jwt sign --secret "your-admin-jwt-secret" --expires 3600

# Or with curl + jq (generate manually)
# For production, use your auth service to issue admin tokens
bash — example request with auth
curl -H "Authorization: Bearer <your-jwt-token>" \
     http://localhost:9000/proxies
ℹ️
In file mode (or when read-only mode is enabled), the Admin API is read-only. Write operations return 403 Forbidden. Use Database or Control Plane mode for dynamic configuration management.

Unauthenticated Endpoints

MethodPathDescriptionUse for
GET /health Basic liveness check. Returns 200 if the process is running. Kubernetes livenessProbe
GET /status Readiness check (alias for /health). Returns 200 when config is loaded. Kubernetes readinessProbe
GET /metrics Prometheus exposition format metrics. No auth required for scraping. Prometheus scrape target

API Endpoints

MethodPathDescription
GET/proxiesList all proxy configurations
POST/proxiesCreate a new proxy
GET/proxies/:idGet a specific proxy by ID
PUT/proxies/:idUpdate a proxy configuration
DELETE/proxies/:idDelete a proxy
GET/consumersList all consumers
POST/consumersCreate a new consumer
GET/consumers/:idGet a consumer by ID
PUT/consumers/:idUpdate a consumer
DELETE/consumers/:idDelete a consumer
PUT/consumers/:id/credentials/:typeUpdate consumer credentials for a given type
DELETE/consumers/:id/credentials/:typeDelete consumer credentials for a given type
GET/pluginsList available plugin types
GET/plugins/configList all plugin configurations
POST/plugins/configCreate a plugin config
GET/plugins/config/:idGet a plugin config by ID
PUT/plugins/config/:idUpdate a plugin config
DELETE/plugins/config/:idDelete a plugin config
GET/upstreamsList all upstream configurations
POST/upstreamsCreate an upstream
GET/upstreams/:idGet an upstream by ID
PUT/upstreams/:idUpdate an upstream
DELETE/upstreams/:idDelete an upstream
GET/admin/metricsComprehensive runtime metrics snapshot (JSON)
GET/backupExport full configuration as JSON
POST/restoreRestore configuration from JSON backup (destructive)
POST/batchBatch create multiple resources in one request

Request & Response Examples

Create a Proxy

bash
curl -X POST http://localhost:9000/proxies \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "listen_path": "/my-api",
    "backend_protocol": "http",
    "backend_host": "api-backend",
    "backend_port": 3000,
    "strip_listen_path": true,
    "plugin_config_ids": [
      "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
    ]
  }'
json — response
{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "listen_path": "/my-api",
  "backend_protocol": "http",
  "backend_host": "api-backend",
  "backend_port": 3000,
  "strip_listen_path": true,
  "plugin_config_ids": ["a1b2c3d4-e5f6-7890-abcd-ef1234567890"],
  "created_at": "2025-01-15T10:30:00Z",
  "updated_at": "2025-01-15T10:30:00Z"
}

Create a Consumer

bash
curl -X POST http://localhost:9000/consumers \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "username": "mobile-app",
    "custom_id": "app-v2",
    "credentials": {
      "key_auth": {
        "key": "sk-live-abc123def456"
      },
      "jwt_auth": {
        "subject": "mobile-app"
      }
    }
  }'

Create an Upstream

bash
curl -X POST http://localhost:9000/upstreams \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "api-backend-pool",
    "algorithm": "least_connections",
    "targets": [
      { "host": "api-1.internal", "port": 3000, "weight": 100 },
      { "host": "api-2.internal", "port": 3000, "weight": 100 },
      { "host": "api-3.internal", "port": 3000, "weight": 50 }
    ],
    "health_check": {
      "enabled": true,
      "type": "http",
      "path": "/health",
      "interval_seconds": 10,
      "timeout_seconds": 3,
      "healthy_threshold": 2,
      "unhealthy_threshold": 3
    }
  }'

Batch Operations

bash
curl -X POST http://localhost:9000/batch \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "operations": [
      { "method": "POST", "path": "/proxies", "body": { "name": "proxy-a", ... } },
      { "method": "POST", "path": "/consumers", "body": { "username": "consumer-1", ... } },
      { "method": "PUT", "path": "/upstreams/upstr_123", "body": { ... } }
    ]
  }'

Error Handling

HTTP StatusMeaningCommon Cause
400Bad RequestInvalid JSON, missing required fields, validation error
401UnauthorizedMissing or invalid JWT token
403ForbiddenAdmin API is in read-only mode (file mode or read-only flag enabled)
404Not FoundResource with specified ID doesn't exist
409ConflictResource name already exists
500Internal Server ErrorDatabase error, unexpected failure
json — error response format
{
  "error": "Field 'listen_path' is required"
}
Custom Plugins Guide → Architecture