Edge Proxy Admin API

v0.1.0
Base URL
http://localhost:8081Default local admin listener

The authenticated HTTP control plane for Edge Proxy runtime configuration.

The HTTP service forwards each request to the internal gRPC control plane. Successful mutations are persisted and published atomically. Authentication is enabled by default and uses the ADMIN_API_TOKEN bearer token.

This document describes the behavior registered in cmd/admin-api/main.go. The project is pre-alpha; do not expose the admin listener to an untrusted network or use real credentials in examples.

Authentication

bearerAuthhttp

Value of ADMIN_API_TOKEN; authentication is enabled by default.

Scheme: bearer

Backends

Manage upstream backend definitions and inspect health state.

List backends

GET
http://localhost:8081/api/backend

Returns all configured backends with their current runtime health state.

Source: Go handler.

Response

200OKArray<Backend>

Configured backends.

401Unauthorizedstring

Bearer authentication is enabled and the token is missing or invalid.

500Internal Server Errorstring

The gRPC control plane rejected the operation or the configuration could not be persisted.

Authorization

bearerAuthhttp (bearer)

Value of ADMIN_API_TOKEN; authentication is enabled by default.

List backends
curl -X GET 'http://localhost:8081/api/backend'
package main

import (
  "fmt"
  "io"
  "net/http"
)

func main() {
  req, _ := http.NewRequest("GET", "http://localhost:8081/api/backend", nil)
  resp, _ := http.DefaultClient.Do(req)
  defer resp.Body.Close()
  data, _ := io.ReadAll(resp.Body)
  fmt.Println(string(data))
}
const response = await fetch('http://localhost:8081/api/backend', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('http://localhost:8081/api/backend')
data = response.json()
[
  {
    "id": "backend-1",
    "url": "http://backend1:8080",
    "weight": 1,
    "enabled": true,
    "active": true,
    "error_count": 0
  }
]
Unauthorized
Failed to update backend: backend does not exist in config: backend-1

Add a backend

POST
http://localhost:8081/api/backend

Adds a uniquely identified HTTP or HTTPS backend and atomically publishes the new configuration.

Source: Go handler.

Body

application/json
idstringrequired
urlstring<uri>required
weightinteger<int32>>= 1required
enabledbooleanfalse

Response

200OKBasicResponse

The change was validated, persisted, and published.

400Bad Requeststring

The request body is not valid JSON or a required path value is missing.

401Unauthorizedstring

Bearer authentication is enabled and the token is missing or invalid.

413Payload Too Largestring

The request body exceeds the service-wide 1 MiB limit.

500Internal Server Errorstring

The gRPC control plane rejected the operation or the configuration could not be persisted.

Authorization

bearerAuthhttp (bearer)

Value of ADMIN_API_TOKEN; authentication is enabled by default.

Add a backend
curl -X POST 'http://localhost:8081/api/backend' \
  -H 'Content-Type: application/json' \
  -d '{
    "id": "backend-3",
    "url": "http://backend3:8080",
    "weight": 1,
    "enabled": true
  }'
package main

import (
  "fmt"
  "io"
  "net/http"
  "strings"
)

func main() {
  body := strings.NewReader(`{
    "id": "backend-3",
    "url": "http://backend3:8080",
    "weight": 1,
    "enabled": true
  }`)
  req, _ := http.NewRequest("POST", "http://localhost:8081/api/backend", body)
  req.Header.Set("Content-Type", "application/json")
  resp, _ := http.DefaultClient.Do(req)
  defer resp.Body.Close()
  data, _ := io.ReadAll(resp.Body)
  fmt.Println(string(data))
}
const response = await fetch('http://localhost:8081/api/backend', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "id": "backend-3",
      "url": "http://backend3:8080",
      "weight": 1,
      "enabled": true
    }),
});

const data = await response.json();
import requests

payload = {
  "id": "backend-3",
  "url": "http://backend3:8080",
  "weight": 1,
  "enabled": True
}

response = requests.post('http://localhost:8081/api/backend', json=payload)
data = response.json()
Request Body
{
  "id": "backend-3",
  "url": "http://backend3:8080",
  "weight": 1,
  "enabled": true
}
{
  "success": true,
  "message": "Configuration updated successfully"
}
Invalid request body: unexpected EOF
Unauthorized
string
Failed to update backend: backend does not exist in config: backend-1

Get a backend

GET
http://localhost:8081/api/backend/{id}

Returns the selected backend and its current runtime health state.

Source: Go handler.

Parameters

idstringrequiredpath

Stable backend identifier.

Response

200OKBackend

Current backend configuration and health state.

401Unauthorizedstring

Bearer authentication is enabled and the token is missing or invalid.

500Internal Server Errorstring

The gRPC control plane rejected the operation or the configuration could not be persisted.

Authorization

bearerAuthhttp (bearer)

Value of ADMIN_API_TOKEN; authentication is enabled by default.

Get a backend
curl -X GET 'http://localhost:8081/api/backend/{id}'
package main

