Home / Docs / API Reference

API Reference

Premium

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

Base URL

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

  • /api/v1/* — versioned REST API (configs, teams, memory, billing, health, usage).
  • /api/oauth/* — OAuth 2.0 device flow (unversioned, stable).
  • /api/ai/* — Servonaut AI proxy (unversioned).
  • /api/cli/* — CLI relay endpoints (heartbeat, status, Mercure token).
  • /api/entitlements — current user entitlements snapshot.
  • /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.

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": 31536000, "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.

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.

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 configuration snapshots from the Servonaut cloud.

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" }

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.

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.

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.

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.
POST /api/ai/topup/checkout Create a Stripe Checkout session to purchase an AI top-up pack.

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.

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.

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, with a separate global circuit breaker on the OAuth device-flow endpoints. The active buckets and limits are defined in config/packages/rate_limiter.yaml and can change between releases — always consult the response headers below for the current state of your bucket.

Rate-limit headers are returned on every authenticated response:

Response headers
X-RateLimit-Limit: <requests in current window> X-RateLimit-Remaining: <requests left> X-RateLimit-Reset: <Unix timestamp when window resets> Retry-After: <seconds; only on 429>

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.
401unauthorizedMissing or invalid access token.
402payment_requiredThe endpoint requires a paid plan. Body includes upgrade_url.
403forbiddenToken does not have 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.
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