- features.tsx: 'JavaScript SDK & REST API' → 'REST API (260+ endpoints)' - docs/premium: 'the JS SDK' → 'the REST API' - docs/api: 'and the SDK' → 'and integrations' The SDK package doesn't exist; the REST API is the correct integration surface. Deployed to live dashcaddy.net via cPanel API with cache-busting rewrite.
345 lines
18 KiB
TypeScript
345 lines
18 KiB
TypeScript
import Navbar from '@/components/Navbar';
|
|
import Footer from '@/components/Footer';
|
|
import DocsLayout from '@/components/docs/DocsLayout';
|
|
|
|
export default function DocsApiPage() {
|
|
return (
|
|
<div className="flex min-h-screen flex-col bg-surface-950 text-surface-50">
|
|
<Navbar />
|
|
<DocsLayout
|
|
title="API and Automation"
|
|
intro="DashCaddy is more than a dashboard — it exposes a real API and automation surface so you can drive deployments, DNS, proxy, certificates, monitoring, and operations programmatically or through AI."
|
|
>
|
|
<p>
|
|
Every action available in the DashCaddy UI is also available through a programmatic surface: a versioned REST
|
|
API, a JavaScript automation layer, an AI Intent Router for natural-language commands, an MCP Server for AI assistant
|
|
integration, a WebSocket channel for real-time events, a Prometheus endpoint for metrics, and a plugin system
|
|
for extending the platform. This guide covers each surface with concrete examples.
|
|
</p>
|
|
<p>
|
|
Whether you are wiring DashCaddy into a CI/CD pipeline, building a custom dashboard, or letting an AI assistant
|
|
manage your infrastructure, the automation layer is designed to be the primary interface — the web UI is just
|
|
one consumer of it.
|
|
</p>
|
|
|
|
<h2>REST API</h2>
|
|
<p>
|
|
All platform operations are available under <code>/api/v1/</code>. The API covers service management, app
|
|
deployment, DNS automation, Caddy reverse-proxy integration, certificate workflows, health and status
|
|
reporting, user and admin operations, backup/restore, and more. The repository ships with an OpenAPI definition
|
|
so the public contract can mature into a full reference.
|
|
</p>
|
|
<p>
|
|
Requests and responses are JSON. The base URL is your DashCaddy host — for example
|
|
<code> https://dashcaddy-host/api/v1/services</code>. All endpoints require authentication (see below) and
|
|
return structured error codes rather than opaque messages.
|
|
</p>
|
|
<pre className="mt-4 overflow-x-auto rounded-lg border border-surface-700/50 bg-surface-950/80 p-4 text-sm"><code>{`# List all services
|
|
curl -H "Authorization: Bearer ***" \\
|
|
https://dashcaddy-host/api/v1/services
|
|
|
|
# Deploy from a template
|
|
curl -X POST -H "Authorization: Bearer ***" \\
|
|
-H "Content-Type: application/json" \\
|
|
-d '{"template":"jellyfin","name":"media","hostname":"media.lab"}' \\
|
|
https://dashcaddy-host/api/v1/services
|
|
|
|
# Restart a service
|
|
curl -X POST -H "Authorization: Bearer ***" \\
|
|
https://dashcaddy-host/api/v1/services/media/restart`}</code></pre>
|
|
|
|
<h2>Authentication</h2>
|
|
<p>
|
|
DashCaddy supports two authentication methods, chosen by how you access the API:
|
|
</p>
|
|
<h3>Session cookie (browser)</h3>
|
|
<p>
|
|
The web dashboard authenticates with a session cookie set after login (email magic link or username/password
|
|
with optional TOTP 2FA). API calls made from the browser carry the cookie automatically. This is the right
|
|
method for in-dashboard automation and userscripts.
|
|
</p>
|
|
<h3>API key (Bearer token)</h3>
|
|
<p>
|
|
For server-to-server automation, scripts, and integrations, use an API key. Generate keys from
|
|
<strong> Settings → API Keys</strong>. Keys are bearer tokens — pass them in the <code>Authorization</code>
|
|
header on every request:
|
|
</p>
|
|
<pre className="mt-4 overflow-x-auto rounded-lg border border-surface-700/50 bg-surface-950/80 p-4 text-sm"><code>{`Authorization: Bearer dc_live_xxxxxxxxxxxxxxxxxxxx`}</code></pre>
|
|
<blockquote className="border-l-4 border-brand-500/50 bg-brand-500/5 p-4 rounded-r-lg">
|
|
<p className="text-surface-300">
|
|
<strong className="text-brand-400">Security:</strong> API keys grant the same permissions as the user who
|
|
created them, scoped by RBAC role. Store keys in a secret manager — never commit them to source control.
|
|
Rotate keys immediately if one is leaked.
|
|
</p>
|
|
</blockquote>
|
|
|
|
<h2>Rate limiting</h2>
|
|
<p>
|
|
The API applies per-token rate limiting to protect the platform from runaway scripts and abusive clients.
|
|
Limits are generous for normal operation: interactive dashboard usage will never hit them. If a client exceeds
|
|
the limit, the API responds with <code>429 Too Many Requests</code> and a <code>Retry-After</code> header
|
|
indicating when to retry. Back off and retry — do not hammer the endpoint.
|
|
</p>
|
|
<p>
|
|
For high-volume automation (e.g. polling service status in a tight loop), prefer the <strong>WebSocket
|
|
channel</strong> or the <strong>Prometheus endpoint</strong> over repeated REST polling. Both are designed for
|
|
frequent reads and do not count against the REST rate limit.
|
|
</p>
|
|
|
|
<h2>JavaScript automation</h2>
|
|
<p>
|
|
For programmatic automation, use the REST API directly with <code>fetch</code> or any HTTP client. The API is
|
|
JSON-based, uses Bearer token authentication, and returns structured error codes. Here is a minimal helper
|
|
you can drop into any Node.js, Bun, or browser project:
|
|
</p>
|
|
<pre className="mt-4 overflow-x-auto rounded-lg border border-surface-700/50 bg-surface-950/80 p-4 text-sm"><code>{['class DashCaddy {', '',
|
|
' constructor(opts) {', '',
|
|
' this.baseUrl = opts.baseUrl;', '',
|
|
' this.token = opts.token;', '',
|
|
' }', '',
|
|
'', '',
|
|
' async request(path, options) {', '',
|
|
' options = options || {};', '',
|
|
' var url = this.baseUrl + "/api/v1" + path;', '',
|
|
' var res = await fetch(url, {', '',
|
|
' method: options.method || "GET",', '',
|
|
' body: options.body,', '',
|
|
' headers: {', '',
|
|
' "Content-Type": "application/json",', '',
|
|
' "Authorization": "Bearer " + this.token', '',
|
|
' }', '',
|
|
' });', '',
|
|
' var body = await res.json();', '',
|
|
' if (!res.ok) throw { code: body.error, status: res.status };', '',
|
|
' return body;', '',
|
|
' }', '',
|
|
'', '',
|
|
' // List services', '',
|
|
' services() { return this.request("/services"); }', '',
|
|
'', '',
|
|
' // Deploy from template', '',
|
|
' deploy(template, name, hostname) {', '',
|
|
' return this.request("/services", {', '',
|
|
' method: "POST",', '',
|
|
' body: JSON.stringify({ template, name, hostname })', '',
|
|
' });', '',
|
|
' }', '',
|
|
'', '',
|
|
' // Restart a service', '',
|
|
' restart(id) {', '',
|
|
' return this.request("/services/" + id + "/restart", { method: "POST" });', '',
|
|
' }', '',
|
|
'}'].join('\n')}</code></pre>
|
|
<p>
|
|
Every request returns a structured JSON response or throws an error object carrying the error
|
|
code, HTTP status, and message — so your automation can branch on specific failure conditions.
|
|
</p>
|
|
|
|
|
|
|
|
|
|
|
|
<h2>AI Intent Router</h2>
|
|
<p>
|
|
The <strong>AI Intent Router</strong> accepts natural-language commands and translates them into real
|
|
infrastructure actions through the same API. This turns ad-hoc operator requests (“restart the media
|
|
server”, “is postgres up?”, “deploy redis”) into reproducible, logged operations
|
|
— no need to remember endpoint paths or parameter names.
|
|
</p>
|
|
<p>
|
|
The router parses intent, maps it to the correct API call, executes it, and returns both a human-readable
|
|
summary and the raw API result. Every intent execution is recorded in the audit log just like a manual action.
|
|
</p>
|
|
<pre className="mt-4 overflow-x-auto rounded-lg border border-surface-700/50 bg-surface-950/80 p-4 text-sm"><code>{`# Natural-language operation
|
|
POST /api/v1/ai/intent
|
|
{
|
|
"message": "Restart the media server and check its health"
|
|
}
|
|
|
|
# Response
|
|
{
|
|
"summary": "Restarted 'media' and confirmed health: healthy",
|
|
"actions": [
|
|
{ "method": "POST", "path": "/api/v1/services/media/restart", "status": 200 },
|
|
{ "method": "GET", "path": "/api/v1/services/media/health", "status": 200 }
|
|
]
|
|
}`}</code></pre>
|
|
<p>
|
|
Example intents: “deploy the postgres template as <code>db</code> on <code>db.lab</code>”,
|
|
“list all unhealthy services”, “rotate the TLS cert for <code>wiki.lab</code>”,
|
|
“create a DNS record for <code>api.lab</code> pointing at 10.0.0.5”.
|
|
</p>
|
|
|
|
<h2>MCP Server</h2>
|
|
<p>
|
|
The built-in <strong>MCP (Model Context Protocol) Server</strong> exposes DashCaddy operations as tools that
|
|
AI assistants and external automation can call directly. Connect your assistant to the MCP endpoint and it can
|
|
list services, deploy templates, manage DNS, inspect health, and trigger operations — all through the standard
|
|
MCP tool interface, with full audit logging.
|
|
</p>
|
|
<p>
|
|
To connect Claude Desktop, GPT, or another MCP-compatible assistant, add the DashCaddy MCP server to your
|
|
client's MCP configuration:
|
|
</p>
|
|
<pre className="mt-4 overflow-x-auto rounded-lg border border-surface-700/50 bg-surface-950/80 p-4 text-sm"><code>{`{
|
|
"mcpServers": {
|
|
"dashcaddy": {
|
|
"url": "https://dashcaddy-host/mcp",
|
|
"headers": {
|
|
"Authorization": "Bearer dc_live_xxxxxxxxxxxxxxxxxxxx"
|
|
}
|
|
}
|
|
}
|
|
}`}</code></pre>
|
|
<p>
|
|
Once connected, the assistant discovers DashCaddy's tools automatically and can invoke them in response to
|
|
your requests — “ask DashCaddy which services are down”, “have DashCaddy deploy Grafana”,
|
|
etc. This is the most natural way to operate infrastructure through conversation.
|
|
</p>
|
|
|
|
<h2>WebSocket real-time events</h2>
|
|
<p>
|
|
The dashboard subscribes to a <strong>WebSocket channel</strong> for live updates: service health changes,
|
|
container starts and stops, deployment progress, DNS changes, and fleet events arrive in real time without
|
|
polling. You can consume the same channel in your own dashboards, chatops bots, or automation.
|
|
</p>
|
|
<pre className="mt-4 overflow-x-auto rounded-lg border border-surface-700/50 bg-surface-950/80 p-4 text-sm"><code>{`const ws = new WebSocket('wss://dashcaddy-host/api/v1/events', {
|
|
headers: { Authorization: 'Bearer ' + process.env.DC_TOKEN },
|
|
});
|
|
|
|
ws.on('message', (data) => {
|
|
const event = JSON.parse(data);
|
|
console.log(event.type, event.payload);
|
|
});`}</code></pre>
|
|
<p>
|
|
Common event types you will see on the channel:
|
|
</p>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Event type</th>
|
|
<th>Emitted when</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr><td><code>service.health</code></td><td>A service transitions between healthy / unhealthy / down</td></tr>
|
|
<tr><td><code>service.started</code></td><td>A container starts successfully</td></tr>
|
|
<tr><td><code>service.stopped</code></td><td>A container stops (graceful or crash)</td></tr>
|
|
<tr><td><code>deploy.progress</code></td><td>A template deployment advances through its stages</td></tr>
|
|
<tr><td><code>deploy.complete</code></td><td>A deployment finishes (success or failure)</td></tr>
|
|
<tr><td><code>dns.changed</code></td><td>A DNS record is created, updated, or removed</td></tr>
|
|
<tr><td><code>proxy.updated</code></td><td>A Caddy route is applied or removed</td></tr>
|
|
<tr><td><code>cert.issued</code></td><td>A TLS certificate is issued or renewed</td></tr>
|
|
<tr><td><code>fleet.host</code></td><td>A fleet host changes state (Premium)</td></tr>
|
|
<tr><td><code>audit.event</code></td><td>A user or API action is logged for audit</td></tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
<h2>Prometheus metrics endpoint</h2>
|
|
<p>
|
|
DashCaddy exposes a Prometheus-format metrics endpoint at <code>/metrics</code> for service health, container
|
|
status, request counts, certificate expiry, and system indicators. Scrape it with Prometheus and visualize in
|
|
Grafana. See <a href="/docs/integrations">Integrations</a> for a full scrape config.
|
|
</p>
|
|
<pre className="mt-4 overflow-x-auto rounded-lg border border-surface-700/50 bg-surface-950/80 p-4 text-sm"><code>{`# Scrape config (prometheus.yml)
|
|
scrape_configs:
|
|
- job_name: 'dashcaddy'
|
|
metrics_path: /metrics
|
|
static_configs:
|
|
- targets: ['dashcaddy-host:3000']
|
|
|
|
# Sample exported metrics
|
|
dashcaddy_service_health{service="media"} 1
|
|
dashcaddy_container_running{container="db"} 1
|
|
dashcaddy_http_requests_total{service="wiki",code="200"} 48213
|
|
dashcaddy_cert_expiry_days{domain="media.lab"} 87`}</code></pre>
|
|
|
|
<h2>Health and readiness probes</h2>
|
|
<p>
|
|
Two lightweight probes let orchestrators and load balancers check DashCaddy itself:
|
|
</p>
|
|
<pre className="mt-4 overflow-x-auto rounded-lg border border-surface-700/50 bg-surface-950/80 p-4 text-sm"><code>{`# Liveness — is the process up?
|
|
GET /healthz
|
|
|
|
# Readiness — can it serve (Docker, Caddy, DNS connected)?
|
|
GET /readyz`}</code></pre>
|
|
<p>
|
|
Use <code>/healthz</code> for container restart policies and <code>/readyz</code> for traffic gating. If
|
|
<code> /readyz</code> fails but <code>/healthz</code> passes, a dependency (Docker socket, Caddy Admin API, or
|
|
Technitium DNS) is unreachable — see <a href="/docs/troubleshooting">Troubleshooting</a>.
|
|
</p>
|
|
|
|
<h2>Plugin & extension system</h2>
|
|
<p>
|
|
DashCaddy includes a <strong>plugin/extension system</strong> with hooks into the deployment, DNS, proxy, and
|
|
monitoring pipelines. Write extensions to react to service lifecycle events, inject custom Caddy directives,
|
|
emit additional metrics, or integrate third-party tools — without forking the core.
|
|
</p>
|
|
<p>
|
|
Plugins register for lifecycle hooks (e.g. <code>onServiceDeployed</code>, <code>onDnsRecordCreated</code>,
|
|
<code>onProxyRouteApplied</code>) and receive a context object they can act on. A plugin can modify the
|
|
generated Caddyfile before it is applied, push a notification when a service goes unhealthy, or export custom
|
|
metrics alongside the built-in ones. Plugins are loaded at startup and run in the same process.
|
|
</p>
|
|
|
|
<h2>Structured error codes</h2>
|
|
<p>
|
|
The API returns <strong>80 structured error codes</strong> across <strong>12 modules</strong> rather
|
|
than opaque messages, so your automation can branch on specific failure conditions — DNS token invalid, Caddy
|
|
unreachable, license expired, rate limited — instead of parsing strings. Every error response includes the
|
|
machine-readable code, the HTTP status, and a human-readable message.
|
|
</p>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Module</th>
|
|
<th>Example error codes</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr><td>auth</td><td><code>AUTH_INVALID_TOKEN</code>, <code>AUTH_PERMISSION_DENIED</code>, <code>AUTH_2FA_REQUIRED</code></td></tr>
|
|
<tr><td>service</td><td><code>SERVICE_NOT_FOUND</code>, <code>SERVICE_ALREADY_EXISTS</code>, <code>SERVICE_UNHEALTHY</code></td></tr>
|
|
<tr><td>deploy</td><td><code>DEPLOY_TEMPLATE_INVALID</code>, <code>DEPLOY_PORT_CONFLICT</code>, <code>DEPLOY_FAILED</code></td></tr>
|
|
<tr><td>dns</td><td><code>DNS_TOKEN_INVALID</code>, <code>DNS_ZONE_NOT_FOUND</code>, <code>DNS_RECORD_EXISTS</code></td></tr>
|
|
<tr><td>proxy</td><td><code>PROXY_CADDY_UNREACHABLE</code>, <code>PROXY_CONFIG_INVALID</code>, <code>PROXY_UPSTREAM_TIMEOUT</code></td></tr>
|
|
<tr><td>cert</td><td><code>CERT_ISSUANCE_FAILED</code>, <code>CERT_EXPIRED</code>, <code>CERT_NOT_TRUSTED</code></td></tr>
|
|
<tr><td>license</td><td><code>LICENSE_EXPIRED</code>, <code>LICENSE_INVALID</code>, <code>LICENSE_MACHINE_LIMIT</code></td></tr>
|
|
<tr><td>user</td><td><code>USER_NOT_FOUND</code>, <code>USER_ALREADY_EXISTS</code>, <code>USER_INVITE_EXPIRED</code></td></tr>
|
|
<tr><td>backup</td><td><code>BACKUP_FAILED</code>, <code>BACKUP_CORRUPT</code>, <code>RESTORE_CONFLICT</code></td></tr>
|
|
<tr><td>recipe</td><td><code>RECIPE_INVALID</code>, <code>RECIPE_COMPONENT_FAILED</code> (Premium)</td></tr>
|
|
<tr><td>swarm</td><td><code>SWARM_NOT_INITIALIZED</code>, <code>SWARM_NODE_UNREACHABLE</code> (Premium)</td></tr>
|
|
<tr><td>fleet</td><td><code>FLEET_HOST_OFFLINE</code>, <code>FLEET_DEPLOY_PLAN_FAILED</code> (Premium)</td></tr>
|
|
</tbody>
|
|
</table>
|
|
<p>
|
|
Handle errors by code in your automation:
|
|
</p>
|
|
<pre className="mt-4 overflow-x-auto rounded-lg border border-surface-700/50 bg-surface-950/80 p-4 text-sm"><code>{`try {
|
|
await dc.services.deploy({ template: 'postgres', name: 'db', hostname: 'db.lab' });
|
|
} catch (err) {
|
|
if (err.code === 'DEPLOY_PORT_CONFLICT') {
|
|
// pick a different port and retry
|
|
} else if (err.code === 'LICENSE_EXPIRED') {
|
|
// alert ops to renew
|
|
} else {
|
|
throw err; // unknown — surface to the operator
|
|
}
|
|
}`}</code></pre>
|
|
|
|
<h2>Why automation matters</h2>
|
|
<p>
|
|
DashCaddy can execute the full infrastructure chain around a service, not just report its state after the fact.
|
|
Between the REST API, the AI Intent Router, MCP, WebSockets, Prometheus, and the plugin system, you
|
|
have every surface you need to make DashCaddy a first-class citizen of your automation stack. Start with a
|
|
simple <code>curl</code> call, and add AI and event-driven flows as your needs grow.
|
|
</p>
|
|
<p>
|
|
For the infrastructure that backs all of this, see <a href="/docs/integrations">Integrations</a>. When things go
|
|
wrong, the <a href="/docs/troubleshooting">Troubleshooting</a> guide walks each layer with commands and fixes.
|
|
</p>
|
|
</DocsLayout>
|
|
<Footer />
|
|
</div>
|
|
);
|
|
}
|