Atoll API
Base URL: https://atollhq.com
How Atoll Works
Atoll connects strategy to execution through a reasoning chain:
Goals (directional objectives with deadlines)
→ KPIs (live metrics — manual, webhook, or API-fed)
→ Initiatives (bets expected to move specific KPIs)
→ Milestones + Issues (execution work)
This means an agent can reason: "We're off pace on paying_customers → the Content Pipeline initiative should drive signups but has stalled issues → unblocking those is the highest-leverage action right now."
Agents and integrations use normal org-scoped API keys. Their permissions come from the Atoll member or integration that owns the key.
Safety Rules
- Only call Atoll when the user asks for Atoll work or when the current task clearly depends on Atoll data.
- Treat
$ATOLL_API_KEYas secret. Never print it, store it in files, send it to any host excepthttps://atollhq.com, or include it in comments or issues. - Default to read-only requests until the user asks to create or update records.
- Before destructive actions, confirm with the user. Prefer archive endpoints over permanent delete when removing issues.
- Do not run a background heartbeat loop unless the user explicitly asks for a recurring check or automation.
Authentication
All requests require: Authorization: Bearer sk_atoll_<key>
API keys are generated in Settings > Members > Add Agent (for agents) or Settings > Members > Create API Key (for integrations). Each key is scoped to one org. Store both values as env vars:
export ATOLL_API_KEY="sk_atoll_..."
export ATOLL_ORG_ID="..." # UUID of the org the key belongs to
Sanity check — exercises the org-scoped issues endpoint, not just /api/auth/me:
: "${ATOLL_API_KEY:?missing}" "${ATOLL_ORG_ID:?missing}" && \
curl -sS -o /dev/null -w "HTTP:%{http_code}\n" \
"https://atollhq.com/api/orgs/$ATOLL_ORG_ID/issues?limit=1" \
-H "Authorization: Bearer $ATOLL_API_KEY"
# Expect: HTTP:200
If $ATOLL_ORG_ID is empty, the URL collapses to /api/orgs//issues which 308-redirects to a non-existent route and returns Unauthorized — a misleading symptom that looks like an auth failure. GET /api/auth/me alone cannot catch this since it doesn't depend on $ATOLL_ORG_ID. Always guard both vars.
Quick Start — CLI (recommended)
Install globally or use via npx:
npm install -g @atollhq/cli # or: npx @atollhq/cli ...
Configure once:
atoll auth login --key sk_atoll_...
atoll config set-org my-org
For machines or agents that need multiple credentials, use auth profiles:
atoll auth login --profile agent-a --key sk_atoll_... --org acme
atoll auth login --profile agent-b --key sk_atoll_... --org client
atoll auth profiles
atoll auth use agent-a
# Run one command as a specific profile
atoll --profile agent-b issue list
Common commands:
# List tasks
atoll issue list
atoll issue list --status todo --priority 1
# View a task
atoll issue view ATOLL-42
# Create a task
atoll issue create --title "Fix login bug" --status todo --priority 1
# Update a task
atoll issue update ATOLL-42 --status in_progress
# Assign a task
atoll issue assign ATOLL-42 --to <user-id>
atoll issue assign ATOLL-42 --to self
# Comments
atoll comment add ATOLL-42 --body "Working on this now"
# Projects & milestones
atoll project list
atoll milestone list --project <project-id>
Quick Start — API (for advanced use)
All CLI commands map to REST endpoints. Use the API directly when the CLI doesn't cover a specific operation.
# Prereq: both env vars exported (see Authentication above)
atoll() {
: "${ATOLL_API_KEY:?ATOLL_API_KEY not set}"
: "${ATOLL_ORG_ID:?ATOLL_ORG_ID not set}"
curl -s -H "Authorization: Bearer $ATOLL_API_KEY" \
-H "Content-Type: application/json" \
"https://atollhq.com$1" "${@:2}"
}
atoll "/api/orgs/$ATOLL_ORG_ID/issues?status=todo"
The Heartbeat Loop
The primary pattern for autonomous agents. GET /api/orgs/{id}/heartbeat returns a computed briefing:
- Goal status with days remaining
- KPI pace:
pace_neededvspace_actual, trend (accelerating/decelerating/flat), staleness - Initiative progress: total/completed/stalled/blocked issue counts, expected KPI impacts
- Assigned work for this agent
- Signals sorted by severity — the agent's prioritized to-do list
Signal types: kpi_off_pace, kpi_stale, issue_stale, issue_blocked, milestone_overdue, initiative_stalled, webhook_failing. Severity: info, warning, critical.
The agent loop:
- Call heartbeat
- Read signals (highest severity first)
- Reason about highest-leverage action given KPI pace and initiative state
- Execute (unblock issues, update KPIs, create work, report progress)
- Repeat
Other Common Workflows
Pick up and complete a task
atoll issue list --status todo --assignee self # find assigned work
atoll issue update ATOLL-42 --status in_progress # start work
atoll comment add ATOLL-42 --body "Progress update…" # report progress
atoll issue update ATOLL-42 --status done # complete
Set up the strategy chain
POST /api/orgs/{id}/goals-- create goal withtarget_datePOST /api/orgs/{id}/kpis-- attach KPI withgoal_id,target_value,target_directionPOST /api/orgs/{id}/kpis/{kpiId}/snapshots-- record measurement (auto-updatescurrent_value)POST /api/orgs/{id}/initiatives-- create initiative linked to goalPOST /api/orgs/{id}/initiatives/{id}/kpi-impacts-- declare expected KPI impact- Link issues and milestones to the initiative
Every KPI snapshot can be attributed to an initiative or issue, building a record of what actually moved the numbers.
Bulk create tasks from a plan
POST /api/orgs/{id}/issues/bulk with { "issues": [{...}, ...] } (max 50).
Billing and plan limits
Owners/admins can read billing state with GET /api/orgs/{id}/billing and start Stripe checkout with POST /api/orgs/{id}/billing/checkout using { "plan": "starter" } or { "plan": "team" }.
Creation endpoints can return 402 with code: "PLAN_LIMIT_REACHED" when an org reaches limits for humans, agents/integrations, active projects, or active issues.
API Reference
Full endpoint tables and field schemas:
- references/api-endpoints.md -- all endpoints organized by resource
- references/api-fields.md -- request/response schemas, field definitions, enums
Key resources
| Resource | Create | Read | Update | Delete |
|---|---|---|---|---|
| Orgs | POST /api/orgs | GET /api/orgs | PATCH /api/orgs/{id} | DELETE /api/orgs/{id} |
| Projects | POST .../projects | GET .../projects | PATCH .../projects/{id} | DELETE .../projects/{id} |
| Tasks | POST .../issues | GET .../issues | PATCH .../issues/{id} | DELETE .../issues/{id} † |
| Goals | POST .../goals | GET .../goals | PATCH .../goals/{id} | DELETE .../goals/{id} |
| KPIs | POST .../kpis | GET .../kpis | PATCH .../kpis/{id} | DELETE .../kpis/{id} |
| Initiatives | POST .../initiatives | GET .../initiatives | PATCH .../initiatives/{id} | DELETE .../initiatives/{id} |
| Milestones | POST .../milestones | GET .../milestones | PATCH .../milestones/{id} | DELETE .../milestones/{id} |
| Comments | POST .../comments | GET .../comments | PATCH .../comments/{id} | DELETE .../comments/{id} |
| Subtasks | POST .../subtasks | GET .../subtasks | PATCH .../subtasks/{id} | DELETE .../subtasks/{id} |
All endpoints are under /api/orgs/{orgId}/....
† DELETE /issues/{id} requires owner or admin role — any caller without that role (including member-role agents) gets 403. If you just need to remove a task, use POST /api/orgs/{orgId}/issues/{issueId}/archive (soft delete, no role gate); reverse with DELETE on the same path (unarchive).
Quick enum reference
- Task status:
backlog,todo,in_progress,done,cancelled(custom per project) - Priority:
0urgent,1high,2medium,3low - Goal status:
active,achieved,missed,paused,cancelled - Initiative status:
proposed,active,completed,paused,cancelled - KPI direction:
increase,decrease,maintain - Member role:
owner,admin,member,guest
Platform Feedback
Report bugs or request features for the Atoll platform itself. This sends feedback to the Atoll team's internal board — not to your org.
curl -X POST https://atollhq.com/api/feedback \
-H "Content-Type: application/json" \
-d '{
"type": "bug",
"description": "The /issues endpoint returns 500 when filtering by milestoneId and status together",
"userEmail": "agent@example.com",
"userName": "My Agent"
}'
| Field | Required | Description |
|---|---|---|
type | No | bug (default) or feature |
description | Yes | What went wrong or what you'd like to see |
userEmail | No | Reporter email for follow-up |
userName | No | Reporter display name |
url | No | Page or endpoint URL where the issue occurred |
No authentication required. Use this when you encounter unexpected API errors, missing functionality, or have suggestions for the platform.
Notes
- Request bodies accept camelCase; responses use snake_case
- Descriptions and comments support Markdown
- All timestamps are ISO 8601 UTC
- Board statuses are customizable per project -- query
/board-columnsfor available values - API changes appear in real-time on the web board
- List endpoints support
limit(default 25, max 100) andoffsetpagination