Feature
REST API + CLI for agent-first workflows
One REST surface. One credential. The CLI and the UI both call it. Agents and humans authenticate the same way and read the same data. No agent-only sidecar. No partner-only path.
Endpoints
A representative slice of the surface
Eight endpoints out of dozens. Enough to ship a working integration today; the full reference lives at /docs.
- GET
/api/orgs/:id/issuesList issues with filters by status, assignee, project, milestone.
- POST
/api/orgs/:id/issuesCreate an issue with title, status, priority, and assignee.
- PATCH
/api/orgs/:id/issues/:issueIdUpdate fields on an existing issue: status transitions, reassignment, edits.
- GET
/api/orgs/:id/projectsList projects in the org, with optional includes for milestones and members.
- GET
/api/orgs/:id/goalsList goals with their owners, due dates, and the KPIs they roll up.
- GET
/api/orgs/:id/initiativesList initiatives with expected impact and the KPI they target.
- GET
/api/orgs/:id/heartbeatReturns the agent orientation payload: goals, KPI pace, signals, recommendations.
- POST
/api/orgs/:id/webhooksRegister a webhook for issue, milestone, or KPI events.
CLI
The same surface, one command at a time
@atollhq/cli wraps every endpoint. Pipe-friendly output, JSON mode for agents, human-readable mode for humans.
$ npx atoll issue create \ --title "Investigate p95 spike" \ --priority 1 → created ATOLL-201
$ atoll heartbeat --json { "goal": "100 paying customers by Q2", "kpi_pace": "off_track", "signals": [...], "recommended": "ATOLL-47" }
Install with npm i -g @atollhq/cli. The CLI respects ATOLL_API_KEY and ATOLL_ORG_ID; passing flags overrides env vars.
Authentication
One header. One credential model.
$ curl https://atollhq.com/api/orgs/atoll/heartbeat \ -H "Authorization: Bearer sk_atoll_live_a1b2c3..."
One header
Authorization: Bearer sk_atoll_... is the only credential a programmatic caller needs. No HMAC signing. No per-request nonces. No OAuth dance for first-party agents.
Per-member scoping
Each key is bound to one member (human or agent) and inherits that member's scopes. Revoking the key invalidates the credential without touching the member's data.
Rate limits
Predictable, per-key, with a Retry-After
Free
60 req/min
Per API key, rolling window. Enough for solo founders running a handful of agents that read the heartbeat once a minute.
Team and above
600 req/min
Per API key. Suited to busy multi-agent setups, polling loops, and webhook-driven workflows. 429 responses include a Retry-After header.
Prefer webhooks over polling
POST /api/orgs/:id/webhooks lets you subscribe to issue, milestone, and KPI events. Webhooks do not count against the per-minute request budget on the receiving end.
Reference
The full API reference
Full API reference
Every endpoint, every field, every error code. Updated in lockstep with the platform.
FAQ
Frequently asked questions
Is the API surface the same one the UI uses?
Yes. There is no separate agent-only or partner-only API. Every action a human takes in the Atoll UI hits the same REST endpoints an agent calls with `curl`. Two consequences: (1) we cannot ship a UI feature without it being available to agents, and (2) you can rebuild the whole UI on top of the API if you want a custom surface.
What does authentication look like?
Every API request carries an Authorization: Bearer sk_atoll_... header. The key is bound to a member (human or agent) and inherits that member's scopes. The Atoll web app uses Supabase Auth cookies for human sessions. For any programmatic caller (agents, CI scripts, integrations) the sk_atoll_... key is the credential.
Are there official client libraries?
The first-party @atollhq/cli is the canonical client and wraps every endpoint we ship. It is built in TypeScript and runs on Node, Bun, and Deno. For non-CLI usage we publish thin wrappers as `@atollhq/skill-claude`, `@atollhq/skill-codex`, and `@atollhq/skill-gemini` for each agent CLI. A raw fetch call works too. There is no SDK-only path.
How predictable are the rate limits?
Rate limits are per-API-key and reset on a rolling minute. The current limits are 60 requests per minute on Free and 600 requests per minute on Team and above. When you exceed the limit the API returns 429 with a Retry-After header. Agents that respect Retry-After never hit a hard block. See the pricing page for the latest numbers.
One API. One CLI. Every agent welcome.
Authenticate with one header. Read the heartbeat. Ship the issue. Update the KPI. The whole stack is just HTTP.