import (
  "fmt"
  "io"
  "net/http"
)

func main() {
  req, _ := http.NewRequest("GET", "http://localhost:8081/api/backend/{id}", nil)
  resp, _ := http.DefaultClient.Do(req)
  defer resp.Body.Close()
  data, _ := io.ReadAll(resp.Body)
  fmt.Println(string(data))
}
const response = await fetch('http://localhost:8081/api/backend/{id}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('http://localhost:8081/api/backend/{id}')
data = response.json()
{
  "id": "string",
  "url": "https://example.com",
  "weight": 1,
  "enabled": true,
  "active": true,
  "error_count": 0,
  "last_error": "string"
}
Unauthorized
Failed to update backend: backend does not exist in config: backend-1

Update a backend

PUT
http://localhost:8081/api/backend/{id}

Replaces the mutable backend fields. The path id is authoritative; any id property in the JSON body is ignored. An omitted URL keeps the existing URL. Weight must be positive. Omitting enabled decodes it as false and therefore disables the backend.

Source: Go handler.

Body

application/json
idstring

Accepted by the decoder but replaced with the path id.

urlstring<uri>

Omit or send an empty string to preserve the existing URL.

weightinteger<int32>>= 1required
enabledbooleanfalse

Omission decodes as false and disables the backend.

Parameters

idstringrequiredpath

Stable backend identifier.

Response

200OKBasicResponse

The change was validated, persisted, and published.

400Bad Requeststring

The request body is not valid JSON or a required path value is missing.

401Unauthorizedstring

Bearer authentication is enabled and the token is missing or invalid.

413Payload Too Largestring

The request body exceeds the service-wide 1 MiB limit.

500Internal Server Errorstring

The gRPC control plane rejected the operation or the configuration could not be persisted.

Authorization

bearerAuthhttp (bearer)

Value of ADMIN_API_TOKEN; authentication is enabled by default.

Update a backend
curl -X PUT 'http://localhost:8081/api/backend/{id}' \
  -H 'Content-Type: application/json' \
  -d '{
    "url": "http://backend1:8080",
    "weight": 2,
    "enabled": true
  }'
package main

import (
  "fmt"
  "io"
  "net/http"
  "strings"
)

func main() {
  body := strings.NewReader(`{
    "url": "http://backend1:8080",
    "weight": 2,
    "enabled": true
  }`)
  req, _ := http.NewRequest("PUT", "http://localhost:8081/api/backend/{id}", body)
  req.Header.Set("Content-Type", "application/json")
  resp, _ := http.DefaultClient.Do(req)
  defer resp.Body.Close()
  data, _ := io.ReadAll(resp.Body)
  fmt.Println(string(data))
}
const response = await fetch('http://localhost:8081/api/backend/{id}', {
  method: 'PUT',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "url": "http://backend1:8080",
      "weight": 2,
      "enabled": true
    }),
});

const data = await response.json();
import requests

payload = {
  "url": "http://backend1:8080",
  "weight": 2,
  "enabled": True
}

response = requests.put('http://localhost:8081/api/backend/{id}', json=payload)
data = response.json()
Request Body
{
  "url": "http://backend1:8080",
  "weight": 2,
  "enabled": true
}
{
  "success": true,
  "message": "Configuration updated successfully"
}
Invalid request body: unexpected EOF
Unauthorized
string
Failed to update backend: backend does not exist in config: backend-1

Delete a backend

DELETE
http://localhost:8081/api/backend/{id}

Removes the backend and its references from virtual hosts and path routes, provided the resulting configuration remains valid.

Source: Go handler.

Parameters

idstringrequiredpath

Stable backend identifier.

Response

200OKBasicResponse

The change was validated, persisted, and published.

401Unauthorizedstring

Bearer authentication is enabled and the token is missing or invalid.

500Internal Server Errorstring

The gRPC control plane rejected the operation or the configuration could not be persisted.

Authorization

bearerAuthhttp (bearer)

Value of ADMIN_API_TOKEN; authentication is enabled by default.

Delete a backend
curl -X DELETE 'http://localhost:8081/api/backend/{id}'
package main

import (
  "fmt"
  "io"
  "net/http"
)

func main() {
  req, _ := http.NewRequest("DELETE", "http://localhost:8081/api/backend/{id}", nil)
  resp, _ := http.DefaultClient.Do(req)
  defer resp.Body.Close()
  data, _ := io.ReadAll(resp.Body)
  fmt.Println(string(data))
}
const response = await fetch('http://localhost:8081/api/backend/{id}', {
  method: 'DELETE',
});

const data = await response.json();
import requests

response = requests.delete('http://localhost:8081/api/backend/{id}')
data = response.json()
{
  "success": true,
  "message": "Configuration updated successfully"
}
Unauthorized
Failed to update backend: backend does not exist in config: backend-1

Virtual hosts

Manage host-based routing and path routing.

List virtual hosts

GET
http://localhost:8081/api/vhost

Returns every configured host routing definition.

