Files
Charon/docs/api.md
Wikid82 e58fcb714d docs: comprehensive documentation polish & CI/CD automation
Major Updates:
- Rewrote all docs in beginner-friendly 'ELI5' language
- Created docs index with user journey navigation
- Added complete getting-started guide for novice users
- Set up GitHub Container Registry (GHCR) automation
- Configured GitHub Pages deployment for documentation

Documentation:
- docs/index.md - Central navigation hub
- docs/getting-started.md - Step-by-step beginner guide
- docs/github-setup.md - CI/CD setup instructions
- README.md - Complete rewrite in accessible language
- CONTRIBUTING.md - Contributor guidelines
- Multiple comprehensive API and schema docs

CI/CD Workflows:
- .github/workflows/docker-build.yml - Multi-platform builds to GHCR
- .github/workflows/docs.yml - Automated docs deployment to Pages
- Supports main (latest), development (dev), and version tags
- Automated testing of built images
- Beautiful documentation site with dark theme

Benefits:
- Zero barrier to entry for new users
- Automated Docker builds (AMD64 + ARM64)
- Professional documentation site
- No Docker Hub account needed (uses GHCR)
- Complete CI/CD pipeline

All 7 implementation phases complete - project is production ready!
2025-11-18 13:11:11 -05:00

11 KiB

API Documentation

CaddyProxyManager+ REST API documentation. All endpoints return JSON and use standard HTTP status codes.

Base URL

http://localhost:8080/api/v1

Authentication

🚧 Authentication is not yet implemented. All endpoints are currently public.

Future authentication will use JWT tokens:

Authorization: Bearer <token>

Response Format

Success Response

{
  "uuid": "550e8400-e29b-41d4-a716-446655440000",
  "name": "Example",
  "created_at": "2025-01-18T10:00:00Z"
}

Error Response

{
  "error": "Resource not found",
  "code": 404
}

Status Codes

Code Description
200 Success
201 Created
204 No Content (successful deletion)
400 Bad Request (validation error)
404 Not Found
500 Internal Server Error

Endpoints

Health Check

Check API health status.

GET /health

Response 200:

{
  "status": "ok"
}

Proxy Hosts

List All Proxy Hosts

GET /proxy-hosts

Response 200:

[
  {
    "uuid": "550e8400-e29b-41d4-a716-446655440000",
    "domain": "example.com, www.example.com",
    "forward_scheme": "http",
    "forward_host": "localhost",
    "forward_port": 8080,
    "ssl_forced": false,
    "http2_support": true,
    "hsts_enabled": false,
    "hsts_subdomains": false,
    "block_exploits": true,
    "websocket_support": false,
    "enabled": true,
    "remote_server_id": null,
    "created_at": "2025-01-18T10:00:00Z",
    "updated_at": "2025-01-18T10:00:00Z"
  }
]

Get Proxy Host

GET /proxy-hosts/:uuid

Parameters:

  • uuid (path) - Proxy host UUID

Response 200:

{
  "uuid": "550e8400-e29b-41d4-a716-446655440000",
  "domain": "example.com",
  "forward_scheme": "https",
  "forward_host": "backend.internal",
  "forward_port": 9000,
  "ssl_forced": true,
  "websocket_support": false,
  "enabled": true,
  "created_at": "2025-01-18T10:00:00Z",
  "updated_at": "2025-01-18T10:00:00Z"
}

Response 404:

{
  "error": "Proxy host not found"
}

Create Proxy Host

POST /proxy-hosts
Content-Type: application/json

Request Body:

{
  "domain": "new.example.com",
  "forward_scheme": "http",
  "forward_host": "localhost",
  "forward_port": 3000,
  "ssl_forced": false,
  "http2_support": true,
  "hsts_enabled": false,
  "hsts_subdomains": false,
  "block_exploits": true,
  "websocket_support": false,
  "enabled": true,
  "remote_server_id": null
}

Required Fields:

  • domain - Domain name(s), comma-separated
  • forward_host - Target hostname or IP
  • forward_port - Target port number

Optional Fields:

  • forward_scheme - Default: "http"
  • ssl_forced - Default: false
  • http2_support - Default: true
  • hsts_enabled - Default: false
  • hsts_subdomains - Default: false
  • block_exploits - Default: true
  • websocket_support - Default: false
  • enabled - Default: true
  • remote_server_id - Default: null

