Skip to content

HTTP API

The web viewer exposes an HTTP API on port 8081 (configurable).

Authentication

Most endpoints require session-based authentication. Login via /api/login with OS credentials to receive a session cookie.

Endpoints

Public Endpoints

Method Path Auth Description
GET /health PUBLIC Health check
GET /login PUBLIC Login page
GET /logout PUBLIC Logout page
GET /api/security-context PUBLIC Security context check
POST /api/login PUBLIC Login API
GET /api/links/identity PUBLIC This gateway's public link identity
POST /api/links/accept PUBLIC Signed acceptance of this gateway's offer (the handler verifies)
POST /api/link/new PUBLIC A mailbox machine or the assistant connector of this account asks for a new link (the handler verifies the signature); it never links or gives a grant
GET /links/approve PUBLIC Approve another machine's link offer (the offer is in the URL fragment)
GET /static/{filename:.*} PUBLIC Static files
GET /.well-known/apple-app-site-association PUBLIC iOS Universal Links config (404 until app.ios_app_ids is set)
POST /api/email/ring PUBLIC The provisioner says email waits for this box (always 204; wakes the puller)
GET /api/phone/twiml/{call_id} PUBLIC TwiML that opens the media stream (Twilio fetches this)
GET /api/phone/media/{call_id} PUBLIC Twilio Media Stream WebSocket for a live call
POST /api/sms/inbound/{token} PUBLIC Inbound SMS webhook (Twilio, signature-verified)
POST /api/phone/voice/webhook/{token} PUBLIC Post-call webhook (ElevenLabs, one static URL; signature-verified in the daemon)
GET /api/phone/voice/webhook/{token} PUBLIC Post-call webhook (ElevenLabs, one static URL; signature-verified in the daemon)
GET /sw.js PUBLIC Push service worker (root scope)

Protected Endpoints

These endpoints require the auth type shown in the table.

