biga

HTTP API

The endpoints the CLI and the viewer use, with their limits and responses.

The CLI and the viewer talk to the same REST API under /api/sessions. It is stable enough to script against, but it is the protocol between biga's own programs, so treat it as an implementation detail that can change between releases.

Conventions

Every JSON response is wrapped in an envelope:

success
{ "ok": true, "data": { } }
failure
{ "ok": false, "error": { "code": "not_found", "message": "Session was not found." } }
Statuserror.codeMeaning
400invalid_requestThe body or a parameter is malformed. error.details names the field.
401unauthorizedA write without the session's owner token.
401access_key_required, access_key_invalidThe server requires an access key and none, or a wrong one, was sent.
403forbiddenThe owner token belongs to another session, or is wrong.
403session_lockedThe session has no owner token and accepts no writes. Start a new one.
404not_foundNo such session, checkpoint or file version.
409invalid_state, inactive_sessionThe session has ended.
413payload_too_large, storage_quota_exceededThe body is over the endpoint's limit, or the session is full.
415unsupported_encoding, unsupported_media_typeSend JSON, plain or gzip.
429rate_limitedSlow down. Retry-After says for how long.

Authentication

Reads are public. Holding a session's ID is the permission to watch it, which is what makes a link shareable without accounts.

Writes need the session's owner token. The response that creates a session carries a token, once:

PUT /api/sessions/k3f9zq2a → 201
{ "ok": true, "data": { "id": "k3f9zq2a", "status": "active", "token": "bgs_…", "shareUrl": "https://biga.example.com/session/k3f9zq2a" } }

The server keeps only a SHA-256 of it. Every later write to that session (reactivating it, snapshot, checkpoint, heartbeat, manifest, ending it) sends it as Authorization: Bearer bgs_…. The CLI stores it for you; see Sessions.

Servers may require an access key. When the operator configures access keys, every write also needs X-Biga-Key: bgk_…. The CLI sends BIGA_ACCESS_KEY. Viewers never need one.

Writes are checked before their body is read, and repeated bad tokens or keys from one client lock it out for a while.

Endpoints

Used by the CLI

Each needs the owner token, except creating a session.

MethodPathDoes
PUT/api/sessions/:idCreates the session (201, with its token), or reactivates it for its owner (200).
DELETE/api/sessions/:idEnds the session.
POST/api/sessions/:id/snapshotReplaces the whole tree. Answers 202.
POST/api/sessions/:id/checkpointRecords one batch of changes. Answers 202.
GET/api/sessions/:id/manifestPath, hash and size of every file, for rejoining. Never cached.
POST/api/sessions/:id/heartbeatSays the broadcast is still alive.

Used by the viewer

MethodPathDoes
GET/api/sessions/:idThe session's title and status.
GET/api/sessions/:id/stateSession, recent checkpoints, tree and, for small sessions, contents.
GET/api/sessions/:id/streamServer-sent events.
GET/api/sessions/:id/checkpointsA page of checkpoint summaries. limit, before.
GET/api/sessions/:id/checkpoints/:seqOne checkpoint with its changes.
GET/api/sessions/:id/fileA file's content. path, and ref: a SHA-256, latest or a checkpoint number.
GET/api/sessions/:id/file/historyThe checkpoints that touched a path. path, limit, before.

Uploads

Upload bodies are gzip-compressed when the server advertises support, by sending an Accept-Encoding: gzip response header (RFC 7694). A server that doesn't gets plain JSON, and a 415 makes the CLI fall back too.

EndpointLargest bodyRate limit
snapshot32 MiB15 per minute, per session
checkpoint8 MiB240 per minute, per session
PUT session16 KiB60 per hour, per client
heartbeatnone30 per minute, per session
any readnone3000 per minute, per client

Limits apply to the body after decompression. A client is an IPv4 address, or an IPv6 /64. Each text file's hash must be the SHA-256 of its content; paths must be relative, with no . or .. segments.

The CLI splits a large change set across several checkpoints, each under 6 MB uncompressed, so a branch switch stays inside the 8 MiB limit.

Events

GET /api/sessions/:id/stream is a text/event-stream. Each message has an event: name and a JSON data: payload with the event's type, sessionId and timestamp. Comment lines (: keepalive …) are sent periodically and carry nothing.

typePayload
connectedThe session ID and the server's time.
checkpointA full checkpoint: seq, label, counts and changes.
snapshotThe new tree.
session_endedNothing more. The stream closes after it.

The server closes the stream with session_ended when the broadcast has gone quiet for too long, and ends it when the client disconnects.