API & Auth
This page summarizes the current Sally API shape and auth model in a way that is useful for integrators. It reflects the actual product behavior, not a fictional future spec.
Base URL
- Local API dev server:
http://127.0.0.1:4000 - Typical deployed API path:
https://your-sally-domain.com/api
Auth model
Sally currently supports four auth paths:
- Session auth for the web app via bearer session tokens.
- Personal API keys for scripts, automations, and local MCP clients. These use the
atpm_...prefix. - Hosted MCP keys for the built-in
/mcpendpoint. These use thesallymcp_...prefix. - Global API token for bootstrap or testing scenarios when configured by environment.
Public routes
These routes are available without normal session or API-key auth:
GET /healthPOST /auth/loginPOST /auth/accept-invitePOST /auth/request-password-resetPOST /auth/reset-password- public upload asset URLs for task and profile images
Workspace selection
For most non-auth routes, Sally resolves a workspace before the route handler runs.
Supported selectors include:
X-Workspace-IdX-Workspace-Slug- query params such as
workspaceId,workspaceSlug,workspace_id, andworkspace_slug
If an account belongs to multiple workspaces, you should treat workspace selection as explicit. If a hosted MCP key is restricted to one workspace, that restriction is enforced automatically.
Practical curl example
curl https://your-sally-domain.com/api/projects \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'X-Workspace-Slug: sally' Permission model
Sally keeps permissions aligned across the web app, API, and MCP.
- Platform role:
NONE,SUPERADMIN - Workspace role:
OWNER,MEMBER,VIEWER - Project role:
OWNER,MEMBER,VIEWER
Main route groups
- Auth and profile: login, logout, profile, invites, password reset, API keys, MCP keys
- Workspaces and accounts: list workspaces, create workspaces, manage members
- Projects: create, update, archive, delete, manage members, view activity, manage statuses
- Tasks: create, update, move, reorder, archive, delete, manage labels, todos, comments, and inline images
- Clients: CRUD and project linking
- Notifications: assignment and mention delivery plus preferences
- Timesheets: task/project/workspace reporting with validation and billing flags
- Board: aggregated board data for the current workspace or project scope
Representative endpoints
POST /auth/login
GET /auth/me
GET /projects
POST /projects
GET /projects/:projectId
POST /tasks
PATCH /tasks/:taskId
POST /tasks/:taskId/move
GET /timesheets/report
POST /auth/api-keys
POST /auth/mcp-keys Request and response style
The API is not yet perfectly uniform. Some routes return envelope objects such as { ok: true, ... }, while others return raw arrays or objects. Error responses usually follow { ok: false, error: 'Message' }.
Example login request
curl -X POST https://your-sally-domain.com/api/auth/login \
-H 'Content-Type: application/json' \
--data '{
"email": "alex@example.com",
"password": "StrongPassw0rd!"
}' Example create task request
curl -X POST https://your-sally-domain.com/api/tasks \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'X-Workspace-Slug: sally' \
-H 'Content-Type: application/json' \
--data '{
"projectId": "YOUR_PROJECT_ID",
"title": "Ship onboarding flow",
"priority": "P2",
"status": "In Progress",
"labels": ["frontend", "priority"],
"todos": [{ "text": "QA pass" }, { "text": "Deploy" }]
}' Good integration habits
- prefer ids over names once discovered
- treat workspace selection as explicit when the user belongs to multiple workspaces
- fetch statuses first and prefer
statusIdfor exact writes - treat key scope and role scope as separate checks
- revoke temporary test keys after experiments