Gateway API
The HTTP surface the frontend talks to.
The HTTP surface. Mount it in your own FastAPI app or serve it directly.
python -m runspace.workspace.serve workspace.yml
For one workspace, app.include_router(gateway.router). For many, resolved by
Host header:
from fastapi import FastAPI
from runspace.workspace.backend import WorkspaceRegistry
app = FastAPI()
registry = WorkspaceRegistry.from_tenants_dir("tenants/")
registry.mount(app) # every tenant, every route, dispatched per request
All paths below are relative to the /api/workspace prefix.
Chat
POST /chat | One request, one reply. Body: app_id, message, session_id |
POST /chat/stream | The same turn as server-sent events — tool progress, partial text, then the final payload |
GET /chat/history | Past turns for a session |
DELETE /chat/history | Clear a session |
Channels and messages
GET /channels | Every channel in the workspace |
POST /channels | Create one — name and slug required |
GET /channels/{slug}/messages | History, oldest first |
POST /channels/{slug}/messages | Post. Dispatches any @mention unless you pass dispatch: false |
POST /channels/{slug}/read | Mark read for one member |
GET /unread | Unread counts per channel for a member |
GET /channels/{slug}/threads/{thread_id} | One thread's replies |
PATCH /messages/{message_id} | Edit; records when |
DELETE /messages/{message_id} | Soft delete — hidden from reads, kept for audit |
POST /messages/{message_id}/reactions | Toggle an emoji for one member |
A client that streams the turn itself must pass dispatch: false when posting,
or the agent answers twice — once from the mention dispatch here and once from
its own /chat/stream call.
Members
GET /channels/{slug}/members | Agents and people in a channel |
POST /channels/{slug}/members | Add, or update a role |
DELETE /channels/{slug}/members/{member_type}/{member_id} | Remove |
GET /users | Everyone @-mentionable in this workspace |
Routines
GET /routines | All scheduled work, with next run |
POST /routines | Create — agent_id, schedule, prompt |
PATCH /routines/{routine_id} | Change schedule, prompt, or enabled |
DELETE /routines/{routine_id} | Remove |
POST /routines/{routine_id}/run | Run now, without waiting for the schedule |
Writes go to routines.yml, so the file stays the source of truth and a
routine created through the API is one you can read in a diff.
External channels
GET /telegram-bots | Bots this workspace answers on |
POST /telegram-bots | Register one |
PATCH /telegram-bots/{bot_name} | Change its settings |
DELETE /telegram-bots/{bot_name} | Remove it |
GET /discovered-chats | Groups a bot has been added to |
DELETE /discovered-chats/{bot_name}/{chat_id} | Forget one |
GET /pairings | Pending DM pairing requests |
POST /pairings/{code}/approve | Approve a request |
POST /pairings/{sender_id}/revoke | Revoke access |
GET /external-channels | Bindings between a channel and an outside provider |
POST /external-channels | Create a binding |
DELETE /external-channels/{binding_id} | Remove one |
Pairing exists so a bot is not open to anyone who finds it: a stranger gets a code, and somebody approves it before their messages reach an agent.
Files and configuration
POST /upload | Attachment upload, with extraction |
GET /files/{file_id} | Fetch one back |
GET /config | The workspace as the frontend sees it |
GET /apps | Agents, with persona and group |
GET /activity | Audit feed of tool calls and replies |
POST /reload-config · POST /agents/{agent_id}/reload | Re-read workspace.yml without a restart |