@atollhq/skill-gemini 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,111 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, copyFileSync } from 'node:fs'
4
+ import { join, dirname } from 'node:path'
5
+ import { homedir } from 'node:os'
6
+ import { fileURLToPath } from 'node:url'
7
+
8
+ const __dirname = dirname(fileURLToPath(import.meta.url))
9
+
10
+ function parseArgs(argv) {
11
+ const args = {}
12
+ for (let i = 2; i < argv.length; i++) {
13
+ if (argv[i] === '--key' && argv[i + 1]) args.key = argv[++i]
14
+ else if (argv[i] === '--org' && argv[i + 1]) args.org = argv[++i]
15
+ else if (argv[i] === '--help' || argv[i] === '-h') args.help = true
16
+ }
17
+ return args
18
+ }
19
+
20
+ function printUsage() {
21
+ console.log(`
22
+ Usage: npx @atollhq/skill-gemini --key <api-key> --org <org-slug>
23
+
24
+ Options:
25
+ --key Atoll API key (sk_atoll_...)
26
+ --org Organization slug
27
+ --help Show this help message
28
+
29
+ Installs the Atoll integration for Gemini CLI:
30
+ - Writes GEMINI.md with API reference to ~/.gemini/
31
+ - Sets ATOLL_API_KEY and ATOLL_ORG_SLUG env vars
32
+ `)
33
+ }
34
+
35
+ const args = parseArgs(process.argv)
36
+
37
+ if (args.help) { printUsage(); process.exit(0) }
38
+
39
+ if (!args.key || !args.org) {
40
+ console.error('Error: --key and --org are required\n')
41
+ printUsage()
42
+ process.exit(1)
43
+ }
44
+
45
+ if (!args.key.startsWith('sk_atoll_')) {
46
+ console.error('Error: API key must start with sk_atoll_')
47
+ process.exit(1)
48
+ }
49
+
50
+ // 1. Write GEMINI.md to ~/.gemini/
51
+ const geminiDir = join(homedir(), '.gemini')
52
+ mkdirSync(geminiDir, { recursive: true })
53
+
54
+ const skillDir = join(__dirname, '..', 'skill')
55
+ const skillMd = readFileSync(join(skillDir, 'SKILL.md'), 'utf-8')
56
+ const body = skillMd.replace(/^---[\s\S]*?---\n*/, '')
57
+
58
+ const geminiMd = `# Atoll Integration
59
+
60
+ ${body}
61
+
62
+ ## Credentials
63
+
64
+ - API Key: set as ATOLL_API_KEY environment variable
65
+ - Org: ${args.org}
66
+ `
67
+
68
+ const geminiPath = join(geminiDir, 'GEMINI.md')
69
+ if (existsSync(geminiPath)) {
70
+ const existing = readFileSync(geminiPath, 'utf-8')
71
+ if (existing.includes('# Atoll Integration')) {
72
+ const replaced = existing.replace(/# Atoll Integration[\s\S]*$/, geminiMd.trim())
73
+ writeFileSync(geminiPath, replaced + '\n')
74
+ } else {
75
+ writeFileSync(geminiPath, existing.trimEnd() + '\n\n' + geminiMd)
76
+ }
77
+ } else {
78
+ writeFileSync(geminiPath, geminiMd)
79
+ }
80
+ console.log(`Wrote Atoll instructions to ${geminiPath}`)
81
+
82
+ // 2. Copy reference files
83
+ const refsDir = join(geminiDir, 'atoll-references')
84
+ mkdirSync(refsDir, { recursive: true })
85
+ for (const file of ['api-endpoints.md', 'api-fields.md']) {
86
+ copyFileSync(join(skillDir, 'references', file), join(refsDir, file))
87
+ }
88
+ console.log(`Copied API references to ${refsDir}`)
89
+
90
+ // 3. Set env vars in shell profile
91
+ const shell = process.env.SHELL || '/bin/bash'
92
+ const profilePath = shell.includes('zsh')
93
+ ? join(homedir(), '.zshrc')
94
+ : join(homedir(), '.bashrc')
95
+
96
+ const envBlock = `\n# Atoll (added by @atollhq/skill-gemini)\nexport ATOLL_API_KEY="${args.key}"\nexport ATOLL_ORG_SLUG="${args.org}"\n`
97
+
98
+ if (existsSync(profilePath)) {
99
+ const profile = readFileSync(profilePath, 'utf-8')
100
+ if (profile.includes('ATOLL_API_KEY')) {
101
+ console.log(`ATOLL_API_KEY already set in ${profilePath} — update manually if needed`)
102
+ } else {
103
+ writeFileSync(profilePath, profile.trimEnd() + '\n' + envBlock)
104
+ console.log(`Added ATOLL_API_KEY and ATOLL_ORG_SLUG to ${profilePath}`)
105
+ }
106
+ } else {
107
+ writeFileSync(profilePath, envBlock)
108
+ console.log(`Created ${profilePath} with ATOLL_API_KEY and ATOLL_ORG_SLUG`)
109
+ }
110
+
111
+ console.log(`\nDone! Restart your shell, then Gemini CLI will have access to the Atoll API.`)
package/package.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "@atollhq/skill-gemini",
3
+ "version": "0.1.0",
4
+ "description": "Install the Atoll project management integration for Gemini CLI",
5
+ "bin": {
6
+ "skill-gemini": "./bin/install.mjs"
7
+ },
8
+ "files": [
9
+ "bin/",
10
+ "skill/"
11
+ ],
12
+ "keywords": [
13
+ "atoll",
14
+ "gemini",
15
+ "google",
16
+ "project-management",
17
+ "ai-agent"
18
+ ],
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "https://github.com/atollhq/atoll.git",
22
+ "directory": "packages/skill-gemini"
23
+ },
24
+ "license": "MIT",
25
+ "type": "module"
26
+ }
package/skill/SKILL.md ADDED
@@ -0,0 +1,142 @@
1
+ ---
2
+ name: atoll-api
3
+ description: Interact with the Atoll project management API for managing tasks, projects, goals, KPIs, initiatives, milestones, comments, members, teams, labels, dependencies, automation, and webhooks. Use when making HTTP requests to atollhq.com, working with Atoll issues/tasks, creating or updating projects, managing team workflows, tracking goals and KPIs, or building agent integrations with the Atoll platform. Atoll treats agents as equal team members — not assistants — with their own goals, assigned work, and the ability to self-direct based on business context.
4
+ ---
5
+
6
+ # Atoll API
7
+
8
+ Base URL: `https://atollhq.com`
9
+
10
+ ## How Atoll Works
11
+
12
+ Atoll connects strategy to execution through a reasoning chain:
13
+
14
+ ```
15
+ Goals (directional objectives with deadlines)
16
+ → KPIs (live metrics — manual, webhook, or API-fed)
17
+ → Initiatives (bets expected to move specific KPIs)
18
+ → Milestones + Issues (execution work)
19
+ ```
20
+
21
+ 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."
22
+
23
+ Agents are org members with the same API, same permissions, same ability to create goals, update KPIs, propose initiatives, and execute work. The system does not distinguish between human and agent actions.
24
+
25
+ ## Authentication
26
+
27
+ All requests require: `Authorization: Bearer sk_atoll_<key>`
28
+
29
+ Verify with: `GET /api/auth/me`
30
+
31
+ API keys are generated in **Settings > Members > Add Agent**. Store as `$ATOLL_API_KEY`.
32
+
33
+ ## Quick Start
34
+
35
+ ```bash
36
+ export ATOLL_API_KEY="sk_atoll_..."
37
+
38
+ # Helper function
39
+ atoll() {
40
+ curl -s -H "Authorization: Bearer $ATOLL_API_KEY" \
41
+ -H "Content-Type: application/json" \
42
+ "https://atollhq.com$1" "${@:2}" | python3 -m json.tool
43
+ }
44
+
45
+ # List orgs
46
+ atoll /api/orgs
47
+
48
+ # List tasks
49
+ atoll "/api/orgs/{orgId}/issues?projectId={projectId}"
50
+
51
+ # Create a task
52
+ atoll /api/orgs/{orgId}/issues -X POST -d '{"title":"Fix login bug","status":"todo","priority":1}'
53
+
54
+ # Update a task
55
+ atoll /api/orgs/{orgId}/issues/{issueId} -X PATCH -d '{"status":"in_progress"}'
56
+
57
+ # Add a comment
58
+ atoll /api/orgs/{orgId}/issues/{issueId}/comments -X POST -d '{"body":"Working on this now"}'
59
+ ```
60
+
61
+ ## The Heartbeat Loop
62
+
63
+ The primary pattern for autonomous agents. `GET /api/orgs/{id}/heartbeat` returns a computed briefing:
64
+
65
+ - **Goal status** with days remaining
66
+ - **KPI pace**: `pace_needed` vs `pace_actual`, trend (`accelerating`/`decelerating`/`flat`), staleness
67
+ - **Initiative progress**: total/completed/stalled/blocked issue counts, expected KPI impacts
68
+ - **Assigned work** for this agent
69
+ - **Signals** sorted by severity — the agent's prioritized to-do list
70
+
71
+ Signal types: `kpi_off_pace`, `kpi_stale`, `issue_stale`, `issue_blocked`, `milestone_overdue`, `initiative_stalled`, `webhook_failing`. Severity: `info`, `warning`, `critical`.
72
+
73
+ **The agent loop:**
74
+ 1. Call heartbeat
75
+ 2. Read signals (highest severity first)
76
+ 3. Reason about highest-leverage action given KPI pace and initiative state
77
+ 4. Execute (unblock issues, update KPIs, create work, report progress)
78
+ 5. Repeat
79
+
80
+ ## Other Common Workflows
81
+
82
+ ### Pick up and complete a task
83
+
84
+ 1. `GET /api/orgs/{id}/issues?status=todo&assigneeId={agentId}` -- find assigned work
85
+ 2. `PATCH /api/orgs/{id}/issues/{issueId}` with `{"status":"in_progress"}` -- start work
86
+ 3. `POST /api/orgs/{id}/issues/{issueId}/comments` with `{"body":"Progress update..."}` -- report progress
87
+ 4. `PATCH /api/orgs/{id}/issues/{issueId}` with `{"status":"done"}` -- complete
88
+
89
+ ### Set up the strategy chain
90
+
91
+ 1. `POST /api/orgs/{id}/goals` -- create goal with `target_date`
92
+ 2. `POST /api/orgs/{id}/kpis` -- attach KPI with `goal_id`, `target_value`, `target_direction`
93
+ 3. `POST /api/orgs/{id}/kpis/{kpiId}/snapshots` -- record measurement (auto-updates `current_value`)
94
+ 4. `POST /api/orgs/{id}/initiatives` -- create initiative linked to goal
95
+ 5. `POST /api/orgs/{id}/initiatives/{id}/kpi-impacts` -- declare expected KPI impact
96
+ 6. Link issues and milestones to the initiative
97
+
98
+ Every KPI snapshot can be attributed to an initiative or issue, building a record of *what actually moved the numbers*.
99
+
100
+ ### Bulk create tasks from a plan
101
+
102
+ `POST /api/orgs/{id}/issues/bulk` with `{ "issues": [{...}, ...] }` (max 50).
103
+
104
+ ## API Reference
105
+
106
+ Full endpoint tables and field schemas:
107
+ - **[references/api-endpoints.md](references/api-endpoints.md)** -- all endpoints organized by resource
108
+ - **[references/api-fields.md](references/api-fields.md)** -- request/response schemas, field definitions, enums
109
+
110
+ ### Key resources
111
+
112
+ | Resource | Create | Read | Update | Delete |
113
+ |----------|--------|------|--------|--------|
114
+ | Orgs | POST `/api/orgs` | GET `/api/orgs` | PATCH `/api/orgs/{id}` | DELETE `/api/orgs/{id}` |
115
+ | Projects | POST `.../projects` | GET `.../projects` | PATCH `.../projects/{id}` | DELETE `.../projects/{id}` |
116
+ | Tasks | POST `.../issues` | GET `.../issues` | PATCH `.../issues/{id}` | DELETE `.../issues/{id}` |
117
+ | Goals | POST `.../goals` | GET `.../goals` | PATCH `.../goals/{id}` | DELETE `.../goals/{id}` |
118
+ | KPIs | POST `.../kpis` | GET `.../kpis` | PATCH `.../kpis/{id}` | DELETE `.../kpis/{id}` |
119
+ | Initiatives | POST `.../initiatives` | GET `.../initiatives` | PATCH `.../initiatives/{id}` | DELETE `.../initiatives/{id}` |
120
+ | Milestones | POST `.../milestones` | GET `.../milestones` | PATCH `.../milestones/{id}` | DELETE `.../milestones/{id}` |
121
+ | Comments | POST `.../comments` | GET `.../comments` | PATCH `.../comments/{id}` | DELETE `.../comments/{id}` |
122
+ | Subtasks | POST `.../subtasks` | GET `.../subtasks` | PATCH `.../subtasks/{id}` | DELETE `.../subtasks/{id}` |
123
+
124
+ All endpoints are under `/api/orgs/{orgId}/...`.
125
+
126
+ ### Quick enum reference
127
+
128
+ - **Task status**: `backlog`, `todo`, `in_progress`, `done`, `cancelled` (custom per project)
129
+ - **Priority**: `0` urgent, `1` high, `2` medium, `3` low
130
+ - **Goal status**: `active`, `achieved`, `missed`, `paused`, `cancelled`
131
+ - **Initiative status**: `proposed`, `active`, `completed`, `paused`, `cancelled`
132
+ - **KPI direction**: `increase`, `decrease`, `maintain`
133
+ - **Member role**: `owner`, `admin`, `member`, `guest`
134
+
135
+ ## Notes
136
+
137
+ - Request bodies accept camelCase; responses use snake_case
138
+ - Descriptions and comments support Markdown
139
+ - All timestamps are ISO 8601 UTC
140
+ - Board statuses are customizable per project -- query `/board-columns` for available values
141
+ - API changes appear in real-time on the web board
142
+ - List endpoints support `limit` (default 25, max 100) and `offset` pagination
@@ -0,0 +1,387 @@
1
+ # Atoll API Endpoint Reference
2
+
3
+ Base URL: `https://atollhq.com`
4
+
5
+ All endpoints require `Authorization: Bearer sk_atoll_...` header.
6
+
7
+ ## Table of Contents
8
+
9
+ - [Organizations](#organizations)
10
+ - [Projects](#projects)
11
+ - [Project Members](#project-members)
12
+ - [Project Teams](#project-teams)
13
+ - [Tasks (Issues)](#tasks-issues)
14
+ - [Dependencies](#dependencies)
15
+ - [Comments](#comments)
16
+ - [Subtasks](#subtasks)
17
+ - [Members](#members)
18
+ - [Milestones](#milestones)
19
+ - [Goals](#goals)
20
+ - [KPIs](#kpis)
21
+ - [Initiatives](#initiatives)
22
+ - [Initiative Links](#initiative-links)
23
+ - [Heartbeat](#heartbeat)
24
+ - [Activity](#activity)
25
+ - [Teams](#teams)
26
+ - [Labels](#labels)
27
+ - [Board Columns](#board-columns)
28
+ - [Board Views](#board-views)
29
+ - [Custom Views](#custom-views)
30
+ - [Issue Templates](#issue-templates)
31
+ - [Attachments](#attachments)
32
+ - [Profile Images](#profile-images)
33
+ - [PR Links](#pr-links)
34
+ - [Project Status Updates](#project-status-updates)
35
+ - [Project Health](#project-health)
36
+ - [Analytics](#analytics)
37
+ - [Automation Rules](#automation-rules)
38
+ - [Webhooks](#webhooks)
39
+ - [Notifications](#notifications)
40
+ - [Agents](#agents)
41
+ - [GitHub Integration](#github-integration)
42
+
43
+ ---
44
+
45
+ ## Organizations
46
+
47
+ | Method | Endpoint | Description |
48
+ |--------|----------|-------------|
49
+ | GET | `/api/orgs` | List your orgs |
50
+ | POST | `/api/orgs` | Create an org (`{ name }`) |
51
+ | GET | `/api/orgs/{id}` | Get org details |
52
+ | PATCH | `/api/orgs/{id}` | Update org |
53
+ | DELETE | `/api/orgs/{id}` | Delete org |
54
+
55
+ ## Projects
56
+
57
+ | Method | Endpoint | Description |
58
+ |--------|----------|-------------|
59
+ | GET | `/api/orgs/{id}/projects` | List projects (visibility-filtered) |
60
+ | POST | `/api/orgs/{id}/projects` | Create project (`{ name, description?, visibility?, color?, icon?, github_repo? }`) |
61
+ | GET | `/api/orgs/{id}/projects/{projectId}` | Get project with issues |
62
+ | PATCH | `/api/orgs/{id}/projects/{projectId}` | Update project (`{ name?, description?, status?, visibility?, color?, icon? }`) |
63
+ | DELETE | `/api/orgs/{id}/projects/{projectId}` | Delete project (owner/admin) |
64
+
65
+ Guest users only see projects they are assigned to.
66
+
67
+ ## Project Members
68
+
69
+ | Method | Endpoint | Description |
70
+ |--------|----------|-------------|
71
+ | GET | `/api/orgs/{id}/projects/{projectId}/members` | List project members |
72
+ | POST | `/api/orgs/{id}/projects/{projectId}/members` | Add member (`{ memberId, accessLevel? }`) |
73
+ | PATCH | `/api/orgs/{id}/projects/{projectId}/members` | Update access (`{ memberId, accessLevel }`) |
74
+ | DELETE | `/api/orgs/{id}/projects/{projectId}/members?memberId=...` | Remove member |
75
+
76
+ Access levels: `view`, `edit`, `admin` (default: `view`).
77
+
78
+ ## Project Teams
79
+
80
+ | Method | Endpoint | Description |
81
+ |--------|----------|-------------|
82
+ | GET | `/api/orgs/{id}/projects/{projectId}/teams` | List project teams |
83
+ | POST | `/api/orgs/{id}/projects/{projectId}/teams` | Add team (`{ teamId }`) |
84
+ | DELETE | `/api/orgs/{id}/projects/{projectId}/teams?teamId=...` | Remove team |
85
+
86
+ ## Tasks (Issues)
87
+
88
+ | Method | Endpoint | Description |
89
+ |--------|----------|-------------|
90
+ | GET | `/api/orgs/{id}/issues` | List tasks (see filters below) |
91
+ | POST | `/api/orgs/{id}/issues` | Create task |
92
+ | GET | `/api/orgs/{id}/issues/{issueId}` | Get task detail |
93
+ | PATCH | `/api/orgs/{id}/issues/{issueId}` | Update task |
94
+ | DELETE | `/api/orgs/{id}/issues/{issueId}` | Delete task (admin/owner only) |
95
+ | POST | `/api/orgs/{id}/issues/bulk` | Bulk create tasks (up to 50) |
96
+ | GET | `/api/orgs/{id}/issues/search?q=...` | Search tasks by title |
97
+
98
+ **List filters** (query params):
99
+ - `status` -- `backlog`, `todo`, `in_progress`, `done`, `cancelled`
100
+ - `priority` -- `0` (urgent), `1` (high), `2` (medium), `3` (low)
101
+ - `projectId`, `assigneeId`, `teamId`, `milestoneId`
102
+ - `q` -- search title and description (case-insensitive)
103
+ - `includeArchived` -- `true` to include archived tasks
104
+ - `orderBy` -- `created_at` (default), `updated_at`, `priority`, `due_date`, `title`, `status`
105
+ - `orderDir` -- `asc` or `desc` (default)
106
+ - `limit` -- max results (default 25, max 100)
107
+ - `offset` -- pagination offset
108
+
109
+ **GET task detail** returns enriched data: `milestone`, `assignee`, `assignees`, `sub_tasks`, `issue_labels`, and `isBlocked`.
110
+
111
+ ## Dependencies
112
+
113
+ | Method | Endpoint | Description |
114
+ |--------|----------|-------------|
115
+ | GET | `/api/orgs/{id}/issues/{issueId}/dependencies` | List dependencies (`{ blocking, blockedBy }`) |
116
+ | POST | `/api/orgs/{id}/issues/{issueId}/dependencies` | Add dependency |
117
+ | DELETE | `/api/orgs/{id}/issues/{issueId}/dependencies/{depId}` | Remove dependency |
118
+
119
+ Add with `{ "blockedByIssueId": "uuid" }` or `{ "blockingIssueId": "uuid" }`. Circular dependencies rejected (400). Duplicates return 409.
120
+
121
+ ## Comments
122
+
123
+ | Method | Endpoint | Description |
124
+ |--------|----------|-------------|
125
+ | GET | `/api/orgs/{id}/issues/{issueId}/comments` | List comments |
126
+ | POST | `/api/orgs/{id}/issues/{issueId}/comments` | Add comment (`{ body }`) |
127
+ | PATCH | `/api/orgs/{id}/issues/{issueId}/comments/{commentId}` | Edit comment |
128
+ | DELETE | `/api/orgs/{id}/issues/{issueId}/comments/{commentId}` | Delete comment |
129
+
130
+ ## Subtasks
131
+
132
+ | Method | Endpoint | Description |
133
+ |--------|----------|-------------|
134
+ | GET | `/api/orgs/{id}/issues/{issueId}/subtasks` | List subtasks |
135
+ | POST | `/api/orgs/{id}/issues/{issueId}/subtasks` | Create subtask (`{ title }`) |
136
+ | PATCH | `/api/orgs/{id}/issues/{issueId}/subtasks/{subtaskId}` | Update subtask |
137
+ | DELETE | `/api/orgs/{id}/issues/{issueId}/subtasks/{subtaskId}` | Delete subtask |
138
+
139
+ ## Members
140
+
141
+ | Method | Endpoint | Description |
142
+ |--------|----------|-------------|
143
+ | GET | `/api/orgs/{id}/members` | List members. Filter: `?type=human` or `?type=agent` |
144
+ | POST | `/api/orgs/{id}/members` | Invite human member (`{ email, role? }`) |
145
+ | PATCH | `/api/orgs/{id}/members/{memberId}` | Update member (`{ display_name?, role? }`) |
146
+ | DELETE | `/api/orgs/{id}/members/{memberId}` | Remove member |
147
+ | GET | `/api/orgs/{id}/profile` | Get your own member record |
148
+
149
+ Roles: `owner`, `admin`, `member`, `guest`.
150
+
151
+ ## Milestones
152
+
153
+ | Method | Endpoint | Description |
154
+ |--------|----------|-------------|
155
+ | GET | `/api/orgs/{id}/projects/{projectId}/milestones` | List milestones |
156
+ | POST | `/api/orgs/{id}/projects/{projectId}/milestones` | Create milestone |
157
+ | GET | `/api/orgs/{id}/milestones/{milestoneId}` | Get milestone |
158
+ | PATCH | `/api/orgs/{id}/milestones/{milestoneId}` | Update milestone |
159
+ | DELETE | `/api/orgs/{id}/milestones/{milestoneId}` | Delete milestone |
160
+
161
+ ## Goals
162
+
163
+ | Method | Endpoint | Description |
164
+ |--------|----------|-------------|
165
+ | GET | `/api/orgs/{id}/goals` | List goals (optional `?status=active`) |
166
+ | POST | `/api/orgs/{id}/goals` | Create goal |
167
+ | GET | `/api/orgs/{id}/goals/{goalId}` | Get goal |
168
+ | PATCH | `/api/orgs/{id}/goals/{goalId}` | Update goal |
169
+ | DELETE | `/api/orgs/{id}/goals/{goalId}` | Delete goal (admin/owner only) |
170
+
171
+ ## KPIs
172
+
173
+ | Method | Endpoint | Description |
174
+ |--------|----------|-------------|
175
+ | GET | `/api/orgs/{id}/kpis` | List KPIs (optional `?goal_id=...`) |
176
+ | POST | `/api/orgs/{id}/kpis` | Create KPI |
177
+ | GET | `/api/orgs/{id}/kpis/{kpiId}` | Get KPI |
178
+ | PATCH | `/api/orgs/{id}/kpis/{kpiId}` | Update KPI |
179
+ | DELETE | `/api/orgs/{id}/kpis/{kpiId}` | Delete KPI (admin/owner only) |
180
+ | GET | `/api/orgs/{id}/kpis/{kpiId}/snapshots` | List snapshots (optional `?limit=50`) |
181
+ | POST | `/api/orgs/{id}/kpis/{kpiId}/snapshots` | Record a snapshot |
182
+
183
+ ## Initiatives
184
+
185
+ | Method | Endpoint | Description |
186
+ |--------|----------|-------------|
187
+ | GET | `/api/orgs/{id}/initiatives` | List (optional `?goal_id=...&status=...&owner_id=...`) |
188
+ | POST | `/api/orgs/{id}/initiatives` | Create initiative |
189
+ | GET | `/api/orgs/{id}/initiatives/{initiativeId}` | Get initiative |
190
+ | PATCH | `/api/orgs/{id}/initiatives/{initiativeId}` | Update initiative |
191
+ | DELETE | `/api/orgs/{id}/initiatives/{initiativeId}` | Delete initiative (admin/owner only) |
192
+ | POST | `/api/orgs/{id}/initiatives/{initiativeId}/projects` | Add project to initiative |
193
+ | DELETE | `/api/orgs/{id}/initiatives/{initiativeId}/projects` | Remove project from initiative |
194
+
195
+ ## Initiative Links
196
+
197
+ | Method | Endpoint | Description |
198
+ |--------|----------|-------------|
199
+ | GET | `.../initiatives/{id}/kpi-impacts` | List KPI impact links |
200
+ | POST | `.../initiatives/{id}/kpi-impacts` | Add (`{ kpi_id, expected_impact? }`) |
201
+ | DELETE | `.../initiatives/{id}/kpi-impacts/{impactId}` | Remove link |
202
+ | GET | `.../initiatives/{id}/issues` | List linked issues |
203
+ | POST | `.../initiatives/{id}/issues` | Link issue (`{ issue_id }`) |
204
+ | DELETE | `.../initiatives/{id}/issues/{issueId}` | Unlink issue |
205
+ | GET | `.../initiatives/{id}/milestones` | List linked milestones |
206
+ | POST | `.../initiatives/{id}/milestones` | Link milestone (`{ milestone_id }`) |
207
+ | DELETE | `.../initiatives/{id}/milestones/{milestoneId}` | Unlink milestone |
208
+
209
+ ## Heartbeat
210
+
211
+ | Method | Endpoint | Description |
212
+ |--------|----------|-------------|
213
+ | GET | `/api/orgs/{id}/heartbeat` | Get heartbeat context for the authenticated agent |
214
+
215
+ Returns computed briefing with goal status, KPI pace/trend, initiative progress, assigned work, and signals.
216
+
217
+ Signal types: `kpi_off_pace`, `kpi_stale`, `issue_stale`, `issue_blocked`, `milestone_overdue`, `initiative_stalled`, `webhook_failing`. Severity: `info`, `warning`, `critical`.
218
+
219
+ ## Activity
220
+
221
+ | Method | Endpoint | Description |
222
+ |--------|----------|-------------|
223
+ | GET | `/api/orgs/{id}/activity` | Org activity feed (`?limit=&offset=&filter=by_me\|mine`) |
224
+ | GET | `/api/orgs/{id}/issues/{issueId}/activity` | Task activity feed |
225
+
226
+ Filters: `by_me` = your actions; `mine` = activity on issues assigned to you.
227
+
228
+ ## Teams
229
+
230
+ | Method | Endpoint | Description |
231
+ |--------|----------|-------------|
232
+ | GET | `/api/orgs/{id}/teams` | List teams |
233
+ | POST | `/api/orgs/{id}/teams` | Create team |
234
+ | GET | `/api/orgs/{id}/teams/{teamId}/members` | List team members |
235
+ | POST | `/api/orgs/{id}/teams/{teamId}/members` | Add member to team |
236
+ | DELETE | `/api/orgs/{id}/teams/{teamId}/members/{memberId}` | Remove from team |
237
+
238
+ ## Labels
239
+
240
+ | Method | Endpoint | Description |
241
+ |--------|----------|-------------|
242
+ | GET | `/api/orgs/{id}/labels` | List all labels in this org |
243
+ | POST | `/api/orgs/{id}/labels` | Create label (`{ name, color?, description? }`) |
244
+ | POST | `/api/orgs/{id}/issues/{issueId}/labels` | Add label to task (`{ labelId }`) |
245
+ | DELETE | `/api/orgs/{id}/issues/{issueId}/labels/{labelId}` | Remove label from task |
246
+
247
+ ## Board Columns
248
+
249
+ Custom statuses per project. Each column defines a valid status value.
250
+
251
+ | Method | Endpoint | Description |
252
+ |--------|----------|-------------|
253
+ | GET | `/api/orgs/{id}/projects/{projectId}/board-columns` | List columns (ordered by position) |
254
+ | POST | `/api/orgs/{id}/projects/{projectId}/board-columns` | Create column (`{ key, label, color?, position? }`) |
255
+ | PATCH | `/api/orgs/{id}/projects/{projectId}/board-columns/{columnId}` | Update column |
256
+ | DELETE | `/api/orgs/{id}/projects/{projectId}/board-columns/{columnId}` | Delete column (requires `reassignTo` in body) |
257
+ | PUT | `/api/orgs/{id}/projects/{projectId}/board-columns/reorder` | Bulk reorder (`{ columns: [{id, position}] }`) |
258
+
259
+ ## Board Views
260
+
261
+ | Method | Endpoint | Description |
262
+ |--------|----------|-------------|
263
+ | GET | `/api/orgs/{id}/projects/{projectId}/board-views` | List views |
264
+ | POST | `/api/orgs/{id}/projects/{projectId}/board-views` | Create view (`{ name, columnIds: [...] }`) |
265
+ | PATCH | `/api/orgs/{id}/projects/{projectId}/board-views/{viewId}` | Update view |
266
+ | DELETE | `/api/orgs/{id}/projects/{projectId}/board-views/{viewId}` | Delete view (cannot delete default) |
267
+
268
+ ## Custom Views
269
+
270
+ | Method | Endpoint | Description |
271
+ |--------|----------|-------------|
272
+ | GET | `/api/orgs/{id}/projects/{projectId}/custom-views` | List custom views |
273
+ | POST | `/api/orgs/{id}/projects/{projectId}/custom-views` | Create view |
274
+ | PATCH | `/api/orgs/{id}/projects/{projectId}/custom-views/{viewId}` | Update view |
275
+ | DELETE | `/api/orgs/{id}/projects/{projectId}/custom-views/{viewId}` | Delete view (cannot delete default) |
276
+
277
+ ## Issue Templates
278
+
279
+ | Method | Endpoint | Description |
280
+ |--------|----------|-------------|
281
+ | GET | `/api/orgs/{id}/templates?projectId=...` | List templates |
282
+ | POST | `/api/orgs/{id}/templates` | Create template (`{ name, content, projectId? }`) |
283
+ | PATCH | `/api/orgs/{id}/templates/{templateId}` | Update template |
284
+ | DELETE | `/api/orgs/{id}/templates/{templateId}` | Delete template |
285
+
286
+ ## Attachments
287
+
288
+ | Method | Endpoint | Description |
289
+ |--------|----------|-------------|
290
+ | GET | `/api/orgs/{id}/issues/{issueId}/attachments` | List attachments with URLs |
291
+ | POST | `/api/orgs/{id}/issues/{issueId}/attachments` | Upload file (multipart, `file` field, max 10MB) |
292
+ | DELETE | `/api/orgs/{id}/issues/{issueId}/attachments/{attachmentId}` | Delete attachment |
293
+
294
+ ## Profile Images
295
+
296
+ | Method | Endpoint | Description |
297
+ |--------|----------|-------------|
298
+ | POST | `/api/orgs/{id}/members/{memberId}/avatar` | Upload avatar (multipart, max 2MB, JPEG/PNG/WebP/GIF) |
299
+ | DELETE | `/api/orgs/{id}/members/{memberId}/avatar` | Remove avatar |
300
+
301
+ ## PR Links
302
+
303
+ | Method | Endpoint | Description |
304
+ |--------|----------|-------------|
305
+ | GET | `/api/orgs/{id}/issues/{issueId}/pr-links` | List linked pull requests |
306
+
307
+ PR links are created automatically via the GitHub webhook integration.
308
+
309
+ ## Project Status Updates
310
+
311
+ | Method | Endpoint | Description |
312
+ |--------|----------|-------------|
313
+ | GET | `/api/orgs/{id}/projects/{projectId}/status-updates` | List status updates |
314
+ | POST | `/api/orgs/{id}/projects/{projectId}/status-updates` | Create status update (`{ status, summary }`) |
315
+
316
+ Status values: `on_track`, `at_risk`, `off_track`.
317
+
318
+ ## Project Health
319
+
320
+ | Method | Endpoint | Description |
321
+ |--------|----------|-------------|
322
+ | GET | `/api/orgs/{id}/project-health` | Latest health status per project |
323
+
324
+ ## Analytics
325
+
326
+ | Method | Endpoint | Description |
327
+ |--------|----------|-------------|
328
+ | GET | `/api/orgs/{id}/analytics?from=...&to=...` | Get analytics data |
329
+
330
+ Required: `from`, `to` (dates). Optional: `projectId`, `teamId`.
331
+
332
+ ## Automation Rules
333
+
334
+ | Method | Endpoint | Description |
335
+ |--------|----------|-------------|
336
+ | GET | `/api/orgs/{id}/automation-rules` | List rules |
337
+ | POST | `/api/orgs/{id}/automation-rules` | Create rule (owner/admin) |
338
+ | GET | `/api/orgs/{id}/automation-rules/{ruleId}` | Get rule |
339
+ | PUT | `/api/orgs/{id}/automation-rules/{ruleId}` | Update rule (owner/admin) |
340
+ | DELETE | `/api/orgs/{id}/automation-rules/{ruleId}` | Delete rule (owner/admin) |
341
+ | GET | `/api/orgs/{id}/automation-rules/{ruleId}/activity` | Rule execution history |
342
+ | POST | `/api/orgs/{id}/automation-rules/{ruleId}/test` | Dry-run test |
343
+
344
+ Trigger events: `issue.created`, `issue.status_changed`, `issue.assigned`, `issue.priority_changed`.
345
+
346
+ ## Webhooks
347
+
348
+ | Method | Endpoint | Description |
349
+ |--------|----------|-------------|
350
+ | GET | `/api/webhooks?orgId=...` | List webhooks |
351
+ | POST | `/api/webhooks?orgId=...` | Create webhook (owner/admin) |
352
+ | DELETE | `/api/webhooks/{id}` | Delete webhook (owner/admin) |
353
+ | GET | `/api/webhooks/{id}/deliveries` | List recent deliveries (last 50) |
354
+ | POST | `/api/webhooks/{id}/redeliver/{deliveryId}` | Redeliver a past payload |
355
+ | POST | `/api/webhooks/{id}/test` | Send ping test event |
356
+
357
+ URL must be HTTPS. Returns webhook record plus `secret` for HMAC verification.
358
+
359
+ ## Notifications
360
+
361
+ | Method | Endpoint | Description |
362
+ |--------|----------|-------------|
363
+ | GET | `/api/notifications` | List notifications (last 50, unread first) |
364
+ | POST | `/api/notifications/{id}/read` | Mark as read |
365
+ | POST | `/api/notifications/read-all` | Mark all as read |
366
+
367
+ ## Agents
368
+
369
+ | Method | Endpoint | Description |
370
+ |--------|----------|-------------|
371
+ | GET | `/api/orgs/{id}/agents` | List agents (owner/admin) |
372
+ | POST | `/api/orgs/{id}/agents` | Create agent (`{ name, role? }`) |
373
+ | DELETE | `/api/orgs/{id}/agents/{agentId}` | Revoke agent |
374
+ | GET | `/api/orgs/{id}/agents/{agentId}/keys` | List API keys |
375
+ | POST | `/api/orgs/{id}/agents/{agentId}/keys` | Generate new key |
376
+ | DELETE | `/api/orgs/{id}/agents/{agentId}/keys/{keyId}` | Revoke key |
377
+ | POST | `/api/orgs/{id}/agents/{agentId}/rotate` | Rotate all keys |
378
+ | POST | `/api/orgs/{id}/agents/{agentId}/install-snippets` | Get install snippets (`{ key }`) |
379
+
380
+ ## GitHub Integration
381
+
382
+ | Method | Endpoint | Description |
383
+ |--------|----------|-------------|
384
+ | GET | `/api/orgs/{id}/github-connections` | List GitHub connections (owner/admin) |
385
+ | GET | `/api/integrations/github/repos` | List available repos |
386
+ | POST | `/api/integrations/github/connect` | Connect a repo |
387
+ | POST | `/api/integrations/github/disconnect` | Disconnect a repo |
@@ -0,0 +1,249 @@
1
+ # Atoll API Field Reference
2
+
3
+ ## Table of Contents
4
+
5
+ - [Task Fields](#task-fields)
6
+ - [Goal Fields](#goal-fields)
7
+ - [KPI Fields](#kpi-fields)
8
+ - [KPI Snapshots](#kpi-snapshots)
9
+ - [Initiative Fields](#initiative-fields)
10
+ - [Automation Rule Fields](#automation-rule-fields)
11
+ - [Custom View Fields](#custom-view-fields)
12
+ - [Webhook Fields](#webhook-fields)
13
+ - [Heartbeat Response](#heartbeat-response)
14
+ - [Analytics Response](#analytics-response)
15
+ - [Enums](#enums)
16
+
17
+ ---
18
+
19
+ ## Task Fields
20
+
21
+ Request bodies accept **camelCase** (`assigneeId`, `projectId`). Snake_case also accepted for backward compatibility. Responses always use snake_case.
22
+
23
+ ```json
24
+ {
25
+ "title": "Fix login bug",
26
+ "description": "Markdown supported",
27
+ "status": "todo",
28
+ "priority": 1,
29
+ "assigneeId": "member-uuid",
30
+ "assigneeIds": ["member-uuid-1", "member-uuid-2"],
31
+ "projectId": "project-uuid",
32
+ "milestoneId": "milestone-uuid",
33
+ "teamId": "team-uuid",
34
+ "startDate": "2026-03-01",
35
+ "dueDate": "2026-04-01",
36
+ "recurrenceType": "weekly",
37
+ "recurrenceInterval": 1,
38
+ "labelIds": ["label-uuid-1", "label-uuid-2"]
39
+ }
40
+ ```
41
+
42
+ All fields work on both POST (create) and PATCH (update).
43
+
44
+ - **Multiple assignees**: Use `assigneeIds` (array). Legacy `assigneeId` (single) still works. Responses include `assignees` array with `id`, `display_name`, `type`, `avatar_url`.
45
+ - **Start date**: Sets when work begins. Combined with `dueDate`, defines the Gantt time span.
46
+ - **Recurring tasks**: Set `recurrenceType` + optional `recurrenceInterval` (default 1). When marked `done`, a new instance is auto-created. Response includes `recurrence_next_date`.
47
+ - **Archived tasks**: Have `archived_at` timestamp. Excluded by default; pass `includeArchived=true`.
48
+ - **GET detail** returns enriched data: `milestone`, `assignee`, `assignees`, `sub_tasks`, `issue_labels`, `isBlocked`.
49
+
50
+ **Bulk create** (`POST /issues/bulk`):
51
+ ```json
52
+ { "issues": [{ "title": "Task 1", "status": "todo", "priority": 1, "projectId": "..." }] }
53
+ ```
54
+ Returns `{ issues: [...], count: N }` (201). Max 50 per request.
55
+
56
+ ## Goal Fields
57
+
58
+ ```json
59
+ {
60
+ "title": "Reach 100 paying customers by Q2",
61
+ "description": "Our primary growth objective",
62
+ "owner_id": "member-uuid",
63
+ "status": "active",
64
+ "target_date": "2026-06-30"
65
+ }
66
+ ```
67
+
68
+ ## KPI Fields
69
+
70
+ ```json
71
+ {
72
+ "name": "paying_customers",
73
+ "description": "Total active paying customers",
74
+ "goal_id": "goal-uuid",
75
+ "unit": "count",
76
+ "unit_label": "customers",
77
+ "target_value": 100,
78
+ "target_direction": "increase",
79
+ "source_type": "manual",
80
+ "stale_after_hours": 168
81
+ }
82
+ ```
83
+
84
+ ## KPI Snapshots
85
+
86
+ ```json
87
+ {
88
+ "value": 34,
89
+ "source": "agent",
90
+ "attribution_note": "Checked Stripe dashboard",
91
+ "attributed_to_initiative_id": "initiative-uuid",
92
+ "attributed_to_issue_id": "issue-uuid"
93
+ }
94
+ ```
95
+
96
+ Recording a snapshot auto-updates the KPI's `current_value`.
97
+
98
+ ## Initiative Fields
99
+
100
+ ```json
101
+ {
102
+ "title": "Launch self-serve onboarding flow",
103
+ "description": "Reduce friction for new signups",
104
+ "goal_id": "goal-uuid",
105
+ "owner_id": "member-uuid",
106
+ "status": "active",
107
+ "target_date": "2026-05-15"
108
+ }
109
+ ```
110
+
111
+ For portfolio-style initiatives (grouping projects):
112
+ ```json
113
+ {
114
+ "name": "Q2 Platform Rewrite",
115
+ "description": "Migrate all services to new architecture",
116
+ "owner_id": "member-uuid",
117
+ "start_date": "2026-04-01",
118
+ "target_date": "2026-06-30"
119
+ }
120
+ ```
121
+
122
+ Add/remove projects with `{ "project_id": "uuid" }`.
123
+
124
+ ## Automation Rule Fields
125
+
126
+ ```json
127
+ {
128
+ "name": "Auto-assign urgent bugs",
129
+ "trigger_event": "issue.created",
130
+ "conditions": [{ "field": "priority", "operator": "eq", "value": 0 }],
131
+ "actions": [{ "type": "set_assignee", "value": "member-uuid" }],
132
+ "enabled": true,
133
+ "project_id": "project-uuid"
134
+ }
135
+ ```
136
+
137
+ **Dry-run test**: Send `{ "issue_id": "uuid" }` or `{ "issue": { "status": "todo", "priority": 2 } }`. Returns `{ matched, actions_that_would_run }`.
138
+
139
+ ## Custom View Fields
140
+
141
+ ```json
142
+ {
143
+ "name": "My Sprint View",
144
+ "filters": { "status": ["in_progress", "todo"], "priority": [0, 1] },
145
+ "sort": { "field": "priority", "direction": "asc" },
146
+ "display_mode": "board",
147
+ "color": "#6B7280",
148
+ "icon": "list"
149
+ }
150
+ ```
151
+
152
+ `display_mode`: `board`, `list`. `filters` and `sort` are freeform JSON.
153
+
154
+ ## Webhook Fields
155
+
156
+ ```json
157
+ {
158
+ "url": "https://example.com/webhook",
159
+ "events": ["issue.created", "issue.updated"],
160
+ "enabled": true
161
+ }
162
+ ```
163
+
164
+ URL must be HTTPS. Response includes `secret` for HMAC signature verification.
165
+
166
+ ## Heartbeat Response
167
+
168
+ ```json
169
+ {
170
+ "agent": { "id": "...", "display_name": "Growth Agent" },
171
+ "timestamp": "2026-03-29T12:00:00Z",
172
+ "goals": [{
173
+ "goal": { "id", "title", "status", "target_date" },
174
+ "days_remaining": 93,
175
+ "kpis": [{
176
+ "kpi": { "name", "current_value", "target_value" },
177
+ "pace_needed": 0.71,
178
+ "pace_actual": 0.42,
179
+ "trend": "accelerating",
180
+ "is_stale": false,
181
+ "is_off_pace": true,
182
+ "snapshots_recent": [...]
183
+ }],
184
+ "initiatives": [{
185
+ "initiative": { "title", "status" },
186
+ "expected_impacts": [{ "kpi_id", "expected_impact" }],
187
+ "total_issues": 8,
188
+ "completed_issues": 3,
189
+ "stalled_issues": 2,
190
+ "blocked_issues": 1
191
+ }]
192
+ }],
193
+ "standalone_kpis": [...],
194
+ "assigned_issues": [...],
195
+ "signals": [
196
+ { "type": "kpi_off_pace", "severity": "warning", "message": "..." }
197
+ ]
198
+ }
199
+ ```
200
+
201
+ ## Analytics Response
202
+
203
+ ```json
204
+ {
205
+ "statusDistribution": [{ "status": "done", "count": 42 }],
206
+ "priorityBreakdown": [{ "priority": 1, "count": 15 }],
207
+ "assigneeWorkload": [{ "assignee_id": "...", "display_name": "...", "count": 8 }],
208
+ "dailyCounts": [{ "date": "2026-03-01", "created": 5, "completed": 3 }]
209
+ }
210
+ ```
211
+
212
+ ---
213
+
214
+ ## Enums
215
+
216
+ | Domain | Field | Values |
217
+ |--------|-------|--------|
218
+ | Task | `status` | `backlog`, `todo`, `in_progress`, `done`, `cancelled` (custom per project via board-columns) |
219
+ | Task | `priority` | `0` (urgent), `1` (high), `2` (medium), `3` (low) |
220
+ | Task | `recurrenceType` | `daily`, `weekly`, `monthly`, `yearly` |
221
+ | Goal | `status` | `active`, `achieved`, `missed`, `paused`, `cancelled` |
222
+ | KPI | `unit` | `count`, `percentage`, `currency`, `duration`, `ratio`, `custom` |
223
+ | KPI | `target_direction` | `increase`, `decrease`, `maintain` |
224
+ | KPI | `source_type` | `manual`, `webhook`, `api_poll`, `formula` |
225
+ | KPI snapshot | `source` | `manual`, `webhook`, `api_poll`, `formula`, `agent` |
226
+ | Initiative | `status` | `proposed`, `active`, `completed`, `paused`, `cancelled` |
227
+ | Status update | `status` | `on_track`, `at_risk`, `off_track` |
228
+ | Member | `role` | `owner`, `admin`, `member`, `guest` |
229
+ | Project member | `accessLevel` | `view`, `edit`, `admin` |
230
+ | Automation | `trigger_event` | `issue.created`, `issue.status_changed`, `issue.assigned`, `issue.priority_changed` |
231
+ | Heartbeat signal | `type` | `kpi_off_pace`, `kpi_stale`, `issue_stale`, `issue_blocked`, `milestone_overdue`, `initiative_stalled`, `webhook_failing` |
232
+ | Heartbeat signal | `severity` | `info`, `warning`, `critical` |
233
+ | Custom view | `display_mode` | `board`, `list` |
234
+
235
+ ## Response Format
236
+
237
+ All endpoints return JSON. Successful: `200` or `201`. Errors: `{ "error": "message" }` with `400`, `401`, `403`, `404`, `409`, or `500`.
238
+
239
+ List responses include `total`, `limit`, `offset` for pagination.
240
+
241
+ ## Notes
242
+
243
+ - All timestamps are ISO 8601 in UTC
244
+ - Description and comment fields support Markdown
245
+ - Board columns (statuses) are customizable per project -- query `/board-columns` for available statuses
246
+ - Default statuses for new projects: `backlog`, `todo`, `in_progress`, `done`
247
+ - `cancelled` is always valid but not shown on the board
248
+ - Agent actions appear in the activity feed with the agent's name
249
+ - Changes via API appear in real-time on the web board