Source: Go handler.

Response

200OKArray<VirtualHostRead>

Configured virtual hosts.

401Unauthorizedstring

Bearer authentication is enabled and the token is missing or invalid.

500Internal Server Errorstring

The gRPC control plane rejected the operation or the configuration could not be persisted.

Authorization

bearerAuthhttp (bearer)

Value of ADMIN_API_TOKEN; authentication is enabled by default.

List virtual hosts
curl -X GET 'http://localhost:8081/api/vhost'
package main

import (
  "fmt"
  "io"
  "net/http"
)

func main() {
  req, _ := http.NewRequest("GET", "http://localhost:8081/api/vhost", nil)
  resp, _ := http.DefaultClient.Do(req)
  defer resp.Body.Close()
  data, _ := io.ReadAll(resp.Body)
  fmt.Println(string(data))
}
const response = await fetch('http://localhost:8081/api/vhost', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('http://localhost:8081/api/vhost')
data = response.json()
[
  {
    "domain": "app.example.local",
    "backend_ids": [
      "backend-1",
      "backend-2"
    ],
    "security_policy_id": "default"
  }
]
Unauthorized
Failed to update backend: backend does not exist in config: backend-1

Add a virtual host

POST
http://localhost:8081/api/vhost

Adds a host routing definition. If security_policy_id is omitted, the service uses default.

Source: Go handler.

Body

application/json
virtual_hostVirtualHost & objectrequired

Response

200OKBasicResponse

The change was validated, persisted, and published.

400Bad Requeststring

The request body is not valid JSON or a required path value is missing.

401Unauthorizedstring

Bearer authentication is enabled and the token is missing or invalid.

413Payload Too Largestring

The request body exceeds the service-wide 1 MiB limit.

500Internal Server Errorstring

The gRPC control plane rejected the operation or the configuration could not be persisted.

Authorization

bearerAuthhttp (bearer)

Value of ADMIN_API_TOKEN; authentication is enabled by default.

Add a virtual host
curl -X POST 'http://localhost:8081/api/vhost' \
  -H 'Content-Type: application/json' \
  -d '{
    "virtual_host": {
      "domain": "api.example.local",
      "backend_ids": [
        "backend-1"
      ],
      "security_policy_id": "default"
    }
  }'
package main

import (
  "fmt"
  "io"
  "net/http"
  "strings"
)