Response 201:

{
  "uuid": "550e8400-e29b-41d4-a716-446655440001",
  "domain": "new.example.com",
  "forward_scheme": "http",
  "forward_host": "localhost",
  "forward_port": 3000,
  "created_at": "2025-01-18T10:05:00Z",
  "updated_at": "2025-01-18T10:05:00Z"
}

Response 400:

{
  "error": "domain is required"
}

Update Proxy Host

PUT /proxy-hosts/:uuid
Content-Type: application/json

Parameters:

  • uuid (path) - Proxy host UUID

Request Body: (all fields optional)

{
  "domain": "updated.example.com",
  "forward_port": 8081,
  "ssl_forced": true
}

Response 200:

{
  "uuid": "550e8400-e29b-41d4-a716-446655440000",
  "domain": "updated.example.com",
  "forward_port": 8081,
  "ssl_forced": true,
  "updated_at": "2025-01-18T10:10:00Z"
}

Delete Proxy Host

DELETE /proxy-hosts/:uuid

Parameters:

  • uuid (path) - Proxy host UUID

Response 204: No content

Response 404:

{
  "error": "Proxy host not found"
}

Remote Servers

List All Remote Servers

GET /remote-servers

Query Parameters:

  • enabled (optional) - Filter by enabled status (true or false)

Response 200:

[
  {
    "uuid": "660e8400-e29b-41d4-a716-446655440000",
    "name": "Docker Registry",
    "provider": "docker",
    "host": "registry.local",
    "port": 5000,
    "reachable": true,
    "last_checked": "2025-01-18T09:55:00Z",
    "enabled": true,
    "created_at": "2025-01-18T09:00:00Z",
    "updated_at": "2025-01-18T09:55:00Z"
  }
]

Get Remote Server

GET /remote-servers/:uuid

Parameters:

  • uuid (path) - Remote server UUID

Response 200:

{
  "uuid": "660e8400-e29b-41d4-a716-446655440000",
  "name": "Docker Registry",
  "provider": "docker",
  "host": "registry.local",
  "port": 5000,
  "reachable": true,
  "enabled": true
}

Create Remote Server

POST /remote-servers
Content-Type: application/json

Request Body:

{
  "name": "Production API",
  "provider": "generic",
  "host": "api.prod.internal",
  "port": 8080,
  "enabled": true
}

Required Fields:

  • name - Server name
  • host - Hostname or IP
  • port - Port number

Optional Fields:

  • provider - One of: generic, docker, kubernetes, aws, gcp, azure (default: generic)
  • enabled - Default: true

Response 201:

{
  "uuid": "660e8400-e29b-41d4-a716-446655440001",
  "name": "Production API",
  "provider": "generic",
  "host": "api.prod.internal",
  "port": 8080,
  "reachable": false,
  "enabled": true,
  "created_at": "2025-01-18T10:15:00Z"
}

Update Remote Server

PUT /remote-servers/:uuid
Content-Type: application/json

Request Body: (all fields optional)

{
  "name": "Updated Name",
  "port": 8081,
  "enabled": false
}

Response 200:

{
  "uuid": "660e8400-e29b-41d4-a716-446655440000",
  "name": "Updated Name",
  "port": 8081,
  "enabled": false,
  "updated_at": "2025-01-18T10:20:00Z"
}

Delete Remote Server

DELETE /remote-servers/:uuid

Response 204: No content

Test Remote Server Connection

Test connectivity to a remote server.

POST /remote-servers/:uuid/test

Parameters:

  • uuid (path) - Remote server UUID

Response 200:

{
  "reachable": true,
  "address": "registry.local:5000",
  "timestamp": "2025-01-18T10:25:00Z"
}

Response 200 (unreachable):

{
  "reachable": false,
  "address": "offline.server:8080",
  "error": "connection timeout",
  "timestamp": "2025-01-18T10:25:00Z"
}

Note: This endpoint updates the reachable and last_checked fields on the remote server.


Import Workflow

Check Import Status

Check if there's an active import session.

GET /import/status

Response 200 (no session):

{
  "has_pending": false
}

Response 200 (active session):

