Skip to main content

Control Plane API Reference (v1)

Base URL: http://localhost:8000

  • Content-Type: application/json
  • Error format: { "detail": string }
  • Authentication:
    • Session cookie via POST /api/v1/auth/login
    • Bearer token via Authorization: Bearer <token> (Master token from MASTER_API_TOKEN or service tokens from /api/v1/auth/tokens)

Conventions

  • Unless noted otherwise, endpoints require authentication via session cookie or bearer token.
  • Endpoints that manage tokens (/api/v1/auth/tokens) require the master token.
  • Error responses use { "detail": string } with appropriate HTTP status codes.
  • Path parameters appear as {param} (for example {domain}).

Models

Upstream

FieldTypeRequiredDescriptionExample
schemestringyesOrigin protocol"http" or "https"
hoststringyesOrigin host"origin.example.com"
portintegeryesOrigin port80
weightintegeryesWeighted round-robin weight1

Rule

FieldTypeRequiredDescriptionExample
pathstringyesPath prefix or regex (interpreted by OpenResty)"^/assets/"
ttlintegeryesTTL in seconds600
methodsstring[]yesAllowed HTTP methods["GET","HEAD"]
slicebooleannoEnable slice for this rule (overrides global)false

DomainConf

FieldTypeRequiredDescriptionExample
originsUpstream[]yesList of upstream origins[Upstream, ...]
upstream_headersobjectnoExtra headers to send to origin{"X-From":"CDN"}
cache_enablebooleanyesEnable cachingtrue
slice_enablebooleanyesEnable slice globallyfalse
rulesRule[]yesCache rules[Rule, ...]
use_acme_dns01booleannoEnable ACME dns-01 automationfalse
acme_cname_targetstring or nullnoTarget CNAME for _acme-challenge (filled after acme-dns registration)null

CacheUpdate (PUT /cache-rules)

FieldTypeRequiredDescription
cache_enablebooleannoToggle caching
slice_enablebooleannoToggle slice
rulesRule[]noCache rules

UpstreamsPayload (PUT /upstreams)

FieldTypeRequiredDescription
originsUpstream[]yesComplete upstream list (replaces all)

CertPayload (PUT /cert)

FieldTypeRequiredDescription
fullchain_pemstringyesCertificate chain in PEM
key_pemstringyesPrivate key in PEM

AssignedNode

FieldTypeDescription
idstringNode identifier
astringIPv4 address or null
aaaastringIPv6 address or null

Endpoints

GET /healthz

Authentication: None

  • Success 200: { "ok": true }
  • Failure 500: { "detail": string }
Example request
curl -s http://localhost:8000/healthz
Example response
{ "ok": true }

POST /api/v1/auth/login

Authentication: None

Request body

FieldTypeRequiredDescription
usernamestringyesUsername
passwordstringyesPassword
  • Success 200: { "ok": true } (sets session cookie)
  • Errors: 401 invalid credentials, 403 password authentication disabled
Example request
curl -i -X POST 'http://localhost:8000/api/v1/auth/login' \
-H 'Content-Type: application/json' \
-d '{"username":"admin","password":"******"}'
Example response
{ "ok": true }

POST /api/v1/auth/logout

  • Success 200: { "ok": true } (clears session cookie)

GET /api/v1/auth/me

Authentication: Session or bearer

Success 200

FieldTypeDescription
usernamestringCurrent username
auth_methodstringone of session/token/master/dev
token_idstring or nullService token id (null for master token)
Example request
curl -s 'http://localhost:8000/api/v1/auth/me' -b cookies.txt -c cookies.txt
Example response
{ "username": "admin", "auth_method": "session", "token_id": null }

GET /api/v1/auth/tokens

Authentication: Master token

  • Success 200
FieldTypeDescription
tokensarrayArray of Token objects

Token object

FieldTypeDescription
idstringToken id
labelstringHuman label
created_atstring (ISO 8601)Creation time
last_used_atstring or nullLast use time
suffixstringLast 2 chars of token
Example request
curl -s 'http://localhost:8000/api/v1/auth/tokens' \
-H 'Authorization: Bearer ${MASTER_API_TOKEN}'

POST /api/v1/auth/tokens

Authentication: Master token

Request body

FieldTypeRequiredDescription
labelstringyesToken label
  • Success 200: Token object plus token (one-time value)
Extra FieldTypeDescription
tokenstringFull token (returned only once)
Example request
curl -s -X POST 'http://localhost:8000/api/v1/auth/tokens' \
-H 'Authorization: Bearer ${MASTER_API_TOKEN}' \
-H 'Content-Type: application/json' \
-d '{"label":"ci token"}'
Example response
{
"id": "4f8a1c9e5d3b",
"label": "ci token",
"created_at": "2024-04-02T07:20:00+00:00",
"last_used_at": null,
"suffix": "3b",
"token": "qjP...<one-time>..."
}

DELETE /api/v1/auth/tokens/{token_id}

  • Requires master token
  • Success 200: { "ok": true }

GET /api/v1/users