func main() {
  body := strings.NewReader(`{
    "virtual_host": {
      "domain": "api.example.local",
      "backend_ids": [
        "backend-1"
      ],
      "security_policy_id": "default"
    }
  }`)
  req, _ := http.NewRequest("POST", "http://localhost:8081/api/vhost", body)
  req.Header.Set("Content-Type", "application/json")
  resp, _ := http.DefaultClient.Do(req)
  defer resp.Body.Close()
  data, _ := io.ReadAll(resp.Body)
  fmt.Println(string(data))
}
const response = await fetch('http://localhost:8081/api/vhost', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "virtual_host": {
        "domain": "api.example.local",
        "backend_ids": [
          "backend-1"
        ],
        "security_policy_id": "default"
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "virtual_host": {
    "domain": "api.example.local",
    "backend_ids": [
      "backend-1"
    ],
    "security_policy_id": "default"
  }
}

response = requests.post('http://localhost:8081/api/vhost', json=payload)
data = response.json()
Request Body
{
  "virtual_host": {
    "domain": "api.example.local",
    "backend_ids": [
      "backend-1"
    ],
    "security_policy_id": "default"
  }
}
{
  "success": true,
  "message": "Configuration updated successfully"
}
Invalid request body: unexpected EOF
Unauthorized
string
Failed to update backend: backend does not exist in config: backend-1

Get a virtual host

GET
http://localhost:8081/api/vhost/{domain}

Returns the routing definition selected by the path domain.

Source: Go handler.

Parameters

domainstringrequiredpath

Virtual-host domain. URL-encode special characters when placing it in the path.

Response

200OKVirtualHost & object

Virtual-host routing definition.

401Unauthorizedstring

Bearer authentication is enabled and the token is missing or invalid.

500Internal Server Errorstring

The gRPC control plane rejected the operation or the configuration could not be persisted.

Authorization

bearerAuthhttp (bearer)

Value of ADMIN_API_TOKEN; authentication is enabled by default.

Get a virtual host
curl -X GET 'http://localhost:8081/api/vhost/{domain}'
package main

import (
  "fmt"
  "io"
  "net/http"
)

func main() {
  req, _ := http.NewRequest("GET", "http://localhost:8081/api/vhost/{domain}", nil)
  resp, _ := http.DefaultClient.Do(req)
  defer resp.Body.Close()
  data, _ := io.ReadAll(resp.Body)
  fmt.Println(string(data))
}
const response = await fetch('http://localhost:8081/api/vhost/{domain}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('http://localhost:8081/api/vhost/{domain}')
data = response.json()
{
  "domain": "string",
  "backend_ids": [
    "string"
  ],
  "path_routes": [
    {
      "path": "/api",
      "backend_ids": [
        "string"
      ],
      "strip_prefix": false
    }
  ],
  "security_policy_id": "default"
}
Unauthorized
Failed to update backend: backend does not exist in config: backend-1

Replace a virtual host

PUT
http://localhost:8081/api/vhost/{domain}

Replaces the virtual-host definition selected by the path. The path domain is authoritative. If the body omits security_policy_id, the existing assignment is preserved.

Source: Go handler.

Body

application/json
domainstring

Accepted by the decoder but replaced with the path domain.

virtual_hostVirtualHostrequired

At least one default backend or one path route is required. Every referenced backend and policy must already exist.

Show child attributes
domainstring
backend_idsArray<string>
path_routesArray<PathRoute>
Show child attributes
pathstringrequired
backend_idsArray<string>
strip_prefixbooleanfalse
security_policy_idstringdefault

Parameters

domainstringrequiredpath

Virtual-host domain. URL-encode special characters when placing it in the path.

Response

200OKBasicResponse

The change was validated, persisted, and published.

400Bad Requeststring

The request body is not valid JSON or a required path value is missing.

401Unauthorizedstring

Bearer authentication is enabled and the token is missing or invalid.

413Payload Too Largestring

The request body exceeds the service-wide 1 MiB limit.

500Internal Server Errorstring

The gRPC control plane rejected the operation or the configuration could not be persisted.

Authorization

bearerAuthhttp (bearer)

Value of ADMIN_API_TOKEN; authentication is enabled by default.

Replace a virtual host
curl -X PUT 'http://localhost:8081/api/vhost/{domain}' \
  -H 'Content-Type: application/json' \
  -d '{
    "virtual_host": {
      "backend_ids": [
        "backend-1",
        "backend-2"
      ],
      "path_routes": [
        {
          "path": "/api",
          "backend_ids": [
            "backend-2"
          ],
          "strip_prefix": true
        }
      ]
    }
  }'
package main

import (
  "fmt"
  "io"
  "net/http"
  "strings"
)

func main() {
  body := strings.NewReader(`{
    "virtual_host": {
      "backend_ids": [
        "backend-1",
        "backend-2"
      ],
      "path_routes": [
        {
          "path": "/api",
          "backend_ids": [
            "backend-2"
          ],
          "strip_prefix": true
        }
      ]
    }
  }`)
  req, _ := http.NewRequest("PUT", "http://localhost:8081/api/vhost/{domain}", body)
  req.Header.Set("Content-Type", "application/json")
  resp, _ := http.DefaultClient.Do(req)
  defer resp.Body.Close()
  data, _ := io.ReadAll(resp.Body)
  fmt.Println(string(data))
}
const response = await fetch('http://localhost:8081/api/vhost/{domain}', {
  method: 'PUT',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "virtual_host": {
        "backend_ids": [
          "backend-1",
          "backend-2"
        ],
        "path_routes": [
          {
            "path": "/api",
            "backend_ids": [
              "backend-2"
            ],
            "strip_prefix": true
          }
        ]
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "virtual_host": {
    "backend_ids": [
      "backend-1",
      "backend-2"
    ],
    "path_routes": [
      {
        "path": "/api",
        "backend_ids": [
          "backend-2"
        ],
        "strip_prefix": True
      }
    ]
  }
}

response = requests.put('http://localhost:8081/api/vhost/{domain}', json=payload)
data = response.json()
Request Body
{
  "virtual_host": {
    "backend_ids": [
      "backend-1",
      "backend-2"
    ],
    "path_routes": [
      {
        "path": "/api",
        "backend_ids": [
          "backend-2"
        ],
        "strip_prefix": true
      }
    ]
  }
}
{
  "success": true,
  "message": "Configuration updated successfully"
}
Invalid request body: unexpected EOF
Unauthorized
string
Failed to update backend: backend does not exist in config: backend-1

Delete a virtual host

DELETE
http://localhost:8081/api/vhost/{domain}

Deletes the routing definition selected by the path domain.

Source: Go handler.

Parameters

domainstringrequiredpath

Virtual-host domain. URL-encode special characters when placing it in the path.

Response

200OKBasicResponse

The change was validated, persisted, and published.

401Unauthorizedstring

Bearer authentication is enabled and the token is missing or invalid.

500Internal Server Errorstring

The gRPC control plane rejected the operation or the configuration could not be persisted.

Authorization

bearerAuthhttp (bearer)

Value of ADMIN_API_TOKEN; authentication is enabled by default.

Delete a virtual host
curl -X DELETE 'http://localhost:8081/api/vhost/{domain}'
package main

import (
  "fmt"
  "io"
  "net/http"
)

func main() {
  req, _ := http.NewRequest("DELETE", "http://localhost:8081/api/vhost/{domain}", nil)
  resp, _ := http.DefaultClient.Do(req)
  defer resp.Body.Close()
  data, _ := io.ReadAll(resp.Body)
  fmt.Println(string(data))
}
const response = await fetch('http://localhost:8081/api/vhost/{domain}', {
  method: 'DELETE',
});

const data = await response.json();
import requests

response = requests.delete('http://localhost:8081/api/vhost/{domain}')
data = response.json()
{
  "success": true,
  "message": "Configuration updated successfully"
}
Unauthorized
Failed to update backend: backend does not exist in config: backend-1

Security policies

Manage reusable rate-limiting policies and host assignments.

Get a virtual host's security policy

GET
http://localhost:8081/api/vhost/{domain}/security

Returns the security policy assigned to the selected virtual host.

Source: Go handler.

Parameters

domainstringrequiredpath

Virtual-host domain. URL-encode special characters when placing it in the path.

Response

200OKVirtualHostSecurity

The virtual host and its resolved policy.

401Unauthorizedstring

Bearer authentication is enabled and the token is missing or invalid.

500Internal Server Errorstring

The gRPC control plane rejected the operation or the configuration could not be persisted.

Authorization

bearerAuthhttp (bearer)

Value of ADMIN_API_TOKEN; authentication is enabled by default.

Get a virtual host's security policy
curl -X GET 'http://localhost:8081/api/vhost/{domain}/security'
package main

import (
  "fmt"
  "io"
  "net/http"
)

func main() {
  req, _ := http.NewRequest("GET", "http://localhost:8081/api/vhost/{domain}/security", nil)
  resp, _ := http.DefaultClient.Do(req)
  defer resp.Body.Close()
  data, _ := io.ReadAll(resp.Body)
  fmt.Println(string(data))
}
const response = await fetch('http://localhost:8081/api/vhost/{domain}/security', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('http://localhost:8081/api/vhost/{domain}/security')
data = response.json()
{
  "domain": "string",
  "security_policy_id": "string",
  "policy": {
    "id": "string"
  }
}
Unauthorized
Failed to update backend: backend does not exist in config: backend-1

Assign a security policy to a virtual host

PUT
http://localhost:8081/api/vhost/{domain}/security

The path domain is authoritative. The referenced policy must exist.

Source: Go handler.

Body

application/json
domainstring

Accepted by the decoder but replaced with the path domain.

policy_idstringrequired

Parameters

domainstringrequiredpath

Virtual-host domain. URL-encode special characters when placing it in the path.

Response

200OKBasicResponse

The change was validated, persisted, and published.

400Bad Requeststring

The request body is not valid JSON or a required path value is missing.

401Unauthorizedstring

Bearer authentication is enabled and the token is missing or invalid.

413Payload Too Largestring

The request body exceeds the service-wide 1 MiB limit.

500Internal Server Errorstring

The gRPC control plane rejected the operation or the configuration could not be persisted.

Authorization

bearerAuthhttp (bearer)

Value of ADMIN_API_TOKEN; authentication is enabled by default.

Assign a security policy to a virtual host
curl -X PUT 'http://localhost:8081/api/vhost/{domain}/security' \
  -H 'Content-Type: application/json' \
  -d '{
    "policy_id": "strict"
  }'
package main

import (
  "fmt"
  "io"
  "net/http"
  "strings"
)

func main() {
  body := strings.NewReader(`{
    "policy_id": "strict"
  }`)
  req, _ := http.NewRequest("PUT", "http://localhost:8081/api/vhost/{domain}/security", body)
  req.Header.Set("Content-Type", "application/json")
  resp, _ := http.DefaultClient.Do(req)
  defer resp.Body.Close()
  data, _ := io.ReadAll(resp.Body)
  fmt.Println(string(data))
}
const response = await fetch('http://localhost:8081/api/vhost/{domain}/security', {
  method: 'PUT',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "policy_id": "strict"
    }),
});

const data = await response.json();
import requests

payload = {
  "policy_id": "strict"
}

response = requests.put('http://localhost:8081/api/vhost/{domain}/security', json=payload)
data = response.json()
Request Body
{
  "policy_id": "strict"
}
{
  "success": true,
  "message": "Configuration updated successfully"
}
Invalid request body: unexpected EOF
Unauthorized
string
Failed to update backend: backend does not exist in config: backend-1

List security policies

GET
http://localhost:8081/api/security/policies

Returns every reusable security policy.

Source: Go handler.

Response

200OKArray<SecurityPolicy>

Configured reusable security policies.

401Unauthorizedstring

Bearer authentication is enabled and the token is missing or invalid.

500Internal Server Errorstring

The gRPC control plane rejected the operation or the configuration could not be persisted.

Authorization

bearerAuthhttp (bearer)

Value of ADMIN_API_TOKEN; authentication is enabled by default.

List security policies
curl -X GET 'http://localhost:8081/api/security/policies'
package main

import (
  "fmt"
  "io"
  "net/http"
)

func main() {
  req, _ := http.NewRequest("GET", "http://localhost:8081/api/security/policies", nil)
  resp, _ := http.DefaultClient.Do(req)
  defer resp.Body.Close()
  data, _ := io.ReadAll(resp.Body)
  fmt.Println(string(data))
}
const response = await fetch('http://localhost:8081/api/security/policies', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('http://localhost:8081/api/security/policies')
data = response.json()
[
  {
    "id": "string"
  }
]
Unauthorized
Failed to update backend: backend does not exist in config: backend-1

Create or replace a security policy

PUT
http://localhost:8081/api/security/policies/{id}

The path id is authoritative and replaces any id supplied in the body.

Source: Go handler.

Body

application/json
idstring

Accepted by the decoder but replaced with the path id.

rate_limitingany
Show child attributes
any

Parameters

idstringrequiredpath

Stable security-policy identifier.

Response

200OKBasicResponse

The change was validated, persisted, and published.

400Bad Requeststring

The request body is not valid JSON or a required path value is missing.

401Unauthorizedstring

Bearer authentication is enabled and the token is missing or invalid.

413Payload Too Largestring

The request body exceeds the service-wide 1 MiB limit.

500Internal Server Errorstring

The gRPC control plane rejected the operation or the configuration could not be persisted.

Authorization

bearerAuthhttp (bearer)

Value of ADMIN_API_TOKEN; authentication is enabled by default.

Create or replace a security policy
curl -X PUT 'http://localhost:8081/api/security/policies/{id}' \
  -H 'Content-Type: application/json' \
  -d '{
    "rate_limiting": {
      "enabled": true,
      "rate_per_ip": 100,
      "burst": 50,
      "window_sec": 60
    }
  }'
package main

import (
  "fmt"
  "io"
  "net/http"
  "strings"
)

func main() {
  body := strings.NewReader(`{
    "rate_limiting": {
      "enabled": true,
      "rate_per_ip": 100,
      "burst": 50,
      "window_sec": 60
    }
  }`)
  req, _ := http.NewRequest("PUT", "http://localhost:8081/api/security/policies/{id}", body)
  req.Header.Set("Content-Type", "application/json")
  resp, _ := http.DefaultClient.Do(req)
  defer resp.Body.Close()
  data, _ := io.ReadAll(resp.Body)
  fmt.Println(string(data))
}
const response = await fetch('http://localhost:8081/api/security/policies/{id}', {
  method: 'PUT',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "rate_limiting": {
        "enabled": true,
        "rate_per_ip": 100,
        "burst": 50,
        "window_sec": 60
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "rate_limiting": {
    "enabled": True,
    "rate_per_ip": 100,
    "burst": 50,
    "window_sec": 60
  }
}

response = requests.put('http://localhost:8081/api/security/policies/{id}', json=payload)
data = response.json()
Request Body
{
  "rate_limiting": {
    "enabled": true,
    "rate_per_ip": 100,
    "burst": 50,
    "window_sec": 60
  }
}
{
  "success": true,
  "message": "Configuration updated successfully"
}
Invalid request body: unexpected EOF
Unauthorized
string
Failed to update backend: backend does not exist in config: backend-1

Runtime configuration

Inspect and update server and load-balancer settings.

Get listener configuration

GET
http://localhost:8081/api/config/server

Returns persisted listener ports. Updating these values does not restart live listeners yet.

Source: Go handler.

Response

200OKServerConfig

Current persisted server configuration.

401Unauthorizedstring

Bearer authentication is enabled and the token is missing or invalid.

500Internal Server Errorstring

The gRPC control plane rejected the operation or the configuration could not be persisted.

Authorization

bearerAuthhttp (bearer)

Value of ADMIN_API_TOKEN; authentication is enabled by default.

Get listener configuration
curl -X GET 'http://localhost:8081/api/config/server'
package main

import (
  "fmt"
  "io"
  "net/http"
)

func main() {
  req, _ := http.NewRequest("GET", "http://localhost:8081/api/config/server", nil)
  resp, _ := http.DefaultClient.Do(req)
  defer resp.Body.Close()
  data, _ := io.ReadAll(resp.Body)
  fmt.Println(string(data))
}
const response = await fetch('http://localhost:8081/api/config/server', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('http://localhost:8081/api/config/server')
data = response.json()
{
  "proxy_port": 1,
  "admin_grpc_port": 1
}
Unauthorized
Failed to update backend: backend does not exist in config: backend-1

Update persisted listener configuration

PUT
http://localhost:8081/api/config/server

A missing or zero-valued port keeps its current value. Live listeners are not restarted.

Source: Go handler.

Body

application/json
proxy_portinteger<int32>[0, 65535]

Zero or omission preserves the current value.

admin_grpc_portinteger<int32>[0, 65535]

Zero or omission preserves the current value.

Response

200OKBasicResponse

The change was validated, persisted, and published.

400Bad Requeststring

The request body is not valid JSON or a required path value is missing.

401Unauthorizedstring

Bearer authentication is enabled and the token is missing or invalid.

413Payload Too Largestring

The request body exceeds the service-wide 1 MiB limit.

500Internal Server Errorstring

The gRPC control plane rejected the operation or the configuration could not be persisted.

Authorization

bearerAuthhttp (bearer)

Value of ADMIN_API_TOKEN; authentication is enabled by default.

Update persisted listener configuration
curl -X PUT 'http://localhost:8081/api/config/server' \
  -H 'Content-Type: application/json' \
  -d '{
    "proxy_port": 8080,
    "admin_grpc_port": 50051
  }'
package main

import (
  "fmt"
  "io"
  "net/http"
  "strings"
)

func main() {
  body := strings.NewReader(`{
    "proxy_port": 8080,
    "admin_grpc_port": 50051
  }`)
  req, _ := http.NewRequest("PUT", "http://localhost:8081/api/config/server", body)
  req.Header.Set("Content-Type", "application/json")
  resp, _ := http.DefaultClient.Do(req)
  defer resp.Body.Close()
  data, _ := io.ReadAll(resp.Body)
  fmt.Println(string(data))
}
const response = await fetch('http://localhost:8081/api/config/server', {
  method: 'PUT',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "proxy_port": 8080,
      "admin_grpc_port": 50051
    }),
});

const data = await response.json();
import requests

payload = {
  "proxy_port": 8080,
  "admin_grpc_port": 50051
}

response = requests.put('http://localhost:8081/api/config/server', json=payload)
data = response.json()
Request Body
{
  "proxy_port": 8080,
  "admin_grpc_port": 50051
}
{
  "success": true,
  "message": "Configuration updated successfully"
}
Invalid request body: unexpected EOF
Unauthorized
string
Failed to update backend: backend does not exist in config: backend-1

Get the load-balancing strategy

GET
http://localhost:8081/api/config/lb

Returns the persisted load-balancing strategy.

Source: Go handler.

Response

200OKLoadBalancerConfig

Current load-balancer configuration.

401Unauthorizedstring

Bearer authentication is enabled and the token is missing or invalid.

500Internal Server Errorstring

The gRPC control plane rejected the operation or the configuration could not be persisted.

Authorization

bearerAuthhttp (bearer)

Value of ADMIN_API_TOKEN; authentication is enabled by default.

Get the load-balancing strategy
curl -X GET 'http://localhost:8081/api/config/lb'
package main

import (
  "fmt"
  "io"
  "net/http"
)

func main() {
  req, _ := http.NewRequest("GET", "http://localhost:8081/api/config/lb", nil)
  resp, _ := http.DefaultClient.Do(req)
  defer resp.Body.Close()
  data, _ := io.ReadAll(resp.Body)
  fmt.Println(string(data))
}
const response = await fetch('http://localhost:8081/api/config/lb', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('http://localhost:8081/api/config/lb')
data = response.json()
{
  "strategy": "least-connections"
}
Unauthorized
Failed to update backend: backend does not exist in config: backend-1

Update the load-balancing strategy

PUT
http://localhost:8081/api/config/lb

Validates and persists the selected load-balancing strategy.

Source: Go handler.

Body

application/json
strategystringleast-connectionsadaptiverequired

Response

200OKBasicResponse

The change was validated, persisted, and published.

400Bad Requeststring

The request body is not valid JSON or a required path value is missing.

401Unauthorizedstring

Bearer authentication is enabled and the token is missing or invalid.

413Payload Too Largestring

The request body exceeds the service-wide 1 MiB limit.

500Internal Server Errorstring

The gRPC control plane rejected the operation or the configuration could not be persisted.

Authorization

bearerAuthhttp (bearer)

Value of ADMIN_API_TOKEN; authentication is enabled by default.

Update the load-balancing strategy
curl -X PUT 'http://localhost:8081/api/config/lb' \
  -H 'Content-Type: application/json' \
  -d '{
    "strategy": "least-connections"
  }'
package main

import (
  "fmt"
  "io"
  "net/http"
  "strings"
)

func main() {
  body := strings.NewReader(`{
    "strategy": "least-connections"
  }`)
  req, _ := http.NewRequest("PUT", "http://localhost:8081/api/config/lb", body)
  req.Header.Set("Content-Type", "application/json")
  resp, _ := http.DefaultClient.Do(req)
  defer resp.Body.Close()
  data, _ := io.ReadAll(resp.Body)
  fmt.Println(string(data))
}
const response = await fetch('http://localhost:8081/api/config/lb', {
  method: 'PUT',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "strategy": "least-connections"
    }),
});