{
  "has_pending": true,
  "session": {
    "uuid": "770e8400-e29b-41d4-a716-446655440000",
    "filename": "Caddyfile",
    "state": "reviewing",
    "created_at": "2025-01-18T10:30:00Z",
    "updated_at": "2025-01-18T10:30:00Z"
  }
}

Get Import Preview

Get preview of hosts to be imported (only available when session state is reviewing).

GET /import/preview

Response 200:

{
  "hosts": [
    {
      "domain": "example.com",
      "forward_host": "localhost",
      "forward_port": 8080,
      "forward_scheme": "http"
    },
    {
      "domain": "api.example.com",
      "forward_host": "backend",
      "forward_port": 9000,
      "forward_scheme": "https"
    }
  ],
  "conflicts": [
    "example.com already exists"
  ],
  "errors": []
}

Response 404:

{
  "error": "No active import session"
}

Upload Caddyfile

Upload a Caddyfile for import.

POST /import/upload
Content-Type: application/json

Request Body:

{
  "content": "example.com {\n    reverse_proxy localhost:8080\n}",
  "filename": "Caddyfile"
}

Required Fields:

  • content - Caddyfile content

Optional Fields:

  • filename - Original filename (default: "Caddyfile")

Response 201:

{
  "session": {
    "uuid": "770e8400-e29b-41d4-a716-446655440000",
    "filename": "Caddyfile",
    "state": "parsing",
    "created_at": "2025-01-18T10:35:00Z"
  }
}

Response 400:

{
  "error": "content is required"
}

Commit Import

Commit the import after resolving conflicts.

POST /import/commit
Content-Type: application/json

Request Body:

{
  "session_uuid": "770e8400-e29b-41d4-a716-446655440000",
  "resolutions": {
    "example.com": "overwrite",
    "api.example.com": "keep"
  }
}

Required Fields:

  • session_uuid - Active import session UUID
  • resolutions - Map of domain to resolution strategy

Resolution Strategies:

  • "keep" - Keep existing configuration, skip import
  • "overwrite" - Replace existing with imported configuration
  • "skip" - Same as keep

Response 200:

{
  "imported": 2,
  "skipped": 1,
  "failed": 0
}

Response 400:

{
  "error": "Invalid session or unresolved conflicts"
}

Cancel Import

Cancel an active import session.

DELETE /import/cancel?session_uuid=770e8400-e29b-41d4-a716-446655440000

Query Parameters:

  • session_uuid - Active import session UUID

Response 204: No content


Rate Limiting

🚧 Rate limiting is not yet implemented.

Future rate limits:

  • 100 requests per minute per IP
  • 1000 requests per hour per IP

Pagination

🚧 Pagination is not yet implemented.

Future pagination:

GET /proxy-hosts?page=1&per_page=20

Filtering and Sorting

🚧 Advanced filtering is not yet implemented.

Future filtering:

GET /proxy-hosts?enabled=true&sort=created_at&order=desc

Webhooks

🚧 Webhooks are not yet implemented.

Future webhook events:

  • proxy_host.created
  • proxy_host.updated
  • proxy_host.deleted
  • remote_server.unreachable
  • import.completed

SDKs

No official SDKs yet. The API follows REST conventions and can be used with any HTTP client.

JavaScript/TypeScript Example

const API_BASE = 'http://localhost:8080/api/v1';

// List proxy hosts
const hosts = await fetch(`${API_BASE}/proxy-hosts`).then(r => r.json());

// Create proxy host
const newHost = await fetch(`${API_BASE}/proxy-hosts`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    domain: 'example.com',
    forward_host: 'localhost',
    forward_port: 8080
  })
}).then(r => r.json());

// Test remote server
const testResult = await fetch(`${API_BASE}/remote-servers/${uuid}/test`, {
  method: 'POST'
}).then(r => r.json());

Python Example

import requests

API_BASE = 'http://localhost:8080/api/v1'

# List proxy hosts
hosts = requests.get(f'{API_BASE}/proxy-hosts').json()

# Create proxy host
new_host = requests.post(f'{API_BASE}/proxy-hosts', json={
    'domain': 'example.com',
    'forward_host': 'localhost',
    'forward_port': 8080
}).json()

# Test remote server
test_result = requests.post(f'{API_BASE}/remote-servers/{uuid}/test').json()

Support

For API issues or questions: