API Reference
Solo & TeamsREST API for config sync, server memory, AI proxy, and team management. Available on the Solo and Teams plans.
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.
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.
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
- The CLI requests a device code from
POST /api/oauth/device. - The user opens the verification URL in a browser and enters the user code.
- The CLI polls
POST /api/oauth/tokenuntil the user approves. - On approval, the CLI receives an access token and a refresh token.
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
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.
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
| Method | Path | Description |
|---|---|---|
| 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. |
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
| Method | Path | Description |
|---|---|---|
| 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.
| Method | Path | Description |
|---|---|---|
| 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
| Method | Path | Description |
|---|---|---|
| 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.
Teams
Team management endpoints are available on the Teams plan. Teams are addressed by slug.
Team lifecycle
| Method | Path | Description |
|---|---|---|
| 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
| Method | Path | Description |
|---|---|---|
| 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
| Method | Path | Description |
|---|---|---|
| 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 status | Error code | Description |
|---|---|---|
400 | invalid_request | Malformed request body or missing required field. |
401 | unauthorized | Invalid or expired access token. |
402 | payment_required | The endpoint requires a paid plan. Body includes upgrade_url. |
403 | forbidden | No access token supplied, or the token lacks permission for the requested resource. |
403 | forbidden_entitlement | Your plan does not include this feature. Body includes upgrade_url. |
404 | not_found | Resource does not exist. |
422 | validation_failed | Request body failed validation. Body may include a fields map. |
429 | rate_limited | Rate limit exceeded. Retry after Retry-After seconds. |
429 | quota_exceeded | Plan quota exhausted (snapshots, instances, AI spend, etc.). |
503 | feature_disabled | The feature is temporarily unavailable. Honor the Retry-After header. |
503 | service_unavailable | The AI subsystem is switched off. Retrying won't help until it's re-enabled. |
503 | upstream_unavailable | All AI providers are temporarily unreachable. Safe to retry with backoff. |
500 | internal_error | Server error. Report to support. |