Method Path Auth Description
GET /api/gateway/health TOKEN_OR_SESSION Aggregate gateway + per-user daemon serving health
GET /api/tunnel TOKEN_OR_SESSION Tunnel observability snapshot
GET /api/state/sessions TOKEN_OR_SESSION List monitored sessions
GET /api/state/sessions/{session_id} TOKEN_OR_SESSION Get monitored session
GET /api/state/sessions/{session_id}/parse TOKEN_OR_SESSION Parse session output
GET /api/state/sessions/{session_id}/capture TOKEN_OR_SESSION Get raw terminal content
POST /api/sessions/wait-any TOKEN_OR_SESSION Wait for any session attention
POST /api/sessions/{session_id}/respond TOKEN_OR_SESSION Send input to a session
POST /api/sessions/{session_id}/exit TOKEN_OR_SESSION Exit a session cleanly
POST /api/sessions/{session_id}/account TOKEN_OR_SESSION Move a Claude or Codex session to another account (resumes its conversation)
POST /api/sessions/{session_id}/restart TOKEN_OR_SESSION Restart a session's agent in place (resumes its conversation, same account)
POST /api/sessions/{session_id}/compact TOKEN_OR_SESSION Compact a session's agent context (/compact), now or at its next idle prompt
POST /api/sessions/{session_id}/goal TOKEN_OR_SESSION Set a session's agent /goal (or clear it), now or at its next idle prompt
POST /api/sessions/{session_id}/goal/pause TOKEN_OR_SESSION Pause a session's /goal for an agentwatch wait (wait --pause-goal)
POST /api/sessions/{session_id}/goal/resume TOKEN_OR_SESSION Set a paused /goal again: the wait ended, a cancel, or the operator
GET /api/sessions/{session_id}/context TOKEN_OR_SESSION How full a session's agent context is, from its transcript
POST /api/sessions/{session_id}/wait TOKEN_OR_SESSION Wait for session attention
POST /api/sessions/{session_id}/inbox TOKEN_OR_SESSION Send a text snippet to the inbox
POST /api/sessions/{session_id}/clipboard TOKEN_OR_SESSION Deprecated alias of /inbox
POST /api/sessions/{session_id}/share TOKEN_OR_SESSION Share a document to the inbox
POST /api/sessions/{session_id}/send TOKEN_OR_SESSION Send raw input to a session
POST /api/sessions/{session_id}/clear-input TOKEN_OR_SESSION Empty a session's input box
POST /api/sessions/{session_id}/scroll TOKEN_OR_SESSION Scroll a session (copy-mode)
GET /auth/token/{token} MAGIC_LINK Magic link login
GET /api/machines SESSION List known machines
POST /api/machines/validate SESSION Validate a remote machine before adding
POST /api/logout SESSION Logout
POST /api/auth/logout-user TOKEN_OR_SESSION End all web sessions of the calling user
GET /api/auth/sessions TOKEN_OR_SESSION List the calling user's live web login sessions
GET /api/whoami SESSION Get current user
GET /api/login-token API_TOKEN Generate magic link
POST /api/log SESSION Remote logging
GET /api/sessions STATUS_COOKIE List tmux sessions
GET /api/session/{session_id} SESSION Get session details
GET /api/capture/{session_id} TOKEN_OR_SESSION Capture session as PNG
GET /api/scroll/{session_id} TOKEN_OR_SESSION Capture scrollback as PNG
GET /api/inbox/{session_id} TOKEN_OR_SESSION List/clear notification inbox
DELETE /api/inbox/{session_id} TOKEN_OR_SESSION List/clear notification inbox
GET /api/clipboard/{session_id} TOKEN_OR_SESSION Deprecated alias of /api/inbox
DELETE /api/clipboard/{session_id} TOKEN_OR_SESSION Deprecated alias of /api/inbox
POST /api/mail/send TOKEN_OR_SESSION Send agent mail to [machine/]session
POST /api/mail/seal TOKEN_OR_SESSION Who to encrypt link mail for: the recipients' public mail keys
POST /api/mail/copies TOKEN_OR_SESSION Silent copies of a thread's messages for its other participants
POST /api/mail/drop TOKEN_OR_SESSION Send a sealed file or secret to a session here or over a link
POST /api/link/mail/send LINK Receive mail from a linked daemon; no read or control access
POST /api/link/mail/status LINK Read state of a message this link delivered; no mailbox read or control access
POST /api/link/mail/receipt LINK A mailbox machine's read receipt for mail this link carried; no mailbox read or control access
POST /api/link/mail/copy LINK Keep a silent thread copy from a linked daemon; no mailbox read or control access
POST /api/link/mail/returned LINK Mail this side sent over the link went back unread (its id and reason only); no mailbox read or control access
POST /api/ask TOKEN_OR_SESSION Give a repo a task, on this box or another machine: an ask, mail of the kind ask (agentwatch ask)
POST /api/link/ask LINK An ask from a linked daemon: start work in a repo that this side's ask grant reaches; no read or control access
POST /api/mail/{session_id} TOKEN_OR_SESSION Agent mailbox: send / peek / clear
GET /api/mail/{session_id} TOKEN_OR_SESSION Agent mailbox: send / peek / clear
DELETE /api/mail/{session_id} TOKEN_OR_SESSION Agent mailbox: send / peek / clear
POST /api/mail/{session_id}/get TOKEN_OR_SESSION Agent mailbox: read one message by id
GET /api/mail/{session_id}/status/{msg_id} TOKEN_OR_SESSION Agent mailbox: read receipt for a sent message
GET /api/mail/{session_id}/history TOKEN_OR_SESSION Recoverable mail owned by the caller
GET /api/mail/{session_id}/thread/{thread_id} TOKEN_OR_SESSION One mail thread as the caller's mailbox holds it, with its participants
GET /api/mail/{session_id}/threads TOKEN_OR_SESSION The mail threads that sessions of a repo took part in
POST /api/mail/{session_id}/recover TOKEN_OR_SESSION Recover mail into a live, caller-owned recipient
POST /api/links/offer SESSION_SAME_ORIGIN Start a link (password web login only)
POST /api/links/approve SESSION_SAME_ORIGIN Approve a link offer (password web login only)
GET /api/links TOKEN_OR_SESSION The caller's links
DELETE /api/links/{link_id}/grants/{permission} TOKEN_OR_SESSION Stop granting one permission
POST /api/links/{link_id}/grants SESSION_SAME_ORIGIN Change what this side grants
POST /api/links/{link_id}/board SESSION_SAME_ORIGIN Set what the other side's agents may do on your boards (widening: password web login only)
POST /api/links/{link_id}/modes SESSION_SAME_ORIGIN Give or stop giving files, secrets or the session list over a link (giving: password web login only)
POST /api/links/{link_id}/board/narrow TOKEN_OR_SESSION Lower a link's board level
POST /api/links/{link_id}/ask SESSION_SAME_ORIGIN Let the other side start work in your repos (the ask grant; on or a change: password web login only)
POST /api/links/{link_id}/requests TOKEN_OR_SESSION Ask the other side of a link for a grant
DELETE /api/links/{link_id}/requests/{request_id} SESSION_SAME_ORIGIN Take back a grant request you sent
POST /api/links/{link_id}/requests/{request_id}/approve SESSION_SAME_ORIGIN Give what the other side asked for (password web login only)
POST /api/links/{link_id}/requests/{request_id}/reject SESSION_SAME_ORIGIN Say no to a grant request
POST /api/links/{link_id}/give-back SESSION_SAME_ORIGIN Ask the other side to stop giving a grant
POST /api/board/remote TOKEN_OR_SESSION One call on a linked machine's project board, as a session the caller owns
POST /api/board/remote/seal TOKEN_OR_SESSION The seal plan of a remote board call: the links and the keys to seal for; no content
POST /api/sessions/remote TOKEN_OR_SESSION A list of the running sessions of linked machines, sealed to the caller
DELETE /api/links/{link_id} TOKEN_OR_SESSION Remove a link
POST /api/link/update LINK The other side changed or removed a link
POST /api/link/request LINK A linked side proposes, cancels or answers a grant request, or gives a grant back; it never raises a grant
POST /api/links/link-requests/{request_id}/approve SESSION_SAME_ORIGIN Link with the machine that asked (password web login only)
POST /api/links/link-requests/{request_id}/reject SESSION_SAME_ORIGIN Say no to a request for a new link
POST /api/link/board LINK A linked agent's clear board call (whoami, the answers record), at the link's board level; no other read or control access
POST /api/link/board/sealed LINK A linked agent's sealed call on this side's project boards; the board user's daemon opens it; no other read or control access
POST /api/link/mail/drop LINK Receive a sealed file or secret from a linked daemon; no read or control access
POST /api/link/sessions LINK A linked machine lists this side's running sessions (basic details, sealed to the asker); needs the list grant; no other read or control access
POST /api/link/sessions/roster LINK A mailbox machine's sealed list of its agents, kept unread for this side's user
GET /api/tasks TOKEN_OR_SESSION Stale-task monitor: long-running counts for every session
GET /api/tasks/{session_id} TOKEN_OR_SESSION Stale-task monitor: long-running shells/subagents for a session
POST /api/tasks/{session_id}/ack TOKEN_OR_SESSION Stale-task monitor: silence one long-running item
GET /api/fs/complete SESSION Autocomplete working directory
GET /api/fs/list/{session_id} TOKEN_OR_SESSION List files in the session's project dir
GET /api/fs/read/{session_id} TOKEN_OR_SESSION Read a file from the session's project dir
GET /api/fs/raw/{session_id} TOKEN_OR_SESSION Raw file bytes from the session's project dir (inline; ?download=1 to save)
POST /api/resize/{session_id} TOKEN_OR_SESSION Resize terminal
POST /api/upload/{session_id} TOKEN_OR_SESSION Upload file to session cwd
POST /api/secret/{session_id} TOKEN_OR_SESSION Leave a secret for the session's agent (shape only in the transcript)
POST /api/sessions/create TOKEN_OR_SESSION Create session (web or CLI)
POST /api/sessions/create-read-only TOKEN_OR_SESSION Create strict read-only unattended review (CLI only)
POST /api/sessions/resume TOKEN_OR_SESSION Reopen a closed session with its full context (session resume)
POST /api/sessions/{session_id}/terminate TOKEN_OR_SESSION Terminate session (web or CLI)
GET /api/session-configs SESSION Get session configs
DELETE /api/session-configs/{index} SESSION Delete session config
GET / SESSION Main app
GET /session/{session_name} SESSION Session deep link
GET /session/{session_name}/scrollback SESSION Session scrollback deep link
GET /session/{session_name}/keyboard SESSION Session keyboard deep link
GET /session/{session_name}/passenger SESSION Session passenger deep link
GET /tunnel SESSION Tunnel status page
GET /settings SESSION Per-user settings page
GET /accounts SESSION Accounts and usage status page
GET /links SESSION The viewer with the Links page in its right pane (links between daemons: grants, requests)
POST /api/accounts SESSION_SAME_ORIGIN Add a Claude setup token or an OpenRouter key (web login only)
GET /api/accounts/policy TOKEN_OR_SESSION The quota policy agents follow on this box
POST /api/deliveries/{session_id}/wait TOKEN_OR_SESSION The session's delivery hook waits for mail and alerts (#393)
GET /email SESSION Held email: review, show, deliver, always allow, delete (a password login acts)
GET /api/email/held SESSION The held email of each user with a password login, with the summaries the daemon opened
GET /api/email/history SESSION The email delivered in the last 30 days, with the summaries the daemon opened
GET /api/email/held/{email_id}/view SESSION One held email as a sandboxed HTML document (no script; remote images only with ?remote=1)
GET /api/email/held/{email_id}/attachment/{index} SESSION Download one attachment of a held email
GET /api/email/held/{email_id}/files SESSION The attachments of a held email (its row loads them when it opens)
POST /api/email/held/{email_id}/deliver SESSION_SAME_ORIGIN Deliver a held email to a live session of its user
POST /api/email/held/{email_id}/delete SESSION_SAME_ORIGIN Delete a held email and its files
POST /api/email/held/{email_id}/allow SESSION_SAME_ORIGIN Add a held email's sender to the allowlist, then deliver it
GET /api/email/unblock/{session_name} SESSION_SAME_ORIGIN Read (GET) or open/close (POST, password login) the 15-minute window in which any sender may email one session
POST /api/email/unblock/{session_name} SESSION_SAME_ORIGIN Read (GET) or open/close (POST, password login) the 15-minute window in which any sender may email one session
GET /history SESSION Finished automatic runs: what started each, its outcome, its conversation, Resume
GET /api/history TOKEN_OR_SESSION The caller's finished automatic runs (cron fires, watch wakes), newest first
GET /api/history/{run_id}/transcript TOKEN_OR_SESSION One page of a finished run's Claude conversation, read by the owner's daemon
POST /api/history/{run_id}/resume TOKEN_OR_SESSION Continue a finished run's conversation in a new live session
GET /api/human TOKEN_OR_SESSION Whether the owner is watching, on what device, their last input, and whether a notification would reach them
GET /api/location TOKEN_OR_SESSION Where the box owner is, their recent movement trail, the local time there, and how stale the fix is
GET /api/manager/status TOKEN_OR_SESSION Is the caller's manager session running
POST /api/manager/start TOKEN_OR_SESSION Start the manager session, or hand a running one a task
GET /api/pages TOKEN_OR_SESSION List the caller's pages, or publish one (tar.gz body; name, ttl, title, kind, session in the query)
POST /api/pages TOKEN_OR_SESSION List the caller's pages, or publish one (tar.gz body; name, ttl, title, kind, session in the query)
DELETE /api/pages/{name} TOKEN_OR_SESSION Delete one of the caller's pages
GET /pages SESSION Your pages: title, kind, session, expiry, size, Open and Delete
GET /pages/ SESSION Your pages (redirects to /pages)
GET /pages/{name} SESSION Open a page (redirects to /pages/{name}/)
GET /pages/{name}/~{token}/{tail:.*} PAGE_VIEW A page's file, sandboxed; the signed view link is the credential
GET /pages/{name}/{tail:.*} SESSION Open a page at a file: mint a view link and redirect to it (navigations only)
GET /api/phone/status TOKEN_OR_SESSION Phone channel readiness and any live call
GET /api/phone/settings SESSION The caller's phone settings, numbers in full (browser only)
PUT /api/phone/config TOKEN_OR_SESSION Store the caller's Twilio account, key and numbers
POST /api/phone/call TOKEN_OR_SESSION Ring the human and open a live conversation
POST /api/phone/say TOKEN_OR_SESSION Speak into the live call
POST /api/phone/hangup TOKEN_OR_SESSION End the live call
POST /api/phone/sms TOKEN_OR_SESSION Text the human from a session
POST /api/phone/test TOKEN_OR_SESSION Send yourself a test text
POST /api/phone/talk TOKEN_OR_SESSION Hold a full-duplex conversation through a provider-hosted voice agent
GET /api/phone/profiles TOKEN_OR_SESSION Call profiles resolved for this session
GET /api/phone/calls TOKEN_OR_SESSION Voice-call cost log: what each call cost, across every vendor
GET /api/push/config SESSION Push capability + VAPID public key
POST /api/push/subscribe SESSION Register a device push subscription
POST /api/push/unsubscribe SESSION Remove a device push subscription
GET /api/push/preferences SESSION Global notification preferences
PUT /api/push/preferences SESSION Global notification preferences
PUT /api/push/preferences/session/{session_name} SESSION Per-session notification override
POST /api/push/test TOKEN_OR_SESSION Send a test push to the caller's devices
POST /api/push/handoff BROWSER_HANDOFF Open this installed app via a user-requested notification to the requesting device
GET /api/schedules TOKEN_OR_SESSION List the caller's scheduled jobs
POST /api/schedules/cron TOKEN_OR_SESSION Create a durable cron job
POST /api/schedules/wakeup TOKEN_OR_SESSION Schedule, continue or stop a wakeup chain
POST /api/schedules/watch TOKEN_OR_SESSION Create a watch on GitHub threads
GET /api/schedules/{job_id} TOKEN_OR_SESSION Get, update or delete one scheduled job
PATCH /api/schedules/{job_id} TOKEN_OR_SESSION Get, update or delete one scheduled job
DELETE /api/schedules/{job_id} TOKEN_OR_SESSION Get, update or delete one scheduled job
GET /api/schedules/{job_id}/state TOKEN_OR_SESSION Read or replace a job's carried state
PUT /api/schedules/{job_id}/state TOKEN_OR_SESSION Read or replace a job's carried state
GET /api/schedules/{job_id}/brief TOKEN_OR_SESSION The running fire's full brief
POST /api/schedules/{job_id}/done TOKEN_OR_SESSION A fired session reports its result
POST /api/schedules/{job_id}/watch-report TOKEN_OR_SESSION A watch's running wake reports done or keep
GET /api/usage TOKEN_OR_SESSION Remaining Claude/Codex quota for the calling user
GET /api/whatsapp/status TOKEN_OR_SESSION WhatsApp channel readiness for the calling user
PUT /api/whatsapp/config TOKEN_OR_SESSION Set or clear the calling user's WhatsApp number
POST /api/whatsapp/send TOKEN_OR_SESSION Message the human in the session's repo group
POST /api/whatsapp/ask TOKEN_OR_SESSION Ask the human on WhatsApp and long-poll for the reply
POST /api/whatsapp/confirm TOKEN_OR_SESSION One-tap WhatsApp poll to confirm an understanding; long-poll for the tap
POST /api/whatsapp/screenshot TOKEN_OR_SESSION Send the session's terminal screenshot to the repo group
GET /api/code/status TOKEN_OR_SESSION VS Code Web availability for the calling user
GET /api/code/status/{session_id} TOKEN_OR_SESSION VS Code Web availability + deep link for one session
POST /api/code/stop TOKEN_OR_SESSION Stop the calling user's VS Code Web backend
GET /code/{username} SESSION VS Code Web (redirect to trailing slash)
ANY /code/{username}/{tail:.*} SESSION VS Code Web (proxied serve-web)
GET /api/board/status TOKEN_OR_SESSION Project boards of every user the caller is logged in as
GET /api/board/status/{session_id} TOKEN_OR_SESSION Project board link for one session's repo
GET /api/board/answers TOKEN_OR_SESSION The caller's recorded operator answers on a project board
GET /boards/{username} SESSION Open a user's project board (sets the board choice, redirects to /board)
GET /boards/{username}/{tail:.*} SESSION Open a user's project board at a deep link (sets the board choice, redirects)
ANY /board SESSION Project board (proxied Scotty)
ANY /board/{tail:.*} SESSION Project board (proxied Scotty)
GET /ws/{session_id} SESSION_SAME_ORIGIN WebSocket streaming
GET /api/github/status/{session_id} TOKEN_OR_SESSION GitHub repo link for a session's workdir

