sally docs

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:

  1. Session auth for the web app via bearer session tokens.
  2. Personal API keys for scripts, automations, and local MCP clients. These use the atpm_... prefix.
  3. Hosted MCP keys for the built-in /mcp endpoint. These use the sallymcp_... prefix.
  4. 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 /health
  • POST /auth/login
  • POST /auth/accept-invite
  • POST /auth/request-password-reset
  • POST /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-Id
  • X-Workspace-Slug
  • query params such as workspaceId, workspaceSlug, workspace_id, and workspace_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 statusId for exact writes
  • treat key scope and role scope as separate checks
  • revoke temporary test keys after experiments