const data = await response.json();
import requests

payload = {
  "strategy": "least-connections"
}

response = requests.put('http://localhost:8081/api/config/lb', json=payload)
data = response.json()
Request Body
{
  "strategy": "least-connections"
}
{
  "success": true,
  "message": "Configuration updated successfully"
}
Invalid request body: unexpected EOF
Unauthorized
string
Failed to update backend: backend does not exist in config: backend-1

Models

BasicResponse

object
successbooleanrequired
messagestring
Example
{
  "success": true,
  "message": "Backend updated successfully"
}

Backend

object
idstringrequired
urlstring<uri>required
weightinteger<int32>>= 1required
enabledboolean
activeboolean
error_countinteger<int32>>= 0
last_errorstring
Example
{
  "id": "string",
  "url": "https://example.com",
  "weight": 1,
  "enabled": true,
  "active": true,
  "error_count": 0,
  "last_error": "string"
}

BackendCreate

object
idstringrequired
urlstring<uri>required
weightinteger<int32>>= 1required
enabledbooleanfalse
Example
{
  "id": "string",
  "url": "https://example.com",
  "weight": 1,
  "enabled": false
}

BackendUpdate

object
idstring

Accepted by the decoder but replaced with the path id.

urlstring<uri>

Omit or send an empty string to preserve the existing URL.

