Home / Docs / API Reference

API Reference

Solo & Teams

REST API for config sync, server memory, AI proxy, and team management. Available on the Solo and Teams plans.

Who is this page for?

You almost certainly don't need raw HTTP to use Servonaut. Pick the right surface:

  • Managing servers interactively? Use the TUI — just run servonaut. It wraps every endpoint on this page (login, config sync, memory sync, AI chat, teams).
  • Scripting or CI? The CLI subcommands (servonaut login, servonaut ai, servonaut memory, servonaut connect) already handle auth, retries, and exit codes for you.
  • Building an AI agent? Prefer the MCP server over hand-rolled HTTP — it exposes these capabilities as guarded, audited tools.

This reference is for everyone else: custom integrations, dashboards, and automation that needs to call the API directly.

Base URL

All endpoints are served from https://servonaut.dev. Paths are grouped by prefix:

  • /api/v1/* — versioned REST API (configs, teams, server memory, health).
  • /api/oauth/* — OAuth 2.0 device flow (unversioned, stable).
  • /api/ai/* — Servonaut AI proxy (unversioned).
  • /api/cli/* — CLI relay endpoints (heartbeat, connection status, relay subscription token).
  • /api/entitlements — current user entitlements snapshot.
  • /api/v1/billing/* — subscription checkout, billing portal, and subscription status (Bearer token required).
  • /mcp/* — MCP server (SSE transport for AI tool calls).

Authentication

Servonaut uses OAuth 2.0 Device Flow (RFC 8628) for authentication. This flow is designed for CLI tools and devices that cannot open a browser themselves.

You probably don't need to implement this

servonaut login runs this entire flow for you — fully headless if needed. It prints a verification URL and short code you can approve from a browser on any device (--no-browser skips opening one locally, --force re-authenticates). Tokens are stored at ~/.servonaut/auth.json (mode 0600) and shared by every CLI subcommand, the MCP server, and the TUI — sign in once per machine. servonaut logout revokes the session and removes the local tokens. Implement the raw flow below only if you are building your own client.

Device flow steps

  1. The CLI requests a device code from POST /api/oauth/device.
  2. The user opens the verification URL in a browser and enters the user code.
  3. The CLI polls POST /api/oauth/token until the user approves.
  4. On approval, the CLI receives an access token and a refresh token.
Step 1: Request a device code
$ curl -X POST https://servonaut.dev/api/oauth/device \ -H "Content-Type: application/json" \ -d '{"client_id": "servonaut-cli"}' { "device_code": "Ag_EE...j5gM", "user_code": "XKCD-1234", "verification_uri": "https://servonaut.dev/api/oauth/verify", "expires_in": 900, "interval": 5 }
Step 3: Poll for the token
$ curl -X POST https://servonaut.dev/api/oauth/token \ -H "Content-Type: application/json" \ -d '{ "grant_type": "urn:ietf:params:oauth:grant-type:device_code", "device_code": "Ag_EE...j5gM" }' # On approval: { "access_token": "snaut_live_...", "refresh_token": "snaut_refresh_...", "token_type": "Bearer", "expires_in": 3600, "scope": "read write" }

While the user has not yet approved, the token endpoint returns authorization_pending (HTTP 400). If the CLI polls faster than the advertised interval, the server responds with slow_down and a new minimum interval — always honor both. The expires_in value in the token response reflects the access token lifetime (default 3600 seconds). Use the refresh token to obtain a new access token before it expires; refresh tokens are valid for 30 days and rotate on each use.

Refreshing an access token

POST /api/oauth/refresh
$ curl -X POST https://servonaut.dev/api/oauth/refresh \ -H "Content-Type: application/json" \ -d '{ "grant_type": "refresh_token", "refresh_token": "snaut_refresh_..." }'

Tokens can be revoked at any time via POST /api/oauth/revoke — this is what servonaut logout calls before deleting the local token file.

Using the access token

Include the token as a Bearer credential in the Authorization header on every API request.

bash
$ curl https://servonaut.dev/api/entitlements \ -H "Authorization: Bearer snaut_live_..."

Config Sync

Store, list, and restore versioned snapshots of your ~/.servonaut/config.json from the Servonaut cloud. In the TUI this is the Sync Config screen (Pull Latest / Push New / Restore / Rename / Delete). Snapshots are encrypted on your machine with a passphrase only you know before they are uploaded — the server only ever stores ciphertext and cannot decrypt it.

Endpoints

MethodPathDescription
GET /api/v1/configs List your config snapshots (paginated).
GET /api/v1/configs/latest Get the most recent snapshot.
GET /api/v1/configs/{id} Get a specific snapshot by id.
POST /api/v1/configs Push a new config snapshot.
POST /api/v1/configs/{id}/restore Restore a specific snapshot as the active config.
PATCH /api/v1/configs/{id} Update a snapshot's label.
DELETE /api/v1/configs/{id} Delete a snapshot.
Push a config snapshot
$ curl -X POST https://servonaut.dev/api/v1/configs \ -H "Authorization: Bearer snaut_live_..." \ -H "Content-Type: application/json" \ -d '{"config": {...}, "label": "before-migration"}' { "id": "snap_01JQ...", "created_at": "2026-03-23T12:00:00Z", "label": "before-migration" }

Billing

Manage your subscription, open the Stripe billing portal, and read your current plan entitlements. All four endpoints require a Bearer token. The checkout and portal endpoints return short-lived hosted URLs — open them in a browser.

Endpoints

MethodPathDescription
POST /api/v1/billing/checkout Start a Stripe Checkout session for a new subscription. Body: {"plan": "solo"|"teams", "interval": "monthly"|"yearly"}. Returns {"checkout_url": "..."}.
POST /api/v1/billing/portal Open the Stripe customer portal (cancel, update payment method, download invoices). Returns {"portal_url": "..."}. Requires an existing subscription.
GET /api/v1/billing/subscription Current subscription record: plan, billing interval, status, seat count, period dates, and cancellation timestamp. Returns {"subscription": null} when no active subscription exists.
GET /api/v1/billing/entitlements Full entitlements snapshot for the authenticated user (same shape as GET /api/entitlements but served under the versioned billing prefix).

Server Memory

Persisted snapshots of each managed server's OS, runtime, services, and configuration. Used by both the CLI and the AI proxy as ground-truth context. The servonaut memory subcommands (build, refresh, show, pin, annotate, export, clear) and the TUI's Fleet Memory and Memory Sync screens are the usual clients of these endpoints. Memory annotations and agent-recorded findings sync across your machines and within teams through the same sync channel.

MethodPathDescription
GET /api/v1/memory List your managed instances and their latest snapshot times.
POST /api/v1/memory/instances Register or update an instance.
POST /api/v1/memory/sync Push a batch of module snapshots collected by the CLI.
GET /api/v1/memory/{instance_id} List modules available for an instance.
GET /api/v1/memory/{instance_id}/{module} Latest snapshot of a single module.
GET /api/v1/memory/{instance_id}/{module}/history Snapshot history for a module (paid plans).
POST /api/v1/memory/{instance_id}/restore/{snapshot_id} Restore a prior snapshot as the active state.
GET /api/v1/memory/drift List detected configuration drift events.
GET /api/v1/memory/anomalies List detected anomalies awaiting acknowledgement.
GET /api/v1/memory/fleet Fleet-wide rollup across all instances.
DELETE /api/v1/memory/{instance_id} Soft-delete an instance and all its module snapshots. Add ?module=name to delete a single module only.
GET /api/v1/memory/{instance_id}/{module}/at/{snapshot_id} Retrieve a specific historical snapshot by its id. Solo & Teams
POST /api/v1/memory/anomalies/{id}/ack Acknowledge an anomaly event. Solo & Teams
POST /api/v1/memory/drift/{id}/ack Acknowledge a configuration drift event. Solo & Teams
GET /api/v1/memory/settings Read your server-memory sync settings (retention window, module allow-list, etc.).
PATCH /api/v1/memory/settings Update your server-memory sync settings.
GET /api/v1/memory/export Download a signed compliance-export archive (tar + manifest) of all your memory data. Teams plan
GET /api/v1/memory/export-signing-key Returns the Ed25519 public key used to sign export manifests. Public — no Bearer token required. Use this to verify a downloaded archive offline.
POST /api/v1/memory/keys Upload (or replace) your memory keypair. The server stores your wrapped private key; plaintext never leaves your machine.
GET /api/v1/memory/keys/me Fetch your active memory keypair (public key + server-wrapped private key) for use on a new device.
POST /api/v1/memory/keys/rotate Generate a new keypair and retire the current one. All future sync envelopes use the new key.
GET /api/v1/memory/keys/team/{slug} List the public keys of all accepted team members (for client-side re-encryption when sharing memory). Teams plan
GET /api/v1/memory/ai-provider-info Returns the AI provider name and retention policy that applies when using AI summaries. Clients must show this to users before requesting a consent token. Teams plan
POST /api/v1/memory/summary/{instance_id}/consent Issue a short-lived consent token authorising a single AI summary run for an instance. Body must include mode, provider_ack: true (after showing the user the /ai-provider-info disclosure), and optionally modules. Teams plan
POST /api/v1/memory/summary/{instance_id} Dispatch an AI summary job for an instance. Requires a consent token from the /consent endpoint above plus your memory passphrase. Returns immediately with {"status": "queued"}. Teams plan
GET /api/v1/memory/summary/{instance_id}/latest Fetch the most recent AI summary envelope for an instance. Returns 404 until the first summary has been generated. Teams plan

Servonaut AI Solo & Teams

Hosted AI proxy — chat, log analysis, server triage, and tool-use via the CLI relay. Requires an active Solo or Teams subscription. Requests are authenticated with your Bearer token. Spend is metered against your monthly budget; query GET /api/entitlements for current budget and usage.

For scripting, prefer servonaut ai chat <prompt> over calling /api/ai/chat directly — it handles SSE streaming (--stream), tool execution opt-in (--tools / --no-tools), and returns documented exit codes (2 unauthenticated, 3 entitlement, 4 quota, 5 budget). servonaut ai conversations wraps the conversation list/show/export/archive/delete endpoints below.

The set of tools the model may call is filtered server-side by your plan: dangerous-tier tools (server create/delete, file transfer, instance termination, IP-ban writes) are only offered when your account has the dangerous-AI-tools opt-in enabled on the website. Automation calling /api/ai/chat directly will see the same filtering. When tool calls are dispatched to one of your machines, a relay listener (servonaut connect, or the TUI's built-in listener) must be running there; headless listeners auto-approve tool calls only up to the guard tier you configure locally and deny anything above it.

Endpoints

MethodPathDescription
POST /api/ai/chat Streaming AI chat (Server-Sent Events). JSON body with a messages array.
POST /api/ai/chat/tool-result Return the result of a tool call back to an in-flight conversation.
GET /api/ai/conversations List your AI conversation history (paginated).
GET /api/ai/conversations/{id} Retrieve a single conversation with all messages.
PATCH /api/ai/conversations/{id} Rename or tag a conversation.
DELETE /api/ai/conversations/{id} Delete a conversation.
GET /api/ai/conversations/{id}/export.json Export a conversation as JSON.
GET /api/ai/conversations/{id}/export.md Export a conversation as Markdown.
GET /api/ai/topup/packs List the available top-up packs (key, label, token count, price in cents). Returns 503 when AI is disabled. Bearer token required.
POST /api/ai/topup/checkout Start a checkout to purchase an AI top-up pack; returns a hosted payment URL to open in a browser. Requires an active Solo or Teams subscription.

servonaut ai topup [small|large] wraps the checkout endpoint and opens the payment URL for you; after purchase your balance refreshes automatically within about a minute. servonaut ai quota --json prints your current token quota, top-up balance, and reset date.

Entitlements

A single read endpoint that returns the user's current plan, feature flags, quotas, and AI budget. The CLI caches this response and re-fetches it on demand. New fields are added over time without breaking existing consumers.

Treat the response as additive: read the fields you know (plan, feature flags, AI budget and usage, the dangerous-AI-tools opt-in flag) with safe defaults, and ignore keys you don't recognize — new ones will appear between releases without notice. Never fail hard on an unknown field.

GET /api/entitlements
$ curl https://servonaut.dev/api/entitlements \ -H "Authorization: Bearer snaut_live_..."

Teams

Team management endpoints are available on the Teams plan. Teams are addressed by slug.

Team lifecycle

MethodPathDescription
GET /api/v1/teams List teams you belong to.
POST /api/v1/teams Create a new team.
GET /api/v1/teams/{slug} Get team details, members, and quotas.
PUT /api/v1/teams/{slug} Update team name or settings.
DELETE /api/v1/teams/{slug} Delete a team.
GET /api/v1/teams/{slug}/audit Retrieve the team audit trail (paginated).

Team members

MethodPathDescription
POST /api/v1/teams/{slug}/members Invite a new member by email.
POST /api/v1/teams/{slug}/members/{memberId}/resend Resend a pending invitation email.
PUT /api/v1/teams/{slug}/members/{memberId} Update a member's role (owner, admin, member).
DELETE /api/v1/teams/{slug}/members/{memberId} Remove a team member.

Team-shared servers, configs, and memory

MethodPathDescription
GET /api/v1/teams/{slug}/servers List servers shared with the team.
POST /api/v1/teams/{slug}/servers Share a server with the team.
GET /api/v1/teams/{slug}/configs List shared team config snapshots.
GET /api/v1/teams/{slug}/memory List server-memory instances visible to the team.
PUT /api/v1/teams/{slug}/ssh-config Update the team's shared SSH configuration.
GET /api/v1/teams/{slug}/secrets-config Read the team's secrets-manager configuration.

CLI relay

The /api/cli/* endpoints back the relay connection that lets hosted AI chats and team-mates dispatch tool calls to your machines. servonaut connect (or the TUI, which starts a listener automatically after login) manages the whole lifecycle — heartbeats, subscription-token refresh, and reconnects — so most of these endpoints are wire-level internals you should not need to call directly.

The one endpoint worth polling from automation is connection health: GET /api/cli/status (Bearer token or browser session) reports both the local listener state and what the backend last heard, including a divergence warning when they disagree. servonaut connect --status prints the same information, and servonaut connect --reconnect heals a stale connection.

Health

GET /api/v1/health is a public, unauthenticated readiness probe. Returns 200 OK with a JSON body when the application is serving traffic.

Rate limits and quotas

All authenticated endpoints are rate-limited per user. Exact limits are operational and may change between releases — don't hardcode assumptions; treat a 429 as the signal. The OAuth device-flow endpoints are limited more strictly: honor the advertised interval and back off whenever you receive a slow_down response.

When a limit is exceeded the endpoint responds with 429 Too Many Requests and a rate_limited error body. Back off and retry after a short delay.

Snapshot-count and AI-spend quotas are plan-specific and surfaced through GET /api/entitlements. The pricing page lists the current per-plan limits.

Error responses

All errors use a consistent JSON envelope: an error code (machine-readable), a human-readable message, and — where applicable — extra fields like upgrade_url, required_tier, or retry_after.

Common error codes

HTTP statusError codeDescription
400invalid_requestMalformed request body or missing required field.
401unauthorizedInvalid or expired access token.
402payment_requiredThe endpoint requires a paid plan. Body includes upgrade_url.
403forbiddenNo access token supplied, or the token lacks permission for the requested resource.
403forbidden_entitlementYour plan does not include this feature. Body includes upgrade_url.
404not_foundResource does not exist.
422validation_failedRequest body failed validation. Body may include a fields map.
429rate_limitedRate limit exceeded. Retry after Retry-After seconds.
429quota_exceededPlan quota exhausted (snapshots, instances, AI spend, etc.).
503feature_disabledThe feature is temporarily unavailable. Honor the Retry-After header.
503service_unavailableThe AI subsystem is switched off. Retrying won't help until it's re-enabled.
503upstream_unavailableAll AI providers are temporarily unreachable. Safe to retry with backoff.
500internal_errorServer error. Report to support.

Example envelopes

402 Payment Required
HTTP/1.1 402 Payment Required Link: <https://servonaut.dev/pricing>; rel="upgrade" Content-Type: application/json { "error": "payment_required", "message": "This feature requires a Solo or Teams subscription.", "required_tier": "solo", "upgrade_url": "https://servonaut.dev/pricing" }
403 Forbidden Entitlement
HTTP/1.1 403 Forbidden Content-Type: application/json { "error": "forbidden_entitlement", "message": "Your plan does not include Servonaut AI.", "upgrade_url": "https://servonaut.dev/pricing" }
429 Quota Exceeded
HTTP/1.1 429 Too Many Requests Content-Type: application/json { "error": "quota_exceeded", "message": "You have reached your plan's instance limit." }
503 Feature Disabled
HTTP/1.1 503 Service Unavailable Retry-After: 60 Content-Type: application/json { "error": "feature_disabled", "message": "This feature is temporarily unavailable. Please try again shortly." }
Documentation