Skip to main content
snapr exposes a JSON HTTP API — the same one its web UI uses. Everything lives under the /api/v1 prefix on the address the server listens on (default 0.0.0.0:8080, see server configuration):
The endpoints in the left sidebar are generated from snapr’s OpenAPI document. A running instance serves the live version of that document at /api/v1/openapi, so you can always fetch the spec that matches your exact snapr version.

Authentication

The API uses session cookies backed by signed JWTs (HS256). Log in with POST /api/v1/auth/login:
A successful login returns {"success": true} and a Set-Cookie header with the snapr_session cookie (HttpOnly, Path=/). Send that cookie with every subsequent request. Wrong credentials return 401. Details worth knowing:
  • Sessions expire after server.auth.tokenExpiration minutes (default 30). When less than 5 minutes remain, any authenticated request gets a refreshed cookie in its response automatically.
  • POST /api/v1/auth/logout clears the cookie.
  • GET /api/v1/auth/check reports the current state: {"authenticated": true|false, "authEnabled": true|false}. It never requires a session.
  • Cookie attributes (Secure, SameSite, Domain) come from server.auth.cookies — see authentication configuration.
If server.secret is empty, snapr signs sessions with a random per-process key, so every restart invalidates all sessions. Set a stable secret in production.

When auth is disabled

If server.auth is absent or enabled: false, the session check is skipped entirely: every endpoint works without a cookie, and no login is needed. The auth endpoints stay reachable so clients can detect this mode — GET /api/v1/auth/check then returns {"authenticated": true, "authEnabled": false}.

Worked example

1

Log in and store the cookie

Skip this step if auth is disabled.
2

List jobs

3

Trigger a run

Returns 202 Accepted with {"job": "...", "startedAt": "..."} — the backup runs in the background. You get 403 if server.permissions.allowManualRun is off, and 409 if the job is already running. See permissions.
4

Download a backup

First list the snapshots, then download one by its filename (for split snapshots, use the set ID — see Splitter):
The response is either the archive bytes (200) or a 307 redirect to a signed storage URL (S3 signed mode, bunny.net Pull Zone) — pass -L so curl follows it.

Log streaming over SSE

Two endpoints stream logs as Server-Sent Events:
  • GET /api/v1/jobs/{name}/logs/stream — one job’s log
  • GET /api/v1/logs/system/stream — the system log
Both accept a tail query parameter (0–50,000): that many existing lines are replayed first, then the stream follows the log live. Both require a session cookie when auth is enabled. Every frame is a message event (the SSE default — no explicit event: name) whose data: field is a JSON object with a single key:
line is the rendered log line and may contain ANSI color codes. Behavior to expect:
  • A heartbeat frame with an empty line ({"line": ""}) is sent every 15 seconds to keep the connection alive.
  • If the requested log is disabled in config (logs.system: false or logs.perJob: false) or the job name is unknown, the stream sends a single message saying so and closes. See log configuration.
curl -N disables output buffering so you see lines as they arrive. In JavaScript, a plain EventSource works: listen for message events and parse event.data as JSON.

Endpoint groups

All paths above are relative to /api/v1. Full request and response schemas are in the generated pages in the sidebar, or live at /api/v1/openapi on your instance.