Skip to content

Hub API

All routes (except /api/health and /api/auth/*) require an authenticated session via cookie.

Base URL: /api

Authentication

Authentication is handled by Better Auth. All auth routes are prefixed with /api/auth.

POST /api/auth/sign-up/email

Create a new account.

Body:

json
{
  "name": "John Doe",
  "email": "john@example.com",
  "password": "password123"
}

Response: 200 — session information

POST /api/auth/sign-in/email

Sign in.

Body:

json
{
  "email": "john@example.com",
  "password": "password123"
}

Response: 200 — session cookie

POST /api/auth/sign-out

Sign out. Invalidates the current session.


Vhosts

GET /api/vhosts

List all vhosts, sorted by domain.

Response: 200

json
[
  {
    "id": 1,
    "domain": "app.example.com",
    "config": "  reverse_proxy http://backend:8080\n  ...",
    "enabled": true,
    "upstream": "http://backend:8080",
    "createdAt": "2025-01-15T10:30:00.000Z",
    "updatedAt": "2025-01-15T10:30:00.000Z"
  }
]

POST /api/vhosts

Create a new vhost.

Body:

json
{
  "domain": "app.example.com",
  "config": "  reverse_proxy http://backend:8080\n  log { ... }",
  "upstream": "http://backend:8080"
}
CodeDescription
201Vhost created, Caddy reloaded
400domain or config missing
409Domain already exists
502Caddy rejected the configuration (rollback performed)

PUT /api/vhosts/:id

Update an existing vhost. All fields are optional.

Body:

json
{
  "domain": "app.example.com",
  "config": "  reverse_proxy http://new-backend:8080\n  ...",
  "upstream": "http://new-backend:8080"
}
CodeDescription
200Vhost updated, Caddy reloaded
404Vhost not found
502Caddy rejected the configuration (rollback performed)

DELETE /api/vhosts/:id

Delete a vhost.

CodeDescription
200{ "success": true }
404Vhost not found
502Caddy rejected the configuration (rollback performed)

PATCH /api/vhosts/:id/toggle

Enable or disable a vhost (toggles current state).

CodeDescription
200Vhost updated
404Vhost not found
502Caddy rejected the configuration (rollback performed)

Logs

GET /api/logs

Retrieve Caddy access logs.

Query params:

ParamTypeDefaultDescription
domainstringFilter by domain
statusintegerFilter by HTTP code
pageinteger1Page number

Response: 200

json
{
  "logs": [
    {
      "timestamp": "2025-01-15T10:30:00.000Z",
      "domain": "app.example.com",
      "method": "GET",
      "path": "/api/data",
      "status": 200,
      "latency": "12.3ms",
      "ip": "192.168.1.1"
    }
  ],
  "total": 150,
  "page": 1,
  "pageSize": 50
}

Changelog

GET /api/changelog

Retrieve the last 100 changelog entries.

Response: 200

json
[
  {
    "id": 1,
    "userId": "abc123",
    "userName": "John Doe",
    "action": "create",
    "domain": "app.example.com",
    "diff": null,
    "createdAt": "2025-01-15T10:30:00.000Z"
  }
]

Possible values for action: create, update, delete, toggle.

For update actions, the diff field contains a stringified JSON with old and new keys.


Health

GET /api/health

Health check. No authentication required.

Response: 200

json
{ "status": "ok" }