API Reference
Zubo exposes a REST API on the webchat port. All endpoints are available at http://localhost:<port>. If authentication is enabled, include Authorization: Bearer <key> on all /api/* requests.
Health Check
GET /health
Returns the current health status and uptime of the Zubo agent. This endpoint does not require authentication, even when auth.enabled is true.
Response:
{
"status": "ok",
"uptime": 3600
}
Chat
Send Message
POST /api/chat
Content-Type: application/json
{
"message": "Hello, how are you?"
}
Sends a message to the agent and returns a complete response once the agent has finished processing.
Response:
{
"reply": "I'm doing well! How can I help?"
}
Stream Message (SSE)
POST /api/chat/stream
Content-Type: application/json
{
"message": "Tell me about AI"
}
Sends a message and receives the response as a Server-Sent Events stream. This allows the UI to display partial responses as they are generated. The stream emits the following event types:
| Event | Data | Description |
|---|---|---|
delta | { "text": "partial text" } | A chunk of the response text as it is generated. |
tool | { "name": "web_search", "status": "start" } | Indicates a tool call has started. Status is "start" or "end". |
done | { "reply": "full response text" } | The complete response. Sent once at the end of the stream. |
error | { "error": "error message" } | An error occurred during processing. |
Chat History
GET /api/chat/history?limit=50
Returns the recent conversation history. Tool calls are filtered out — only user and assistant text messages are returned.
Query parameters:
| Parameter | Default | Description |
|---|---|---|
limit | 50 | Number of messages to return. Maximum 200. |
Response:
{
"messages": [
{ "role": "user", "content": "Hello" },
{ "role": "assistant", "content": "Hi! How can I help?" }
]
}
Voice Chat
POST /api/chat/voice
Content-Type: multipart/form-data
audio: <audio file>
tts: "true" (optional)
Send an audio file for speech-to-text transcription, then process the transcribed text through the agent. Requires an STT provider to be configured. If tts=true is included and a TTS provider is configured, the response will include base64-encoded audio of the agent's reply.
Response:
{
"transcript": "What's the weather?",
"reply": "Currently 72°F and sunny.",
"audio": "<base64 audio>",
"audioFormat": "mp3"
}
File Upload
POST /api/upload
Content-Type: multipart/form-data
file: <document>
Upload a document for memory indexing. The file is parsed, chunked, embedded, and stored in the memory database. The agent will be able to recall information from uploaded documents in future conversations.
Limits: 50MB maximum file size.
Allowed extensions: .pdf, .docx, .txt, .md, .csv, .json, .html, .xml, .yaml, .yml, .ts, .js, .py, .sh
Response:
{
"uploaded": true,
"filename": "report.pdf",
"size": 245760,
"chunks": 12,
"wordCount": 5430
}
Dashboard API
All dashboard endpoints are under /api/dashboard/. These power the built-in web UI and can also be used by external tools and integrations.
Status
GET /api/dashboard/status
Returns an overview of the agent's current state, including the active provider, connected channels, message count, memory count, and running status.
{
"Provider": "anthropic/claude-sonnet-4-5",
"Channels": "webchat, telegram",
"Messages": "1234",
"Memories": "567",
"Status": "running"
}
System Prompt
GET /api/dashboard/system
Retrieve the current system prompt.
PUT /api/dashboard/system
Content-Type: application/json
{
"content": "You are a helpful assistant named Zubo."
}
Update the system prompt. The new prompt takes effect on the next message.
Memory
GET /api/dashboard/memory
Get the current contents of MEMORY.md, the always-loaded memory file.
PUT /api/dashboard/memory
Content-Type: application/json
{
"content": "User's name is Thomas. Prefers concise answers."
}
Update the contents of MEMORY.md. Changes take effect on the next message.
GET /api/dashboard/memory/recent
Returns the last 20 memory chunks with their source, timestamp, and content.
GET /api/dashboard/memory/search?q=programming
Search memory chunks using full-text search. Returns matching chunks ranked by relevance.
Skills
GET /api/dashboard/skills
List all installed skills with their metadata.
Response:
{
"skills": [
{
"name": "weather",
"description": "Get current weather for a location",
"status": "active",
"path": "~/.zubo/skills/weather"
}
]
}
Cron Jobs
GET /api/dashboard/cron
List all configured cron jobs and their status.
Response:
{
"jobs": [
{
"name": "daily-summary",
"schedule": "0 9 * * *",
"task": "Send a daily briefing",
"enabled": true,
"last_run": "2026-02-12T09:00:00Z"
}
]
}
Logs
GET /api/dashboard/logs
Returns the last 100 log lines from the agent's log output.
Config
GET /api/dashboard/config
Returns the current configuration (sensitive values are masked).
PUT /api/dashboard/config/model
Content-Type: application/json
{
"provider": "anthropic",
"model": "claude-sonnet-4-5-20250929"
}
Update the active LLM provider and model. The change takes effect on the next message.
Settings
GET /api/dashboard/settings/heartbeat
Get the current heartbeat interval.
PUT /api/dashboard/settings/heartbeat
Content-Type: application/json
{
"minutes": 60
}
Update the heartbeat interval. Set to 0 to disable.
Channel Status
GET /api/dashboard/channel-status
Returns the configuration and connection status for each channel (webchat, Telegram, Discord, Slack, WhatsApp, Signal). Each channel reports whether it is configured and whether it is currently enabled.
Secrets Management
GET /api/dashboard/secrets
List all stored secrets. Values are masked in the response for security.
GET /api/dashboard/secrets/:name
Reveal the full value of a single secret by name.
POST /api/dashboard/secrets
Content-Type: application/json
{
"name": "OPENWEATHER_API_KEY",
"value": "abc123...",
"service": "weather"
}
Create or update a secret. The optional service field associates the secret with a specific integration or skill.
DELETE /api/dashboard/secrets/:name
Delete a secret by name.
Analytics API
Analytics endpoints provide insight into usage, cost, performance, and tool activity.
GET /api/dashboard/analytics/summary
Returns aggregate statistics: total tokens used, estimated cost in USD, average response time in milliseconds, and total session count.
GET /api/dashboard/analytics/usage-over-time
Token usage broken down by day for the last 7 days.
GET /api/dashboard/analytics/tools
Tool call counts and average duration for each tool.
GET /api/dashboard/analytics/sessions
Top 20 sessions ranked by token usage, with provider and model information.
GET /api/dashboard/analytics/perf-snapshots
System performance snapshots over time, including RSS memory, heap usage, and database file size.
GET /api/dashboard/analytics/cost-breakdown
Cost aggregated by provider and model, including total tokens, total cost, and request count for each.
GET /api/dashboard/analytics/response-time-trend
Average, minimum, and maximum response times by day over the last 7 days.
GET /api/dashboard/analytics/top-models
Top 10 models ranked by total token usage.
Data Management
POST /api/dashboard/export
Download a full JSON export of the database, including conversations, memory, settings, and analytics.
POST /api/dashboard/backup
Create a SQLite backup file of the database.
POST /api/dashboard/import
Content-Type: multipart/form-data
Upload a JSON export file to import data. Maximum file size is 100MB.
GET /api/dashboard/db-stats
Returns row counts for each table in the database and the total database file size.
Workflows & Agents
GET /api/dashboard/workflows
List all configured workflows with their steps and status.
GET /api/dashboard/agents
List all configured agents (sub-agents) with their names, descriptions, and tool assignments.
Uploads
GET /api/dashboard/uploads
List all uploaded files with their filenames, sizes, chunk counts, and upload timestamps.
Skill Registry
GET /api/dashboard/registry/search?q=weather
Search the community skill registry by name or keyword. Returns matching skills with their names, descriptions, and install commands.
POST /api/dashboard/registry/install
Content-Type: application/json
{
"name": "weather"
}
Install a skill from the registry by name. The skill is downloaded and placed in ~/.zubo/skills/.
API Keys
POST /api/keys
Content-Type: application/json
{
"label": "my-integration"
}
Create a new API key. The label field is optional. The full key is returned once at creation time and cannot be retrieved again.
Response:
{
"id": "k_abc123",
"key": "zb_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
GET /api/keys
List all API keys. Keys are shown with their IDs, labels, creation dates, and last-used timestamps. The full key value is not included.
DELETE /api/keys/:id
Delete an API key by its ID. The key is immediately revoked and can no longer be used for authentication.
Server-Sent Events
GET /api/events
Opens a long-lived SSE connection for receiving real-time events from the agent. The connection emits the following event types:
| Event | Data | Description |
|---|---|---|
connected | { "timestamp": "2026-02-12T10:00:00Z" } | Sent once when the connection is established. |
ping | { "timestamp": "2026-02-12T10:00:30Z" } | Sent every 30 seconds to keep the connection alive. |
Onboarding
GET /api/dashboard/onboarding
Returns the current onboarding state, including whether setup has been completed and the last completed step.
PUT /api/dashboard/onboarding
Content-Type: application/json
{
"completed": true,
"step": 4
}
Update the onboarding state. Used by the dashboard to track setup progress.
Test LLM
POST /api/dashboard/test-llm
Send a test request to the configured LLM provider to verify connectivity and credentials. Returns a simple confirmation with the model name.
Response:
{
"ok": true,
"response": "OK",
"model": "claude-sonnet-4-5-20250929"
}
Rate Limits
Rate limiting is applied per IP address. When a client exceeds the limit, the endpoint returns 429 Too Many Requests with a Retry-After header indicating how many seconds to wait before retrying.
| Endpoint | Default Limit | Config Key |
|---|---|---|
All /api/chat* endpoints | 60 requests/min per IP | rateLimit.chatPerMinute |
/api/upload | 10 requests/min per IP | rateLimit.uploadPerMinute |
Rate limits are configurable via zubo config set or the config file.
Authentication
When auth.enabled is true in your configuration:
- All
/api/*endpoints require anAuthorization: Bearer <key>header. - Create keys using the CLI:
zubo auth create-key [label] - Keys can also be created via the
POST /api/keysendpoint (requires an existing valid key). - The
/healthendpoint does not require authentication, even when auth is enabled.
Requests without a valid key receive a 401 Unauthorized response:
{
"error": "Unauthorized",
"message": "Valid API key required"
}