Cloud OS API
Complete reference for the Quazzar Cloud OS REST API. All endpoints use the /api/ prefix and require authentication unless noted otherwise. The base URL is your Cloud OS instance address (for example, http://localhost:8080/api/).
See Authentication for details on obtaining and using tokens.
Authentication
Endpoints for user setup, login, token management, TOTP two-factor authentication, and session management.
| Method | Path | Description |
|---|---|---|
POST | /api/auth/setup | Create the initial admin account (first boot only) |
POST | /api/auth/login | Authenticate and receive JWT tokens |
POST | /api/auth/refresh | Refresh an expired access token |
GET | /api/auth/me | Get the current authenticated user |
POST | /api/auth/change-password | Change the admin password |
POST | /api/auth/totp/enable | Enable TOTP two-factor authentication |
POST | /api/auth/totp/verify | Verify a TOTP code |
GET | /api/auth/sessions | List active sessions |
DELETE | /api/auth/sessions/{id} | Revoke a specific session |
Apps
Manage applications installed on the Cloud OS instance. Apps are deployed from templates as Docker containers and can be started, stopped, restarted, and monitored.
| Method | Path | Description |
|---|---|---|
GET | /api/apps | List all installed apps |
POST | /api/apps | Install a new app from a template |
GET | /api/apps/{appId} | Get app details |
DELETE | /api/apps/{appId} | Uninstall an app |
POST | /api/apps/{appId}/start | Start a stopped app |
POST | /api/apps/{appId}/stop | Stop a running app |
POST | /api/apps/{appId}/restart | Restart an app |
GET | /api/apps/{appId}/logs | Get app container logs |
GET | /api/apps/{appId}/stats | Get app resource usage statistics |
Example: Install an App
curl -X POST http://localhost:8080/api/apps \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"template": "nextcloud",
"name": "my-nextcloud",
"config": {
"admin_user": "admin",
"admin_password": "SecurePassword123"
}
}'{
"id": "app_abc123",
"name": "my-nextcloud",
"template": "nextcloud",
"status": "installing",
"created_at": "2025-01-15T10:30:00Z"
}Example: Get App Logs
curl "http://localhost:8080/api/apps/app_abc123/logs?lines=100&follow=false" \
-H "Authorization: Bearer <token>"Example: Get App Stats
curl http://localhost:8080/api/apps/app_abc123/stats \
-H "Authorization: Bearer <token>"{
"app_id": "app_abc123",
"cpu_percent": 2.5,
"memory_usage_mb": 256,
"memory_limit_mb": 1024,
"network_rx_bytes": 1048576,
"network_tx_bytes": 524288,
"disk_usage_mb": 512
}Templates
Browse the application template catalog. Templates define how apps are installed and configured.
| Method | Path | Description |
|---|---|---|
GET | /api/templates | List all available templates |
GET | /api/templates/categories | List template categories |
GET | /api/templates/{name} | Get details for a specific template |
Example: List Templates
curl http://localhost:8080/api/templates \
-H "Authorization: Bearer <token>"[
{
"name": "nextcloud",
"display_name": "Nextcloud",
"description": "Self-hosted productivity platform",
"category": "productivity",
"version": "28.0",
"icon": "nextcloud.svg"
},
{
"name": "gitea",
"display_name": "Gitea",
"description": "Lightweight self-hosted Git service",
"category": "development",
"version": "1.21",
"icon": "gitea.svg"
}
]System
Monitor system resources, hardware health, and performance metrics for the Cloud OS instance.
| Method | Path | Description |
|---|---|---|
GET | /api/system/metrics/current | Get current system resource usage (CPU, memory, disk) |
GET | /api/system/metrics | Get historical system metrics |
GET | /api/system/info | Get system information (OS, kernel, uptime) |
GET | /api/system/apps/metrics | Get aggregated metrics for all apps |
GET | /api/system/disk/health | Get disk health status (S.M.A.R.T.) |
GET | /api/system/disks | List all disks and partitions |
GET | /api/system/network/interfaces | List network interfaces |
Example: Get Current Metrics
curl http://localhost:8080/api/system/metrics/current \
-H "Authorization: Bearer <token>"{
"cpu": {
"usage_percent": 12.5,
"cores": 4,
"model": "Intel Xeon E-2236"
},
"memory": {
"total_mb": 16384,
"used_mb": 8192,
"usage_percent": 50.0
},
"disk": {
"total_gb": 500,
"used_gb": 120,
"usage_percent": 24.0
},
"uptime_seconds": 864000
}Example: Get System Info
curl http://localhost:8080/api/system/info \
-H "Authorization: Bearer <token>"{
"hostname": "cloud-os-01",
"os": "Ubuntu 22.04 LTS",
"kernel": "5.15.0-91-generic",
"architecture": "x86_64",
"quazzar_version": "0.2.9",
"uptime_seconds": 864000,
"node_id": "node_abc123"
}Backups
Create and manage backups of app data and system configuration. Supports local and remote backup targets.
| Method | Path | Description |
|---|---|---|
GET | /api/backups | List all backups |
POST | /api/backups | Create a new backup |
POST | /api/backups/{id}/restore | Restore from a backup |
GET | /api/backup/targets | List configured backup targets |
POST | /api/backup/targets | Add a backup target (local, S3, etc.) |
GET | /api/backup/schedule | Get the backup schedule |
Example: Create a Backup
curl -X POST http://localhost:8080/api/backups \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"target": "s3-primary",
"apps": ["app_abc123", "app_def456"],
"include_config": true
}'{
"id": "bak_abc123",
"status": "in_progress",
"target": "s3-primary",
"apps": ["app_abc123", "app_def456"],
"include_config": true,
"started_at": "2025-01-15T10:30:00Z"
}Example: Configure an S3 Backup Target
curl -X POST http://localhost:8080/api/backup/targets \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"name": "s3-primary",
"type": "s3",
"config": {
"bucket": "my-backups",
"region": "us-east-1",
"access_key": "AKIAIOSFODNN7EXAMPLE",
"secret_key": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"encryption": true
}
}'Domains
Manage custom domains and SSL certificates for apps running on the Cloud OS instance.
| Method | Path | Description |
|---|---|---|
GET | /api/domains | List all configured domains |
POST | /api/domains | Add a new domain |
PUT | /api/domains/{id} | Update a domain configuration |
DELETE | /api/domains/{id} | Remove a domain |
GET | /api/domains/{id}/ssl | Get SSL certificate status for a domain |
Example: Add a Domain
curl -X POST http://localhost:8080/api/domains \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"domain": "cloud.example.com",
"app_id": "app_abc123",
"auto_ssl": true
}'{
"id": "dom_abc123",
"domain": "cloud.example.com",
"app_id": "app_abc123",
"ssl": {
"status": "provisioning",
"provider": "letsencrypt"
},
"created_at": "2025-01-15T10:30:00Z"
}SSL certificates are automatically provisioned through the built-in Caddy reverse proxy when auto_ssl is enabled. Ensure your domain’s DNS A record points to the Cloud OS instance before adding it.
VPN
Manage the built-in WireGuard VPN server for secure remote access to the Cloud OS instance and its apps.
| Method | Path | Description |
|---|---|---|
GET | /api/vpn/provider | Get VPN server configuration |
POST | /api/vpn/provider | Configure the VPN server |
GET | /api/vpn/peers | List VPN peers (clients) |
POST | /api/vpn/peers | Create a new VPN peer |
DELETE | /api/vpn/peers/{id} | Remove a VPN peer |
GET | /api/vpn/peers/{id}/qrcode | Get a QR code for peer configuration |
Example: Create a VPN Peer
curl -X POST http://localhost:8080/api/vpn/peers \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"name": "my-laptop",
"dns": "1.1.1.1"
}'{
"id": "peer_abc123",
"name": "my-laptop",
"public_key": "aB1cD2eF3gH4...",
"allowed_ips": "10.0.0.2/32",
"config": "[Interface]\nPrivateKey = ...\nAddress = 10.0.0.2/32\nDNS = 1.1.1.1\n\n[Peer]\n..."
}The config field contains the full WireGuard configuration file content for the peer. You can also retrieve a QR code for easy mobile setup:
curl http://localhost:8080/api/vpn/peers/peer_abc123/qrcode \
-H "Authorization: Bearer <token>"Alerts
Configure alert rules and notification channels to monitor app and system health.
| Method | Path | Description |
|---|---|---|
GET | /api/alerts/rules | List alert rules |
POST | /api/alerts/rules | Create an alert rule |
GET | /api/alerts/channels | List notification channels |
POST | /api/alerts/channels | Create a notification channel |
POST | /api/alerts/channels/{id}/test | Send a test notification |
Example: Create an Alert Rule
curl -X POST http://localhost:8080/api/alerts/rules \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"name": "High CPU Usage",
"metric": "system.cpu.usage_percent",
"condition": "greater_than",
"threshold": 90,
"duration": "5m",
"channel_id": "ch_abc123",
"severity": "warning"
}'Example: Create a Notification Channel
curl -X POST http://localhost:8080/api/alerts/channels \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"name": "Ops Team Slack",
"type": "slack",
"config": {
"webhook_url": "https://hooks.slack.com/services/T00/B00/xxxx"
}
}'Security
Run security scans, view findings, and manage Web Application Firewall (WAF) rules.
| Method | Path | Description |
|---|---|---|
GET | /api/security/score | Get the overall security score |
POST | /api/security/scan | Trigger a security scan |
GET | /api/security/findings | List security findings |
GET | /api/waf/rules | List WAF rules |
Example: Get Security Score
curl http://localhost:8080/api/security/score \
-H "Authorization: Bearer <token>"{
"overall_score": 85,
"categories": {
"tls": 95,
"headers": 80,
"firewall": 90,
"authentication": 75,
"updates": 85
},
"findings_count": {
"critical": 0,
"high": 1,
"medium": 3,
"low": 5
}
}Example: Trigger a Security Scan
curl -X POST http://localhost:8080/api/security/scan \
-H "Authorization: Bearer <token>"{
"scan_id": "scan_abc123",
"status": "running",
"started_at": "2025-01-15T10:30:00Z"
}API Keys
Manage API keys for programmatic access to the Cloud OS instance.
| Method | Path | Description |
|---|---|---|
GET | /api/keys | List all API keys |
POST | /api/keys | Create a new API key |
DELETE | /api/keys/{id} | Revoke an API key |
See the Authentication page for detailed examples of creating and using API keys.
Webhooks
Configure outgoing webhooks to receive notifications when events occur on the Cloud OS instance.
| Method | Path | Description |
|---|---|---|
GET | /api/webhooks | List configured webhooks |
POST | /api/webhooks | Create a new webhook |
PUT | /api/webhooks/{id} | Update a webhook |
DELETE | /api/webhooks/{id} | Delete a webhook |
See Webhooks for detailed webhook setup, event types, and signature verification.
AI
Interact with locally hosted AI models for chat and RAG (Retrieval-Augmented Generation) search.
| Method | Path | Description |
|---|---|---|
GET | /api/ai/models | List available AI models |
POST | /api/ai/models/download | Download a new AI model |
POST | /api/ai/chat | Send a chat message to an AI model |
POST | /api/rag/search | Perform a RAG search over indexed documents |
Example: Chat with a Local AI Model
curl -X POST http://localhost:8080/api/ai/chat \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"model": "llama3",
"messages": [
{
"role": "user",
"content": "How do I configure Nextcloud to use external storage?"
}
]
}'Example: RAG Search
curl -X POST http://localhost:8080/api/rag/search \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"query": "backup encryption setup",
"limit": 5
}'Audit
View the audit log of all administrative actions performed on the Cloud OS instance.
| Method | Path | Description |
|---|---|---|
GET | /api/audit/logs | List audit log entries |
Example: Get Audit Logs
curl "http://localhost:8080/api/audit/logs?limit=50" \
-H "Authorization: Bearer <token>"[
{
"id": "aud_abc123",
"action": "app.installed",
"resource": "app_def456",
"details": "Installed Nextcloud from template",
"ip_address": "192.168.1.100",
"timestamp": "2025-01-15T10:30:00Z"
},
{
"id": "aud_def456",
"action": "backup.created",
"resource": "bak_ghi789",
"details": "Manual backup to s3-primary",
"ip_address": "192.168.1.100",
"timestamp": "2025-01-15T10:25:00Z"
}
]Audit logs are immutable and cannot be deleted through the API. They are retained according to the configured retention policy.
Memory MCP
Quazzar ships a built-in Model Context Protocol server. External AI clients (Claude Desktop, Claude Code, ChatGPT, Cursor, VS Code Copilot) connect with a bearer token and read/write durable memories backed by the same notes store the UI uses.
See Memory MCP for the tool / resource / prompt surface and Memory MCP quickstart for the wiring walkthrough.
MCP transport endpoints
| Method | Path | Description |
|---|---|---|
GET / POST | /mcp | Streamable HTTP MCP endpoint (MCP spec 2025-03+). Bearer authed. |
GET | /mcp/sse | Legacy SSE event stream for older clients. |
POST | /mcp/messages | Legacy SSE JSON-RPC sink paired with /mcp/sse. |
Authorization header on every request: Authorization: Bearer quaz_....
API keys
Session-authed endpoints (used by the Settings UI) for managing MCP bearer tokens.
| Method | Path | Description |
|---|---|---|
GET | /api/mcp/keys | List every key owned by the current user (metadata only — raw bearer is never returned) |
POST | /api/mcp/keys | Create a key. Raw bearer is returned in the response once. |
DELETE | /api/mcp/keys/{id} | Revoke a key. Immediate — the client loses access on the next request. |
POST | /api/mcp/keys/{id}/rotate | Revoke the existing key and mint a new one with the same name, scopes, namespace, and expiry window. Raw bearer is returned once. |
Create key
curl -X POST http://localhost:8080/api/mcp/keys \
-H "Authorization: Bearer <session-token>" \
-H "Content-Type: application/json" \
-d '{
"name": "Claude on my laptop",
"client_type": "claude_desktop",
"namespace": "work",
"scopes": ["read_memory", "write_memory"],
"expires_in_days": 90
}'{
"id": "key_abc123",
"name": "Claude on my laptop",
"client_type": "claude_desktop",
"namespace": "work",
"scopes": ["read_memory", "write_memory"],
"key_prefix": "quaz_AB12CDE",
"expires_at": "2026-07-21T10:30:00Z",
"raw": "quaz_AB12CDEFGH345JKLMNPQRSTVWXYZ2"
}The raw field is shown only on create and rotate. Raw bearers are bcrypt-hashed on disk.
Rotate key
curl -X POST http://localhost:8080/api/mcp/keys/key_abc123/rotate \
-H "Authorization: Bearer <session-token>"Returns the same shape as create, with a new raw bearer. The old bearer is revoked in place (ErrRevoked on use).
Active sessions
| Method | Path | Description |
|---|---|---|
GET | /api/mcp/sessions | List every live MCP stream bound to the current user |
DELETE | /api/mcp/sessions/{id} | Disconnect a specific session |
curl http://localhost:8080/api/mcp/sessions \
-H "Authorization: Bearer <session-token>"[
{
"id": "sess_abc",
"client_name": "claude-desktop",
"transport": "streamable-http",
"ip": "192.168.1.42",
"connected_at": "2026-04-21T10:10:00Z",
"last_active_at": "2026-04-21T10:30:00Z"
}
]Each MCP connection is tracked as a separate session — restarting a client opens a new one.
Embedding and analytics
| Method | Path | Description |
|---|---|---|
GET | /api/mcp/memory/embed-stats | Embedding backend status, queue depth, and coverage |
POST | /api/mcp/memory/reindex | Push every note owned by the caller onto the embedding queue |
GET | /api/mcp/memory/analytics | Aggregate totals, top tags, top clients, embedding coverage over time |
curl http://localhost:8080/api/mcp/memory/embed-stats \
-H "Authorization: Bearer <session-token>"{
"queue_size": 0,
"total": 1250,
"total_with_embedding": 1247,
"backend_name": "ollama",
"backend_dim": 768,
"enabled": true
}curl -X POST http://localhost:8080/api/mcp/memory/reindex \
-H "Authorization: Bearer <session-token>"{ "enqueued": 1250, "enabled": true }Pending items collapse via the queue’s UNIQUE(note_id) constraint, so triggering a reindex on a noisy node still completes in bounded work.
Cross-node sync (Orbit Pro)
| Method | Path | Description |
|---|---|---|
GET | /api/mcp/sync/status | List enabled namespaces, timestamps, and errors |
POST | /api/mcp/sync/enable | Body: { "namespace": "work" }. Opts the namespace in to replication |
POST | /api/mcp/sync/disable | Body: { "namespace": "work" }. Pauses but keeps cursor |
POST | /api/mcp/sync/resync | Body: { "namespace": "work" }. Forces one push + one pull pass |
POST | /api/mcp/sync/reset | Body: { "namespace": "work" }. Drops cursor and outbox |
Enable returns HTTP 402 Payment Required with the canonical upgrade shape when the caller is on the Community plan.
Notes graph
Session-authed endpoints for the Orbit Notes mind-map view.
| Method | Path | Description |
|---|---|---|
GET | /api/notes/graph | Return nodes + links with filter support |
PATCH | /api/notes/{id}/meta | Adjust importance or toggle archived on any note |
GET /api/notes/graph
Every filter on the Notes mind-map toolbar maps onto a query parameter:
| Param | Values | Default |
|---|---|---|
source | Comma-separated user,mcp,molly | all three |
namespace | Comma-separated namespace names | all |
client | Comma-separated mcp_client_name values | all |
tags | Comma-separated tag names | no filter |
min_importance | 0.0..1.0 | 0 |
include_archived | 1 / 0 | 0 |
curl "http://localhost:8080/api/notes/graph?source=user,mcp&namespace=work,personal&client=claude-desktop&tags=urgent,review&min_importance=0.4&include_archived=1" \
-H "Authorization: Bearer <session-token>"{
"nodes": [
{
"id": "note_abc",
"title": "Incident 2026-04-19",
"source": "mcp",
"namespace": "work",
"client": "claude-desktop",
"importance": 0.7,
"created_at": "2026-04-19T14:32:00Z",
"updated_at": "2026-04-19T14:32:00Z",
"last_referenced_at": "2026-04-20T09:10:00Z"
}
],
"links": [
{
"source": "note_abc",
"target": "note_def",
"source_kind": "mcp",
"target_kind": "user",
"mixed_sources": true
}
]
}PATCH /api/notes/{id}/meta
curl -X PATCH http://localhost:8080/api/notes/note_abc/meta \
-H "Authorization: Bearer <session-token>" \
-H "Content-Type: application/json" \
-d '{ "importance": 0.75 }'Accepted bodies:
{ "importance": 0.75 }— set importance to a0.0..1.0value.{ "archived": true }— appends#archived, drops importance to 0.{ "archived": false }— strips#archived, leaves importance untouched.
External MCP callers route through memory_update / memory_delete instead, which enforce per-key scope checks.
Molly memory
Session-authed endpoints for Molly’s memory slash commands and settings. Not MCP — external clients use /mcp instead.
| Method | Path | Description |
|---|---|---|
POST | /api/molly/memory/remember | Persist a new memory (body: content, title?, tags?, importance?) |
POST | /api/molly/memory/recall | Hybrid search bound to the user + Molly namespace |
GET | /api/molly/memory/recent?limit=N | List the N most recently referenced Molly memories |
POST | /api/molly/memory/clear | Soft-delete every memory in the Molly namespace |
DELETE | /api/molly/memory/mcp/{id} | Soft (default) or hard (?hard=true) delete a single memory |
curl -X POST http://localhost:8080/api/molly/memory/remember \
-H "Authorization: Bearer <session-token>" \
-H "Content-Type: application/json" \
-d '{
"content": "Deployed v0.6.35 to node-01.",
"title": "Deploy 2026-04-21",
"tags": ["deploy"],
"importance": 0.7
}'All endpoints return 503 Service Unavailable when the MCP Memory service is not wired (air-gap builds).
Billing and Licensing
Feature gates for the Orbit Pro paid tier. See Orbit Pro for the tier matrix.
| Method | Path | Description |
|---|---|---|
GET | /api/license/orbit-features | Projection of the current plan’s Orbit feature gate map |
POST | /api/billing/upgrade | Start a Stripe Checkout session (proxied through the CP) |
Feature gate projection
curl http://localhost:8080/api/license/orbit-features \
-H "Authorization: Bearer <session-token>"{
"plan": "community",
"features": {
"orbit_collab": false,
"orbit_graph": false,
"orbit_full_formulas": false,
"orbit_charts": false,
"orbit_pivot": false,
"orbit_history": false,
"orbit_advanced_export": false,
"orbit_memory_sync": false,
"orbit_unlimited_shares": false,
"orbit_slides_themes": false
},
"limits": {
"share_links_max": 3,
"mcp_rate_per_minute": 30,
"version_history_hours": 24
}
}The web client uses this to render gated controls before the user clicks.
Upgrade flow
curl -X POST http://localhost:8080/api/billing/upgrade \
-H "Authorization: Bearer <session-token>" \
-H "Content-Type: application/json" \
-d '{ "plan": "pro", "return_to": "https://node.example.com/docs" }'{
"checkout_url": "https://checkout.stripe.com/c/pay/cs_live_..."
}The request is proxied through the Control Panel to Stripe. After checkout, Stripe redirects to return_to with a session id. The CC agent picks up the new plan on the next heartbeat — the node’s license.Gate is wired to the agent’s plan accessor, so the feature unlocks on the next request without a restart.
Canonical 402 response
Every gated path returns HTTP 402 Payment Required on the Community plan with this shape:
{
"error": "upgrade_required",
"feature": "orbit_pivot",
"current_plan": "community",
"required_plan": "pro",
"message": "Pivot tables require Orbit Pro.",
"upgrade_url": "/api/billing/upgrade"
}Clients catch the 402 via isUpgradeError() and render either an inline <UpgradePrompt> or open a modal <OrbitUpgradeDialog> so the user can upgrade without losing the action that triggered the gate.