weightinteger<int32>>= 1required
enabledbooleanfalse

Omission decodes as false and disables the backend.

Example
{
  "id": "string",
  "url": "https://example.com",
  "weight": 1,
  "enabled": false
}

PathRoute

object
pathstringrequired
backend_idsArray<string>
strip_prefixbooleanfalse
Example
{
  "path": "/api",
  "backend_ids": [
    "string"
  ],
  "strip_prefix": false
}

VirtualHost

object

At least one default backend or one path route is required. Every referenced backend and policy must already exist.

domainstring
backend_idsArray<string>
path_routesArray<PathRoute>
Show child attributes
pathstringrequired
backend_idsArray<string>
strip_prefixbooleanfalse
security_policy_idstringdefault
Example
{
  "domain": "string",
  "backend_ids": [
    "string"
  ],
  "path_routes": [
    {
      "path": "/api",
      "backend_ids": [
        "string"
      ],
      "strip_prefix": false
    }
  ],
  "security_policy_id": "default"
}

VirtualHostRead

object

At least one default backend or one path route is required. Every referenced backend and policy must already exist.

domainstring
backend_idsArray<string>
path_routesArray<PathRoute>
Show child attributes
pathstringrequired
backend_idsArray<string>
strip_prefixbooleanfalse
security_policy_idstringdefault
object
Example
{
  "domain": "string",
  "backend_ids": [
    "string"
  ],
  "path_routes": [
    {
      "path": "/api",
      "backend_ids": [
        "string"
      ],
      "strip_prefix": false
    }
  ],
  "security_policy_id": "default"
}

