Documentation

The developer API

API keys, the REST surface, webhooks and how they differ from the MCP connector

This is for code that talks to SquadBear directly — a script, a backend job, a webhook listener — rather than a person chatting with an agent.

API keys

Create one at Admin → API keys. The full token is shown exactly once at creation time ("Copy this token now — it is shown only once and cannot be retrieved later") and starts with sbk_; only its display prefix is kept afterward, so if you lose the token you generate a new one.

A key carries whatever subset of scopes you check when creating it — people:read, teams:read, leave:read, leave:write, balances:read, reports:read, time:read, time:write, events:read, webhooks:write, admin:write. Requesting an endpoint that needs a scope your key doesn't have fails with a 403 naming the missing scope, not a silent partial result.

A key acts as the workspace, not as any one person — it isn't tied to whoever created it, and losing that person doesn't break it. Internally it resolves to a tenant-scoped service actor; the scopes you granted it are what actually bound what it can do, not a role.

The REST API

Base path is /api/v1. It authenticates with Authorization: Bearer <token> — not a custom header — and returns a 401 with WWW-Authenticate: Bearer if that's missing or malformed. Interactive, always-current docs (generated from the same route definitions the server runs) are live at app.squadbear.com/api/v1/docs — no separate spec to keep in sync by hand.

Webhooks

Manage subscriptions at Admin → Webhooks. When adding one you choose between every event and a specific set of event types; the same choice is available via the API or MCP by passing an eventTypes list at creation (omit it for every event). Event names include request.created, request.approved, employee.created, employee.offboarded, checklist.completed, ack.signed, and more, visible as they happen in the "Recent events" panel on that same page. Unknown event names are rejected at creation.

Every delivery is a signed POST: header X-Squadbear-Signature, value sha256=<hex-hmac>, computed as HMAC-SHA256 of the raw request body using the secret shown once when you create the webhook. Verify it before trusting a payload. Deliveries that fail are retried on a short cron cycle, up to 3 attempts total, then dropped — treat a webhook as at-least-once-if-your-endpoint-is-usually-up, not guaranteed.

The MCP connector, briefly

There's a third surface: connect an agent over MCP and it can act in the workspace using your own permissions in a chat, no code required — see Connect Claude to SquadBear for setup. Its scopes (leave:read, time:write, health:write, and the rest) are consented per connection when someone approves it, and are a completely separate list from the API-key scopes above — a workspace's API keys don't grant anything to a connected agent, and vice versa.

UI names vs. wire names

The names you see in the app and the identifiers you use over the API and MCP deliberately diverge — the wire names are a stable contract, the UI names are tuned for humans. Where they differ, this is the map:

UI nameMCP toolsAPI routeScope
Documents (Company documents)list_files, get_file_link, delete_file/api/filesfiles:read / files:write
My Tasks (personal to-dos)list_my_checklist_items, list_checklists/api/my-tasks, /api/checkliststasks:read / tasks:write
Work items (time-tracking rows)list_work_items, create_work_item/api/taskstime:read / time:write
Acknowledgmentslist_ack_campaigns, create_ack_campaign, acknowledge_document/api/ack-campaignsdocs:ack
Health checkslist_health_runs, create_health_run/api/health/runshealth:read / health:write
My Leaverequest_time_off, list_my_requests/api/v1/leave-requests (public) · /api/requests (internal)leave:read / leave:write

One historical wrinkle: the tasks:* scopes and the /api/tasks REST route predate the task→work-item rename, so the MCP tools say work_item (list_work_items, create_work_item) while the REST route and taskId params keep the old noun. Checklist to-dos live under list_my_checklist_items and the tasks:* scopes. And "files" is the wire umbrella: the Documents library the UI shows is the scope='tenant' slice of it.

Worked example

Northlake's ops engineer, Bartek, wants new leave requests posted into their team chat the moment someone files one. He creates an API key scoped to webhooks:write at Admin → API keys, then calls the webhook endpoint with {"url": "https://hooks.example/northlake", "eventTypes": ["request.created"]} to skip subscribing to everything. His endpoint checks X-Squadbear-Signature against the one-time secret before it trusts a payload, then posts the requester's name and dates into chat.