Authentication: Session or bearer

Success 200

FieldTypeDescription
usersarrayArray of user objects

User object

FieldTypeDescription
usernamestringUsername
emailstringEmail (may be empty)
statusstring"Active" or "Inactive"
lastLoginstring"Never" or timestamp
Example request
curl -s 'http://localhost:8000/api/v1/users' \
-H 'Authorization: Bearer <token>'

POST /api/v1/users

Request body

FieldTypeRequired
usernamestringyes
emailstringyes
passwordstringyes
statusstringyes ("Active"/"Inactive")
  • Success 200: { "ok": true }
  • Error 409: user already exists

PUT /api/v1/users/{username}

Request body (all optional)

FieldType
emailstring
passwordstring
statusstring
  • Success 200: { "ok": true }
  • Error 404: user not found

DELETE /api/v1/users/{username}

  • Success 200: { "ok": true }

POST /api/v1/domains/{domain}

Authentication: Session or bearer

Path params

ParamTypeDescription
domainstringDomain name

Request body: DomainConf

  • Success 200: { "ok": true }
  • Errors: 400 origins must be a non-empty list, 409 domain already exists
Example request
curl -X POST 'http://localhost:8000/api/v1/domains/example.com' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <token>' \
-d '{
"origins":[{"scheme":"http","host":"10.0.0.10","port":80,"weight":2}],
"cache_enable": true,
"slice_enable": false,
"rules": []
}'

GET /api/v1/domains

Success 200

FieldTypeDescription
domainsstring[]Domain names

GET /api/v1/domains/{domain}

  • Success 200: DomainConf
  • Error 404: domain not found

GET /api/v1/domains/{domain}/cname

Authentication: Session or bearer

Path params

ParamTypeDescription
domainstringDomain name

Success 200

FieldTypeDescription
access_domainstringAccess FQDN
replicasintegerReplica count
assigned_nodesAssignedNode[]Nodes assigned
ttlintegerTTL

Errors

  • 405: cname is disabled
Example response
{
"access_domain": "example.com.cdn.local.test.",
"replicas": 2,
"assigned_nodes": [
{"id":"node-1","a":"100.64.2.61","aaaa":null},
{"id":"node-2","a":"100.64.2.62","aaaa":null}
],
"ttl": 60
}

PUT /api/v1/domains/{domain}

Request body: DomainConf

  • Success 200: { "ok": true }
  • Errors: 404 domain not found, 400 origins must be a non-empty list

DELETE /api/v1/domains/{domain}

  • Success 200: { "ok": true } (also cleans related keys)

PUT /api/v1/domains/{domain}/cache-rules

Request body: CacheUpdate

  • Success 200: { "ok": true }

PUT /api/v1/domains/{domain}/upstreams

Request body: UpstreamsPayload

  • Success 200: { "ok": true }

PUT /api/v1/domains/{domain}/cert

Request body: CertPayload

  • Success 200: { "ok": true }
  • Error 400: invalid PEM

GET /api/v1/domains/{domain}/acme

Success 200

Response fields

FieldTypeDescription
use_acme_dns01booleanWhether ACME is enabled
acme_cname_targetstring or nullTarget CNAME for _acme-challenge
statusstring"registered" / "disabled" / other statuses
registeredbooleanWhether acme-dns is registered
fulldomainstring or nullFull domain returned by acme-dns
subdomainstring or nullSubdomain part used by acme-dns

POST /api/v1/domains/{domain}/acme

  • Optional body: { "force_renew": true } (ignored by current implementation)
  • Success 202: { "ok": true, "task_id": string }
  • Conflict 409: acme issuance already running or queued for this domain

DELETE /api/v1/domains/{domain}/acme

  • Success 200: { "ok": true }

POST /api/v1/purge

Authentication: Session or bearer

Query params

ParamTypeRequiredDescription
domainstringyesTarget domain
pathstringyesPath; supports prefix wildcard * (e.g., /images/cat*); /* clears all
  • Success 200: { "ok": true } (message published; cleanup completes asynchronously)
Example request
curl -X POST 'http://localhost:8000/api/v1/purge?domain=example.com&path=/images/cat*' \
-H 'Authorization: Bearer <token>'

PUT /api/v1/nodes

Authentication: Session or bearer

Request body

FieldTypeRequiredDescription
nodesarrayyesArray of node objects

Node object

FieldTypeDescription
idstringNode id
namestringHuman name
astringIPv4
aaaastring or nullIPv6
  • Notes: active is not accepted (maintained by health checks). Update triggers CNAME zone rebuild and NOTIFY.
  • Success 200: { "ok": true, "count": number }
Example request
curl -X PUT 'http://localhost:8000/api/v1/nodes' \
-H 'Authorization: Bearer <token>' \
-H 'Content-Type: application/json' \
-d '{
"nodes": [
{"id":"node-1","name":"edge-1","a":"100.64.2.61","aaaa":null},
{"id":"node-2","name":"edge-2","a":"100.64.2.62","aaaa":null}
]
}'