Skip to main content
Browse the documentation

Platform concepts

Sessions

A session is one conversation with one agent; each message you send starts a run, and files can travel with it.

A session is a conversation with one agent — what the web app shows as a chat. It holds the transcript, and every message you send into it starts a run: the agent's work on that message. The run streams its progress while it happens and leaves its answer in the transcript when it finishes.

Sessions need the sessions:read scope to read and sessions:write to change; opening one and sending messages also need runs:create.

Opening a session

curl -X POST https://api.snaga.ai/api/v1/sessions \
  -H "Authorization: Bearer $SNAGA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"agent_id": "<agent_id>"}'

The answer is 201 with the session and its session_id. A new session is active and expires 24 hours after it is created. Two details are worth knowing:

  • If the same agent already has an active session created in the last 30 seconds with no messages and no runs, that one is returned with 200 instead of a new one. This absorbs double clicks.
  • Your plan limits how many sessions can be active at once; past it the call is 403.

Sending a message

curl -X POST https://api.snaga.ai/api/v1/sessions/<session_id>/messages \
  -H "Authorization: Bearer $SNAGA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"content": "Summarise this week'\''s competitor news"}'

The answer is 202 Accepted with a run_id. The agent works in the background; there are two ways to follow it:

StreamWhat it carries
GET /api/v1/runs/{runId}/eventsThe events of this one run.
GET /api/v1/sessions/{sessionId}/eventsEverything in the session: connected, run_added, each run's events, run_done, session_closed.

Both are Server-Sent Events. To resume after a dropped connection, send the last event id you received as Last-Event-ID. Ignore event names you do not recognise — that is how new ones arrive. See pagination and streaming.

Reading the transcript

GET /api/v1/sessions/{sessionId}/messages returns the conversation. Without limit you get the whole transcript. With limit (1–500) and cursor (an offset) you get one page, with has_more and the cursor for the next one; a cursor the platform cannot read is 400 INVALID_CURSOR. messages and items carry the same list, and total always counts the whole transcript, not the page. Each entry has a role (user, assistant, system or tool_result), its content, the run_id it belongs to, a timestamp, and a stable message_id. Assistant entries also carry the tools the run called.

If the agent is still working, the answer describes the run in flight, so a client opened mid-answer can attach to it instead of showing an idle chat. A session that does not exist is 404, never an empty list.

GET /api/v1/sessions/{sessionId}/export gives the conversation as md (the default) or json (?format=json).

Attaching files

Files are uploaded first, then referenced by id in a message. Upload as multipart/form-data or as base64 JSON; an upload can be up to 50 MiB.

curl -X POST https://api.snaga.ai/api/v1/files \
  -H "Authorization: Bearer $SNAGA_API_KEY" \
  -F "[email protected]"

The answer is 201 with the file's file_id, filename, mime_type, size_bytes and sha256. Then send it:

{ "content": "What are the three main risks in this report?", "file_ids": ["<file_id>"] }

content may be an empty string when file_ids has at least one id — a picture with no caption is an ordinary message. A message with neither text nor files is refused.

CallWhat it does
GET /api/v1/filesPages through your company's files; metadata only.
GET /api/v1/files/{fileId}One file's metadata.
GET /api/v1/files/{fileId}/contentThe bytes, with the file's own content type. Supports Range.
DELETE /api/v1/files/{fileId}Deletes the file. There is no undo.

Uploaded files stay until you delete them. Files an agent produces and its workspaces are covered in files and workspaces.

Organising sessions

GET /api/v1/sessions lists sessions; filter with agent_id, and page with limit and cursor. PUT /api/v1/sessions/{sessionId} changes what you can change about a session:

FieldEffect
archivedtrue hides it from the list (it stays readable by id); the next message unarchives it. List archived ones with ?archived=true or ?archived=all.
pinnedtrue pins it for every client; list pinned ones with ?pinned=true.
metadataA small label bag, merged into what is stored.

Sharing and branching

POST /api/v1/sessions/{sessionId}/share with {"role": "viewer"} (or "editor") creates a link anyone can open, optionally expiring after expires_in_hours. Each call creates a new link and the previous one stops working; DELETE on the same path revokes it.

POST /api/v1/sessions/{sessionId}/branch forks the conversation from an earlier run, so you can try a different direction without losing the original. Switch with PUT /api/v1/sessions/{sessionId}/branches/{branchId}/activate.

Closing a session

DELETE /api/v1/sessions/{sessionId} deletes the session and everything it owns: its runs and their events, its share link, its tasks, and the memories extracted from it. It cannot be undone. POST /api/v1/sessions/bulk-delete does the same for many sessions at once.

  • Runs — what happens after you send a message.
  • Agents — who you are talking to.
  • Memory and knowledge — what an agent remembers between sessions.