VirtualHostCreateRequest

object
virtual_hostVirtualHost & objectrequired
Example
{
  "virtual_host": {
    "domain": "string",
    "backend_ids": [
      "string"
    ],
    "path_routes": [
      {
        "path": "/api",
        "backend_ids": [
          "string"
        ],
        "strip_prefix": false
      }
    ],
    "security_policy_id": "default"
  }
}

VirtualHostUpdateRequest

object
domainstring

Accepted by the decoder but replaced with the path domain.

virtual_hostVirtualHostrequired

At least one default backend or one path route is required. Every referenced backend and policy must already exist.

Show child attributes
domainstring
backend_idsArray<string>
path_routesArray<PathRoute>
Show child attributes
pathstringrequired
backend_idsArray<string>
strip_prefixbooleanfalse
security_policy_idstringdefault
Example
{
  "domain": "string",
  "virtual_host": {
    "domain": "string",
    "backend_ids": [
      "string"
    ],
    "path_routes": [
      {
        "path": "/api",
        "backend_ids": [
          "string"
        ],
        "strip_prefix": false
      }
    ],
    "security_policy_id": "default"
  }
}

RateLimitingConfig

object
any

SecurityPolicy

object
idstringrequired
rate_limitingany
Show child attributes
any
Example
{
  "id": "string"
}

