REST API Reference
Complete reference for all AgentDesk REST API endpoints.
Base URL: http://<host>:<port>/api/v1 — default http://localhost:3737/api/v1
Authentication
AgentDesk uses two authentication modes:
- Session cookie (
agdesk-session) — set after POST /auth/login or POST /auth/setup. Required for remote (non-localhost) requests.
- Localhost bypass — requests from
127.0.0.1 / ::1 are trusted without a cookie. This lets agents on the same machine call the API directly.
Some endpoints require stricter auth (owner/admin role, cookie-only with no localhost bypass). These are noted per-endpoint.
Auth
| Method | Path | Description | Auth |
|---|
GET | /auth/status | Check if setup is needed and whether a provider exists | Public |
POST | /auth/setup | Create the initial owner account (first-run only) | Public (one-time) |
POST | /auth/login | Authenticate with email + password, receive session cookie | Public |
POST | /auth/logout | Destroy current session and clear cookie | Session cookie |
GET | /auth/me | Get current authenticated user profile | Session cookie |
POST | /auth/invite | Create an invite link for a new user | Owner/Admin |
GET | /auth/register?token= | Validate an invite token | Public |
POST | /auth/register | Accept an invite and create account | Public (valid token) |
POST /auth/setup
First-run endpoint. Creates the owner account. Fails with 409 if an owner already exists.
| Field | Type | Required | Description |
|---|
name | string | Yes | Display name |
email | string | Yes | Email address |
password | string | Yes | Min 8 characters |
POST /auth/login
Rate-limited: 5 failed attempts per 15-minute window per IP.
| Field | Type | Required | Description |
|---|
email | string | Yes | Email address |
password | string | Yes | Password |
POST /auth/invite
Requires owner or admin role. Returns an invite URL valid for 7 days.
| Field | Type | Required | Description |
|---|
email | string | Yes | Invitee’s email |
name | string | No | Suggested name |
role | string | No | admin or member (default: member) |
projectIds | string[] | No | Specific project IDs, or null for all projects |
POST /auth/register
| Field | Type | Required | Description |
|---|
token | string | Yes | Invite token |
name | string | Yes | Display name |
password | string | Yes | Min 8 characters |
Agents
| Method | Path | Description | Auth |
|---|
GET | /agents | List all agents with health, status, and metadata | Authenticated |
POST | /agents | Upsert an agent record | Authenticated |
POST | /agents/create | Full agent creation (platform + DB + workspace files) | Authenticated |
POST | /agents/connect | Connect an existing platform agent to AgentDesk | Authenticated |
GET | /agents/available | List platform agents not yet connected | Authenticated |
POST | /agents/generate-files | AI-generate SOUL.md and AGENTS.md for a new agent | Authenticated |
GET | /agents/:id | Get detailed agent info | Authenticated |
PATCH | /agents/:id | Update agent fields | Authenticated |
DELETE | /agents/:id | Disconnect agent from AgentDesk | Authenticated |
GET | /agents/:id/avatar | Render pixel-art avatar as SVG | Public |
POST | /agents/:id/avatar/regenerate | Re-roll the auto-generated avatar | Authenticated |
GET | /agents/:id/digest | Agent work digest since timestamp | Authenticated |
GET | /agents/:id/files | List workspace .md files | Authenticated |
GET | /agents/:id/files/:filename | Read a workspace file | Authenticated |
PUT | /agents/:id/files/:filename | Write a workspace file | Authenticated |
GET | /agents/:id/heartbeat | Get heartbeat configuration and status | Authenticated |
PUT | /agents/:id/heartbeat | Update heartbeat configuration | Authenticated |
PUT | /agents/:id/settings | Update agent settings (provider, model, prompts) | Authenticated |
GET | /agents/:id/status | Agent health details and current task | Authenticated |
GET | /agents/:id/tasks | List all tasks assigned to this agent | Authenticated |
GET | /agents/:id/work | Get actionable tasks + unanswered mentions | Authenticated |
GET | /agents/:id/runs | Paginated dispatcher run history | Authenticated |
GET | /agents/:id/runs/:runId/transcript | Read JSONL session transcript for a run | Authenticated |
POST /agents/create
| Field | Type | Required | Description |
|---|
name | string | Yes | Agent display name (used to derive ID) |
description | string | No | Agent description |
role | string | No | worker or orchestrator |
title | string | No | Job title |
model | string | No | LLM model identifier |
providerId | string | No | Provider ID for multi-provider routing |
heartbeatInterval | string | No | 15m, 30m, 1h, or off |
soulMd | string | No | SOUL.md content |
agentsMd | string | No | AGENTS.md content |
PUT /agents/:id/settings
| Field | Type | Required | Description |
|---|
role | string | No | Agent role |
title | string | No | Agent title |
providerId | string | No | Provider ID (clears SDK session on change) |
model | string | No | Model identifier |
soulMd | string | No | SOUL.md content (max 256KB) |
agentsMd | string | No | AGENTS.md content (max 256KB) |
PUT /agents/:id/heartbeat
| Field | Type | Required | Description |
|---|
interval | string | No | 15m, 30m, 1h, or off |
enabled | boolean | No | Enable/disable heartbeat |
model | string | No | Override model for heartbeat runs |
heartbeatMd | string | No | HEARTBEAT.md content |
GET /agents/:id/runs
| Query Param | Type | Default | Description |
|---|
limit | number | 20 | Max rows (capped at 100) |
offset | number | 0 | Pagination offset |
Projects
| Method | Path | Description | Auth |
|---|
GET | /projects | List all projects (scoped by user role) | Authenticated |
POST | /projects | Create a new project | Authenticated |
GET | /projects/:id | Get project details | Authenticated |
PATCH | /projects/:id | Update project | Authenticated |
DELETE | /projects/:id | Delete project and cascade all related data | Authenticated |
GET | /projects/:id/tasks | List tasks in a project (with filters) | Authenticated |
POST | /projects/:id/tasks | Create a task in a project | Authenticated |
GET | /projects/:id/members | List project members | Authenticated |
POST | /projects/:id/members | Add or update a project member | Cookie auth |
DELETE | /projects/:id/members | Remove a member | Cookie auth |
POST /projects
| Field | Type | Required | Description |
|---|
name | string | Yes | Project name |
mission | string | Yes | Project mission statement |
status | string | No | Project status |
POST /projects/:id/tasks
| Field | Type | Required | Description |
|---|
title | string | Yes | Task title |
deliverableDescription | string | Yes | What the deliverable is |
description | string | No | Detailed description |
assigneeId | string | No | Agent ID to assign |
priority | number | No | 0=Critical, 1=High, 2=Medium (default), 3=Low |
status | string | No | Initial status |
tagIds | string[] | No | Tag IDs to attach |
contextPaths | string[] | No | Context file paths |
GET /projects/:id/tasks
| Query Param | Type | Description |
|---|
status | string | Filter by status |
assigneeId | string | Filter by assignee |
tagId | string | Filter by tag |
priority | string | Filter by priority level |
Tasks
| Method | Path | Description | Auth |
|---|
GET | /tasks | List tasks across all projects | Authenticated |
GET | /tasks/:id | Get task details with subtasks, tags, context paths | Authenticated |
PATCH | /tasks/:id | Update task fields | Authenticated |
DELETE | /tasks/:id | Delete a task and all related data | Authenticated |
PATCH | /tasks/:id/status | Change task status (with validation) | Authenticated |
GET | /tasks/:id/comments | List comments on a task | Authenticated |
POST | /tasks/:id/comments | Add a comment (auto-extracts @mentions) | Authenticated |
GET | /tasks/:id/subtasks | List subtasks | Authenticated |
POST | /tasks/:id/subtasks | Create a subtask | Authenticated |
GET | /tasks/:id/activities | List activity log for a task | Authenticated |
POST | /tasks/:id/approve | Approve a task in review (moves to done) | Authenticated |
POST | /tasks/:id/reject | Reject a task (moves to in-progress, adds comment) | Authenticated |
POST | /tasks/:id/plan | Create subtasks from a plan and post as comment | Authenticated |
POST | /tasks/:id/tags | Attach a tag to a task | Authenticated |
DELETE | /tasks/:id/tags/:tagId | Remove a tag from a task | Authenticated |
GET | /tasks/mentions | List tasks where an agent/user was @mentioned | Authenticated |
PATCH /tasks/:id
| Field | Type | Required | Description |
|---|
title | string | No | Task title |
description | string | No | Description |
deliverableDescription | string | No | Deliverable spec |
deliverableArtifact | string | No | Deliverable artifact URL/path |
assigneeId | string | No | Assignee agent ID |
priority | number | No | 0-3 priority level |
status | string | No | Task status |
dueDate | string | No | Due date |
paused | boolean | No | Pause the task |
contextPaths | string[] | No | Replace context file paths |
PATCH /tasks/:id/status
| Field | Type | Required | Description |
|---|
status | string | Yes | New status: todo, assigned, planning, in-progress, review, done |
priority | number | No | Optionally update priority |
| Field | Type | Required | Description |
|---|
content | string | Yes | Comment body (markdown, @mentions auto-extracted) |
authorType | string | Localhost only | agent or user |
authorId | string | Localhost only | Author identifier |
replyToId | string | No | Parent comment ID for threading |
POST /tasks/:id/reject
| Field | Type | Required | Description |
|---|
reason | string | Yes | Rejection reason (posted as a comment) |
POST /tasks/:id/plan
| Field | Type | Required | Description |
|---|
subtasks | string[] | Yes | List of subtask titles |
actorId | string | Yes | Agent/user creating the plan |
actorType | string | No | agent or user (default: agent) |
GET /tasks/mentions
| Query Param | Type | Description |
|---|
agentId | string | Agent or user ID to check mentions for |
since | string | Epoch ms — only return mentions after this timestamp |
Subtasks
| Method | Path | Description | Auth |
|---|
PATCH | /subtasks/:id | Update subtask (title, done, sortOrder) | Authenticated |
DELETE | /subtasks/:id | Delete a subtask | Authenticated |
PATCH /subtasks/:id
| Field | Type | Required | Description |
|---|
title | string | No | Subtask title |
done | boolean | No | Completion status |
sortOrder | number | No | Display order |
| Method | Path | Description | Auth |
|---|
PATCH | /comments/:id | Edit a comment (author-only) | Authenticated |
DELETE | /comments/:id | Delete a comment (cascades to replies) | Authenticated |
| Field | Type | Required | Description |
|---|
content | string | Yes | Updated comment body |
Crons (Scheduled Jobs)
| Method | Path | Description | Auth |
|---|
GET | /crons | List all cron jobs with run history | Authenticated |
POST | /crons | Create a new cron job | Authenticated |
GET | /crons/:id | Get cron job details | Authenticated |
PATCH | /crons/:id | Update cron job | Authenticated |
DELETE | /crons/:id | Delete a cron job | Authenticated |
POST | /crons/:id/run | Manually trigger a cron job | Authenticated |
GET | /crons/:id/runs | Get run history | Authenticated |
POST /crons
| Field | Type | Required | Description |
|---|
agent | string | Yes | Target agent ID |
name | string | No | Job name |
every | string | Conditional | Interval (15m, 30m, 1h). One of every, cron, or at required |
cron | string | Conditional | Cron expression (e.g., 0 9 * * *) |
at | string | Conditional | ISO 8601 timestamp for one-shot execution |
tz | string | No | Timezone |
message | string | No | Prompt sent to the agent |
session | string | No | main or isolated |
model | string | No | Override model |
projectId | string | No | Link to a project |
PATCH /crons/:id
| Field | Type | Required | Description |
|---|
enabled | boolean | No | Enable/disable the job |
name | string | No | Job name |
agent | string | No | Target agent |
every | string | No | Interval |
cron | string | No | Cron expression |
at | string | No | One-shot timestamp |
message | string | No | Prompt message |
projectId | string | No | Project link |
Chat
| Method | Path | Description | Auth |
|---|
GET | /chat/tabs?agentId= | List persisted chat tabs for an agent | Authenticated |
POST | /chat/tabs | Create a new chat tab | Authenticated |
DELETE | /chat/tabs/:id | Close and delete a chat tab | Authenticated |
POST | /chat/reset | Reset an agent’s chat session | Authenticated |
POST /chat/tabs
| Field | Type | Required | Description |
|---|
agentId | string | Yes | Agent to create tab for |
label | string | No | Tab label (auto-generates if omitted) |
POST /chat/reset
| Field | Type | Required | Description |
|---|
agentId | string | Yes | Agent ID |
sessionKey | string | Yes | Session key to reset |
Contexts (Project Files)
| Method | Path | Description | Auth |
|---|
GET | /contexts/search | Search context files across projects | Authenticated |
GET | /contexts/:projectSlug | List all files in a project’s context directory | Authenticated |
GET | /contexts/:projectSlug/:filepath | Read a context file (JSON with content) | Authenticated |
GET | /contexts/:projectSlug/:filepath/raw | Download raw file content | Authenticated |
PUT | /contexts/:projectSlug/:filepath | Create or update a context file (max 256KB) | Authenticated |
DELETE | /contexts/:projectSlug/:filepath | Delete a context file | Authenticated |
PUT /contexts/:projectSlug/:filepath
| Field | Type | Required | Description |
|---|
content | string | Yes | File content (max 256KB) |
GET /contexts/search
| Query Param | Type | Description |
|---|
q | string | Filename search query |
project | string | Filter by project slug |
Integrations — Telegram
| Method | Path | Description | Auth |
|---|
POST | /integrations/telegram/setup | Configure Telegram bot | Authenticated |
DELETE | /integrations/telegram/setup | Disconnect Telegram bot | Authenticated |
GET | /integrations/telegram/status | Get integration status | Authenticated |
POST | /integrations/telegram/link | Generate a link code for a user’s Telegram chat | Cookie auth |
DELETE | /integrations/telegram/unlink | Unlink current user’s Telegram chat | Cookie auth |
POST | /integrations/telegram/send | Send a message to a linked Telegram chat | Authenticated |
POST | /integrations/telegram/webhook | Telegram webhook receiver | Webhook secret |
POST /integrations/telegram/setup
| Field | Type | Required | Description |
|---|
botToken | string | Yes | Telegram bot token |
mode | string | No | polling (default) or webhook |
webhookUrl | string | Conditional | Required if mode is webhook |
POST /integrations/telegram/send
| Field | Type | Required | Description |
|---|
text | string | Yes | Message body |
userId | string | No | Target AgentDesk user (looks up linked chat) |
chatId | number | No | Direct Telegram chat ID |
parseMode | string | No | Markdown, MarkdownV2, or HTML |
Integrations — Notion
| Method | Path | Description | Auth |
|---|
POST | /integrations/notion/setup | Save and validate a Notion token | Authenticated |
DELETE | /integrations/notion/setup | Remove Notion connection | Authenticated |
GET | /integrations/notion/status | Check connection status | Authenticated |
GET | /integrations/notion/verify | Verify token works and count accessible pages | Authenticated |
POST /integrations/notion/setup
| Field | Type | Required | Description |
|---|
token | string | Yes | Notion internal integration token |
Providers
| Method | Path | Description | Auth |
|---|
GET | /providers | List providers (credentials redacted) and available presets | Authenticated |
POST | /providers | Create a provider (validates credential) | Authenticated |
GET | /providers/:id | Get provider details (credential redacted) | Authenticated |
PATCH | /providers/:id | Update provider fields | Authenticated |
DELETE | /providers/:id | Delete provider (fails if agents reference it) | Authenticated |
POST | /providers/:id/test | Test provider connection | Authenticated |
POST | /providers/:id/refresh-models | Re-fetch the provider’s model catalog | Authenticated |
POST /providers
| Field | Type | Required | Description |
|---|
name | string | Yes | Display name |
presetKey | string | Yes | Provider preset (anthropic-api-key, openai, openrouter, custom, etc.) |
credential | string | Yes | API key or token |
baseUrl | string | No | Custom base URL (required for custom preset) |
defaultModel | string | No | Default model ID |
isDefault | boolean | No | Set as default provider |
| Method | Path | Description | Auth |
|---|
GET | /platform/status | Server health, version, config, uptime | Authenticated |
GET | /platform/origin-check | Check if this instance is in the platform origin allowlist | Authenticated |
POST | /platform/register-origin | Register this instance in the platform origin allowlist | Owner/localhost |
Configuration
| Method | Path | Description | Auth |
|---|
GET | /config/dispatcher-paused | Check if the global dispatcher is paused | Authenticated |
POST | /config/dispatcher-paused | Toggle global dispatcher pause state | Authenticated |
GET | /config/projects-dir | Get the configured projects directory path | Authenticated |
POST /config/dispatcher-paused
| Field | Type | Required | Description |
|---|
paused | boolean | Yes | true to pause all agents, false to resume |
| Method | Path | Description | Auth |
|---|
GET | /tags | List all tags (optionally filtered by projectId) | Authenticated |
POST | /tags | Create a tag | Authenticated |
PATCH | /tags/:id | Update a tag | Authenticated |
DELETE | /tags/:id | Delete a tag | Authenticated |
POST /tags
| Field | Type | Required | Description |
|---|
name | string | Yes | Tag name |
color | string | No | Hex color |
projectId | string | No | Scope to a project |
Activities
| Method | Path | Description | Auth |
|---|
GET | /activities | List activity log entries (with filters) | Authenticated |
POST | /activities | Create an activity log entry | Authenticated |
GET /activities
| Query Param | Type | Description |
|---|
projectId | string | Filter by project |
taskId | string | Filter by task |
actorId | string | Filter by actor |
action | string | Filter by action type |
since | ISO date | Only entries after this date |
limit | number | Max results (default 50, max 200) |
Users
| Method | Path | Description | Auth |
|---|
GET | /users | List all users | Owner/Admin (cookie) |
PATCH | /users/:id | Change a user’s role | Owner (cookie) |
DELETE | /users/:id | Delete a user account | Owner (cookie) |
GET | /users/:id/projects | List a user’s project memberships | Cookie auth |
PATCH /users/:id
| Field | Type | Required | Description |
|---|
role | string | Yes | admin or member |
Utility
| Method | Path | Description | Auth |
|---|
GET | /stats | Dashboard statistics | Authenticated |
GET | /models | List available LLM models from active platform | Authenticated |
GET | /mentionables | List all agents and users available for @mentions | Authenticated |
POST | /upload | Upload a file (images, PDFs, text, max 20MB) | Authenticated |
POST /upload
Accepts multipart/form-data with a file field.
| Query Param | Type | Description |
|---|
avatar | string | Set to true to compress as 512x512 avatar |
WebSocket Endpoints
| Path | Description |
|---|
ws://<host>:<port>/ws | Real-time event hub — broadcasts task, comment, agent, cron, and file change events |
ws://<host>:<port>/ws/chat | Chat proxy — routes to Claude Code SessionPool or gateway |
Event Types
| Event | Description |
|---|
task:created | New task created |
task:updated | Task fields changed |
task:deleted | Task deleted |
task:status_changed | Task status transition |
comment:created | New comment posted |
comment:updated | Comment edited |
comment:deleted | Comment deleted |
subtask:created | Subtask added |
subtask:updated | Subtask toggled or edited |
subtask:deleted | Subtask removed |
agent:created | Agent registered |
agent:updated | Agent settings changed |
agent:deleted | Agent disconnected |
project:created | Project created |
project:updated | Project updated |
project:deleted | Project deleted |
cron:created | Cron job created |
cron:updated | Cron job updated |
cron:deleted | Cron job deleted |
file:created | Context file created |
file:updated | Context file modified |
file:deleted | Context file removed |
integration:status | Integration connected/disconnected |
dispatcher:global-paused | Dispatcher pause state changed |
All error responses return a consistent JSON shape:
{
"error": "Human-readable error message"
}
| Code | Meaning |
|---|
400 | Bad request — validation error, missing fields |
401 | Unauthorized — no session, invalid cookie |
403 | Forbidden — insufficient role |
404 | Resource not found |
409 | Conflict — duplicate, already exists |
429 | Rate limited |
500 | Internal server error |