Endpoint Details

GET /health

Liveness check endpoint. Success and error envelopes are defined by agentwatch/server/utils/responses.py.

Response:

{
  "s": "ok",
  "client_version": "2026070618",
  "server_version": "0.62.0"
}

POST /api/login

Authenticate with OS credentials.

Request:

{
  "username": "user",
  "password": "password",
  "force": false
}

Response:

{
  "success": true,
  "username": "user"
}

If another session exists and force is false:

{
  "success": false,
  "session_exists": true,
  "existing_session": {
    "ip": "192.168.1.100",
    "hostname": "other-device.local",
    "location": "Local Network"
  }
}

GET /api/sessions

List all tmux sessions with detection info.

Response:

{
  "hostname": "macbook",
  "sessions": [
    {
      "session_id": "$0",
      "session_name": "coding-0",
      "created_at": 1707321600,
      "attached": false,
      "windows": 1,
      "cwd": "/home/user/project",
      "program": "Claude Code",
      "state": "Idle",
      "launched_by": "agent",
      "parent": "planner",
      "parent_alive": true,
      "cron_job": null,
      "launcher": "planner",
      "launcher_alive": true
    }
  ]
}

launched_by is the session's origin (web, cli, agent, cron, whatsapp, sms). parent is the parent session that launched a child session (null for any other origin), and parent_alive says whether it is a live session of the same user. The rows of GET /api/state/sessions also carry original_parent after a person took the session over.

Deprecated: launcher, launcher_alive and original_launcher carry the same values as parent, parent_alive and original_parent for one release. They go in #517.

GET /api/capture/{session_id}

Capture terminal as PNG image.

Response: image/png

GET /api/scroll/{session_id}

Capture scrollback buffer.

Query Parameters: - max_lines: Maximum lines to capture (default: 500, max: 2000)

Response:

{
  "type": "scroll_response",
  "png_base64": "iVBORw0KGgo...",
  "total_lines": 500,
  "pane_height": 24,
  "history_size": 2000,
  "cols": 80,
  "retina": true
}

POST /api/resize/{session_id}

Resize terminal dimensions.

Request:

{
  "cols": 120,
  "rows": 40
}

Response:

{
  "s": "ok",
  "cols": 120,
  "rows": 40
}