SecurityPolicyWrite

object
idstring

Accepted by the decoder but replaced with the path id.

rate_limitingany
Show child attributes
any
Example
{
  "id": "string"
}

SecurityPolicyAssignment

object
domainstring

Accepted by the decoder but replaced with the path domain.

policy_idstringrequired
Example
{
  "domain": "string",
  "policy_id": "string"
}

VirtualHostSecurity

object
domainstringrequired
security_policy_idstringrequired
policySecurityPolicyrequired
Show child attributes
idstringrequired
rate_limitingany
Show child attributes
any
Example
{
  "domain": "string",
  "security_policy_id": "string",
  "policy": {
    "id": "string"
  }
}

ServerConfig

object
proxy_portinteger<int32>[1, 65535]required
admin_grpc_portinteger<int32>[1, 65535]required
Example
{
  "proxy_port": 1,
  "admin_grpc_port": 1
}

ServerConfigUpdate

object
proxy_portinteger<int32>[0, 65535]

Zero or omission preserves the current value.

admin_grpc_portinteger<int32>[0, 65535]

Zero or omission preserves the current value.

Example
{
  "proxy_port": 0,
  "admin_grpc_port": 0
}

LoadBalancerConfig

object
strategystringleast-connectionsadaptiverequired
Example
{
  "strategy": "least-connections"
}