From 62d8b3947425a0985ac998a15b66ae3c38ed8bf4 Mon Sep 17 00:00:00 2001 From: Aron Prins Date: Wed, 1 Apr 2026 13:49:11 +0200 Subject: [PATCH 1/5] feat(skills): add paperclip-routines skill MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a new skill that documents how to create and manage Paperclip routines — recurring tasks that fire on a schedule, webhook, or API call and dispatch an execution issue to the assigned agent. --- skills/paperclip-routines/SKILL.md | 210 +++++++++++++++++++++++++++++ 1 file changed, 210 insertions(+) create mode 100644 skills/paperclip-routines/SKILL.md diff --git a/skills/paperclip-routines/SKILL.md b/skills/paperclip-routines/SKILL.md new file mode 100644 index 00000000..fcad88fa --- /dev/null +++ b/skills/paperclip-routines/SKILL.md @@ -0,0 +1,210 @@ +--- +name: paperclip-routines +description: > + Create, manage, and trigger Paperclip routines — recurring tasks that fire on + a schedule (cron), webhook, or API call and create an execution issue for the + assigned agent. Use when you need to set up recurring work, add or modify + triggers, inspect run history, or reason about concurrency and catch-up + behaviour. +--- + +# Paperclip Routines + +Routines are recurring tasks. Each time a routine fires it creates an execution issue assigned to the routine's agent — the agent picks it up in the normal heartbeat flow. + +A routine has: +- One assigned agent and one project +- One or more triggers (schedule, webhook, or API) +- A concurrency policy (what to do when a previous run is still active) +- A catch-up policy (what to do with missed scheduled runs) + +**Authorization:** Agents can read all routines in their company but can only create/manage routines assigned to themselves. Board operators have full access including reassignment. + +--- + +## Lifecycle + +``` +active <-> paused +active -> archived (terminal — cannot be reactivated) +``` + +Paused routines do not fire. Archived routines do not fire and cannot be unarchived. + +--- + +## Creating a Routine + +``` +POST /api/companies/{companyId}/routines +{ + "title": "Weekly CEO briefing", + "description": "Compile status report and post to Slack", + "assigneeAgentId": "{agentId}", + "projectId": "{projectId}", + "goalId": "{goalId}", // optional + "parentIssueId": "{issueId}", // optional — parent for run issues + "priority": "medium", + "status": "active", + "concurrencyPolicy": "coalesce_if_active", + "catchUpPolicy": "skip_missed" +} +``` + +| Field | Required | Notes | +|-------|----------|-------| +| `title` | yes | Max 200 chars | +| `assigneeAgentId` | yes | Agents: must be themselves | +| `projectId` | yes | | +| `goalId` | no | Inherited by run issues | +| `parentIssueId` | no | Run issues become children of this issue | +| `priority` | no | `critical` `high` `medium`(default) `low` | +| `status` | no | `active`(default) `paused` `archived` | +| `concurrencyPolicy` | no | See below | +| `catchUpPolicy` | no | See below | + +--- + +## Concurrency Policies + +Controls what happens when a trigger fires while the previous run issue is still open/active. + +| Policy | Behaviour | +|--------|-----------| +| `coalesce_if_active` **(default)** | New run is marked `coalesced` and linked to the existing active run — no new issue created | +| `skip_if_active` | New run is marked `skipped` and linked to the existing active run — no new issue created | +| `always_enqueue` | Always create a new issue regardless of active runs | + +--- + +## Catch-Up Policies + +Controls what happens with scheduled runs that were missed (e.g. server downtime). + +| Policy | Behaviour | +|--------|-----------| +| `skip_missed` **(default)** | Missed runs are dropped | +| `enqueue_missed_with_cap` | Missed runs are enqueued, capped at 25 | + +--- + +## Adding Triggers + +A routine can have multiple triggers of different kinds. + +``` +POST /api/routines/{routineId}/triggers +``` + +### Schedule (cron) + +```json +{ + "kind": "schedule", + "cronExpression": "0 9 * * 1", + "timezone": "Europe/Amsterdam" +} +``` + +- `cronExpression`: standard 5-field cron syntax +- `timezone`: IANA timezone string (e.g. `UTC`, `America/New_York`) +- The server computes `nextRunAt` automatically + +### Webhook + +```json +{ + "kind": "webhook", + "signingMode": "hmac_sha256", + "replayWindowSec": 300 +} +``` + +- `signingMode`: `bearer` (default) or `hmac_sha256` +- `replayWindowSec`: 30–86400 (default 300) +- Response includes the webhook URL (`publicId`-based) and the signing secret +- Fire externally: `POST /api/routine-triggers/public/{publicId}/fire` + - Bearer: `Authorization: Bearer ` + - HMAC: `X-Paperclip-Signature` + `X-Paperclip-Timestamp` headers + +### API (manual only) + +```json +{ + "kind": "api" +} +``` + +No configuration. Fire via the manual run endpoint. + +--- + +## Updating and Deleting Triggers + +``` +PATCH /api/routine-triggers/{triggerId} +{ "enabled": false, "cronExpression": "0 10 * * 1" } + +DELETE /api/routine-triggers/{triggerId} +``` + +To rotate a webhook secret (old secret is immediately invalidated): + +``` +POST /api/routine-triggers/{triggerId}/rotate-secret +``` + +--- + +## Manual Run + +Fires a run immediately, bypassing the schedule. Concurrency policy still applies. + +``` +POST /api/routines/{routineId}/run +{ + "source": "manual", + "triggerId": "{triggerId}", // optional — attributes run to a specific trigger + "payload": { "context": "..." }, // optional — passed to the run issue + "idempotencyKey": "unique-key" // optional — prevents duplicate runs +} +``` + +--- + +## Updating a Routine + +All create fields are updatable. Agents cannot reassign a routine to another agent. + +``` +PATCH /api/routines/{routineId} +{ "status": "paused", "title": "New title" } +``` + +--- + +## Reading Routines and Runs + +``` +GET /api/companies/{companyId}/routines // list all +GET /api/routines/{routineId} // detail with triggers +GET /api/routines/{routineId}/runs?limit=50 // run history (default 50) +``` + +--- + +## Key Endpoints + +| Action | Endpoint | +|--------|----------| +| List routines | `GET /api/companies/{companyId}/routines` | +| Get routine | `GET /api/routines/{routineId}` | +| Create routine | `POST /api/companies/{companyId}/routines` | +| Update routine | `PATCH /api/routines/{routineId}` | +| Add trigger | `POST /api/routines/{routineId}/triggers` | +| Update trigger | `PATCH /api/routine-triggers/{triggerId}` | +| Delete trigger | `DELETE /api/routine-triggers/{triggerId}` | +| Rotate webhook secret | `POST /api/routine-triggers/{triggerId}/rotate-secret` | +| Manual run | `POST /api/routines/{routineId}/run` | +| Fire webhook (external) | `POST /api/routine-triggers/public/{publicId}/fire` | +| List runs | `GET /api/routines/{routineId}/runs` | From e5b2e8b29bafab198c58071fd0b56f0e632a40e0 Mon Sep 17 00:00:00 2001 From: Aron Prins Date: Wed, 1 Apr 2026 13:56:10 +0200 Subject: [PATCH 2/5] fix(skills): address greptile review on paperclip-routines skill - Add missing `description` field to the Creating a Routine field table - Document optional `label` field available on all trigger kinds --- skills/paperclip-routines/SKILL.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/skills/paperclip-routines/SKILL.md b/skills/paperclip-routines/SKILL.md index fcad88fa..29bbc3df 100644 --- a/skills/paperclip-routines/SKILL.md +++ b/skills/paperclip-routines/SKILL.md @@ -54,6 +54,7 @@ POST /api/companies/{companyId}/routines | Field | Required | Notes | |-------|----------|-------| | `title` | yes | Max 200 chars | +| `description` | no | Human-readable description of the routine | | `assigneeAgentId` | yes | Agents: must be themselves | | `projectId` | yes | | | `goalId` | no | Inherited by run issues | @@ -92,6 +93,8 @@ Controls what happens with scheduled runs that were missed (e.g. server downtime A routine can have multiple triggers of different kinds. +All trigger kinds accept an optional `label` field (max 120 chars) — useful for distinguishing multiple triggers of the same kind on one routine. + ``` POST /api/routines/{routineId}/triggers ``` From 3c99ab8d013b9df804abb177ac826c2d233b2a33 Mon Sep 17 00:00:00 2001 From: Aron Prins Date: Thu, 2 Apr 2026 10:52:52 +0200 Subject: [PATCH 3/5] chore: improve api documentation and implementing routines properly. --- skills/paperclip/SKILL.md | 29 +++++++++- skills/paperclip/references/api-reference.md | 61 +++++++++++++++++++- 2 files changed, 86 insertions(+), 4 deletions(-) diff --git a/skills/paperclip/SKILL.md b/skills/paperclip/SKILL.md index 1d319ad3..d495f28f 100644 --- a/skills/paperclip/SKILL.md +++ b/skills/paperclip/SKILL.md @@ -3,9 +3,10 @@ name: paperclip description: > Interact with the Paperclip control plane API to manage tasks, coordinate with other agents, and follow company governance. Use when you need to check - assignments, update task status, delegate work, post comments, or call any - Paperclip API endpoint. Do NOT use for the actual domain work itself (writing - code, research, etc.) — only for Paperclip coordination. + assignments, update task status, delegate work, post comments, set up or manage + routines (recurring scheduled tasks), or call any Paperclip API endpoint. Do NOT + use for the actual domain work itself (writing code, research, etc.) — only for + Paperclip coordination. --- # Paperclip Skill @@ -137,6 +138,17 @@ Authorized managers can install company skills independently of hiring, then ass If you are asked to install a skill for the company or an agent you MUST read: `skills/paperclip/references/company-skills.md` +## Routines + +Routines are recurring tasks. Each time a routine fires it creates an execution issue assigned to the routine's agent — the agent picks it up in the normal heartbeat flow. + +- Create and manage routines with the routines API — agents can only manage routines assigned to themselves. +- Add triggers per routine: `schedule` (cron), `webhook`, or `api` (manual). +- Control concurrency and catch-up behaviour with `concurrencyPolicy` and `catchUpPolicy`. + +If you are asked to create or manage routines you MUST read: +`skills/paperclip/references/api-reference.md` + ## Critical Rules - **Always checkout** before working. Never PATCH to `in_progress` manually. @@ -291,6 +303,17 @@ PATCH /api/agents/{agentId}/instructions-path | List issue attachments | `GET /api/issues/:issueId/attachments` | | Get attachment content | `GET /api/attachments/:attachmentId/content` | | Delete attachment | `DELETE /api/attachments/:attachmentId` | +| List routines | `GET /api/companies/:companyId/routines` | +| Get routine | `GET /api/routines/:routineId` | +| Create routine | `POST /api/companies/:companyId/routines` | +| Update routine | `PATCH /api/routines/:routineId` | +| Add trigger | `POST /api/routines/:routineId/triggers` | +| Update trigger | `PATCH /api/routine-triggers/:triggerId` | +| Delete trigger | `DELETE /api/routine-triggers/:triggerId` | +| Rotate webhook secret | `POST /api/routine-triggers/:triggerId/rotate-secret` | +| Manual run | `POST /api/routines/:routineId/run` | +| Fire webhook (external) | `POST /api/routine-triggers/public/:publicId/fire` | +| List runs | `GET /api/routines/:routineId/runs` | ## Company Import / Export diff --git a/skills/paperclip/references/api-reference.md b/skills/paperclip/references/api-reference.md index aea4250c..77f95d78 100644 --- a/skills/paperclip/references/api-reference.md +++ b/skills/paperclip/references/api-reference.md @@ -597,7 +597,15 @@ Terminal states: `done`, `cancelled` | GET | `/api/agents/me/inbox/mine?userId=:userId` | Mine-tab issue list for a specific board user | | GET | `/api/agents/:agentId` | Agent details + chain of command | | GET | `/api/companies/:companyId/agents` | List all agents in company | +| POST | `/api/companies/:companyId/agents` | Create agent directly (no approval) | +| PATCH | `/api/agents/:agentId` | Update agent config or budget | +| POST | `/api/agents/:agentId/pause` | Temporarily stop heartbeats | +| POST | `/api/agents/:agentId/resume` | Resume a paused agent | +| POST | `/api/agents/:agentId/terminate` | Permanently deactivate agent (irreversible) | +| POST | `/api/agents/:agentId/keys` | Create long-lived API key (full value shown once) | +| POST | `/api/agents/:agentId/heartbeat/invoke` | Manually trigger a heartbeat | | GET | `/api/companies/:companyId/org` | Org chart tree | +| GET | `/api/companies/:companyId/adapters/:adapterType/models` | List selectable models for an adapter type | | PATCH | `/api/agents/:agentId/instructions-path` | Set/clear instructions path (`AGENTS.md`) | | GET | `/api/agents/:agentId/config-revisions` | List config revisions | | POST | `/api/agents/:agentId/config-revisions/:revisionId/rollback` | Roll back config | @@ -608,6 +616,7 @@ Terminal states: `done`, `cancelled` | ------ | ---------------------------------- | ---------------------------------------------------------------------------------------- | | GET | `/api/companies/:companyId/issues` | List issues, sorted by priority. Filters: `?status=`, `?assigneeAgentId=`, `?assigneeUserId=`, `?projectId=`, `?labelId=`, `?q=` (full-text search across title, identifier, description, comments) | | GET | `/api/issues/:issueId` | Issue details + ancestors | +| GET | `/api/issues/:issueId/heartbeat-context` | Compact context for heartbeat: issue state, ancestor summaries, comment cursor | | POST | `/api/companies/:companyId/issues` | Create issue | | PATCH | `/api/issues/:issueId` | Update issue (optional `comment` field adds a comment in same call) | | POST | `/api/issues/:issueId/checkout` | Atomic checkout (claim + start). Idempotent if you already own it. | @@ -615,8 +624,13 @@ Terminal states: `done`, `cancelled` | GET | `/api/issues/:issueId/comments` | List comments | | GET | `/api/issues/:issueId/comments/:commentId` | Get a specific comment by ID | | POST | `/api/issues/:issueId/comments` | Add comment (@-mentions trigger wakeups) | +| GET | `/api/issues/:issueId/documents` | List issue documents | +| GET | `/api/issues/:issueId/documents/:key` | Get issue document by key | +| PUT | `/api/issues/:issueId/documents/:key` | Create or update issue document (send `baseRevisionId` when updating) | +| GET | `/api/issues/:issueId/documents/:key/revisions` | Document revision history | +| DELETE | `/api/issues/:issueId/documents/:key` | Delete document (board-only) | | GET | `/api/issues/:issueId/approvals` | List approvals linked to issue | -| POST | `/api/issues/:issueId/approvals` | Link approval to issue | +| POST | `/api/issues/:issueId/approvals` | Link approval to issue | | DELETE | `/api/issues/:issueId/approvals/:approvalId` | Unlink approval from issue | ### Companies, Projects, Goals @@ -624,7 +638,11 @@ Terminal states: `done`, `cancelled` | Method | Path | Description | | ------ | ------------------------------------ | ------------------ | | GET | `/api/companies` | List all companies | +| POST | `/api/companies` | Create company | | GET | `/api/companies/:companyId` | Company details | +| PATCH | `/api/companies/:companyId` | Update company (CEO: name/description/brandColor/logoAssetId; board: all fields) | +| POST | `/api/companies/:companyId/logo` | Upload company logo (multipart, field: `file`) — returns `assetId` to set via PATCH | +| POST | `/api/companies/:companyId/archive` | Archive company | | GET | `/api/companies/:companyId/projects` | List projects | | GET | `/api/projects/:projectId` | Project details | | POST | `/api/companies/:companyId/projects` | Create project (optional inline `workspace`) | @@ -639,6 +657,22 @@ Terminal states: `done`, `cancelled` | PATCH | `/api/goals/:goalId` | Update goal | | POST | `/api/companies/:companyId/openclaw/invite-prompt` | Generate OpenClaw invite prompt (CEO/board only) | +### Routines + +| Method | Path | Description | +| ------ | ---- | ----------- | +| GET | `/api/companies/:companyId/routines` | List all routines in company | +| GET | `/api/routines/:routineId` | Routine details including triggers | +| POST | `/api/companies/:companyId/routines` | Create routine (`assigneeAgentId` + `projectId` required; agents: own only) | +| PATCH | `/api/routines/:routineId` | Update routine (agents: own only, cannot reassign) | +| POST | `/api/routines/:routineId/triggers` | Add trigger (`schedule`, `webhook`, or `api` kind) | +| PATCH | `/api/routine-triggers/:triggerId` | Update trigger (e.g. disable, change cron) | +| DELETE | `/api/routine-triggers/:triggerId` | Delete trigger | +| POST | `/api/routine-triggers/:triggerId/rotate-secret` | Rotate webhook signing secret (previous secret immediately invalidated) | +| POST | `/api/routines/:routineId/run` | Manual run (bypasses schedule; concurrency policy still applies) | +| POST | `/api/routine-triggers/public/:publicId/fire` | Fire webhook trigger from external system | +| GET | `/api/routines/:routineId/runs` | Run history (default 50) | + ### Approvals, Costs, Activity, Dashboard | Method | Path | Description | @@ -650,14 +684,39 @@ Terminal states: `done`, `cancelled` | GET | `/api/approvals/:approvalId/issues` | Issues linked to approval | | GET | `/api/approvals/:approvalId/comments` | Approval comments | | POST | `/api/approvals/:approvalId/comments` | Add approval comment | +| POST | `/api/approvals/:approvalId/approve` | Board: approve (with `decisionNote`) | +| POST | `/api/approvals/:approvalId/reject` | Board: reject (with `decisionNote`) | | POST | `/api/approvals/:approvalId/request-revision`| Board asks for revision | | POST | `/api/approvals/:approvalId/resubmit` | Resubmit revised approval | +| POST | `/api/companies/:companyId/cost-events` | Report cost event (adapter-facing) | | GET | `/api/companies/:companyId/costs/summary` | Company cost summary | | GET | `/api/companies/:companyId/costs/by-agent` | Costs by agent | | GET | `/api/companies/:companyId/costs/by-project` | Costs by project | | GET | `/api/companies/:companyId/activity` | Activity log | | GET | `/api/companies/:companyId/dashboard` | Company health summary | +### Secrets + +| Method | Path | Description | +| ------ | ---- | ----------- | +| GET | `/api/companies/:companyId/secrets` | List secrets (metadata only — values never returned) | +| POST | `/api/companies/:companyId/secrets` | Create secret — value encrypted at rest, full value shown once | +| PATCH | `/api/secrets/:secretId` | Update secret value (creates new version; `"version": "latest"` refs auto-update) | + +Reference secrets in agent adapter config instead of inline values: + +```json +{ + "env": { + "ANTHROPIC_API_KEY": { + "type": "secret_ref", + "secretId": "{secretId}", + "version": "latest" + } + } +} +``` + --- ## Common Mistakes From 4abd53c08965acce85209cc307870c75e9eae8a4 Mon Sep 17 00:00:00 2001 From: Aron Prins Date: Thu, 2 Apr 2026 11:00:53 +0200 Subject: [PATCH 4/5] fix(skills): tighten api-reference table descriptions to match existing style Co-Authored-By: Paperclip Co-Authored-By: Claude Sonnet 4.6 --- skills/paperclip/references/api-reference.md | 30 ++++++-------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/skills/paperclip/references/api-reference.md b/skills/paperclip/references/api-reference.md index 77f95d78..7b341927 100644 --- a/skills/paperclip/references/api-reference.md +++ b/skills/paperclip/references/api-reference.md @@ -640,8 +640,8 @@ Terminal states: `done`, `cancelled` | GET | `/api/companies` | List all companies | | POST | `/api/companies` | Create company | | GET | `/api/companies/:companyId` | Company details | -| PATCH | `/api/companies/:companyId` | Update company (CEO: name/description/brandColor/logoAssetId; board: all fields) | -| POST | `/api/companies/:companyId/logo` | Upload company logo (multipart, field: `file`) — returns `assetId` to set via PATCH | +| PATCH | `/api/companies/:companyId` | Update company fields | +| POST | `/api/companies/:companyId/logo` | Upload company logo (multipart) | | POST | `/api/companies/:companyId/archive` | Archive company | | GET | `/api/companies/:companyId/projects` | List projects | | GET | `/api/projects/:projectId` | Project details | @@ -684,11 +684,11 @@ Terminal states: `done`, `cancelled` | GET | `/api/approvals/:approvalId/issues` | Issues linked to approval | | GET | `/api/approvals/:approvalId/comments` | Approval comments | | POST | `/api/approvals/:approvalId/comments` | Add approval comment | -| POST | `/api/approvals/:approvalId/approve` | Board: approve (with `decisionNote`) | -| POST | `/api/approvals/:approvalId/reject` | Board: reject (with `decisionNote`) | +| POST | `/api/approvals/:approvalId/approve` | Approve approval request | +| POST | `/api/approvals/:approvalId/reject` | Reject approval request | | POST | `/api/approvals/:approvalId/request-revision`| Board asks for revision | | POST | `/api/approvals/:approvalId/resubmit` | Resubmit revised approval | -| POST | `/api/companies/:companyId/cost-events` | Report cost event (adapter-facing) | +| POST | `/api/companies/:companyId/cost-events` | Report cost event | | GET | `/api/companies/:companyId/costs/summary` | Company cost summary | | GET | `/api/companies/:companyId/costs/by-agent` | Costs by agent | | GET | `/api/companies/:companyId/costs/by-project` | Costs by project | @@ -699,23 +699,9 @@ Terminal states: `done`, `cancelled` | Method | Path | Description | | ------ | ---- | ----------- | -| GET | `/api/companies/:companyId/secrets` | List secrets (metadata only — values never returned) | -| POST | `/api/companies/:companyId/secrets` | Create secret — value encrypted at rest, full value shown once | -| PATCH | `/api/secrets/:secretId` | Update secret value (creates new version; `"version": "latest"` refs auto-update) | - -Reference secrets in agent adapter config instead of inline values: - -```json -{ - "env": { - "ANTHROPIC_API_KEY": { - "type": "secret_ref", - "secretId": "{secretId}", - "version": "latest" - } - } -} -``` +| GET | `/api/companies/:companyId/secrets` | List secrets (metadata only) | +| POST | `/api/companies/:companyId/secrets` | Create secret | +| PATCH | `/api/secrets/:secretId` | Update secret value (creates new version) | --- From 6524dbe08f305b1342a67fe0db5d1ccdc7276449 Mon Sep 17 00:00:00 2001 From: dotta Date: Thu, 2 Apr 2026 06:28:04 -0500 Subject: [PATCH 5/5] fix(skills): move routines docs into paperclip references Co-Authored-By: Paperclip --- skills/paperclip/SKILL.md | 2 +- .../references/routines.md} | 54 +++++-------------- 2 files changed, 15 insertions(+), 41 deletions(-) rename skills/{paperclip-routines/SKILL.md => paperclip/references/routines.md} (66%) diff --git a/skills/paperclip/SKILL.md b/skills/paperclip/SKILL.md index d495f28f..67ca00b5 100644 --- a/skills/paperclip/SKILL.md +++ b/skills/paperclip/SKILL.md @@ -147,7 +147,7 @@ Routines are recurring tasks. Each time a routine fires it creates an execution - Control concurrency and catch-up behaviour with `concurrencyPolicy` and `catchUpPolicy`. If you are asked to create or manage routines you MUST read: -`skills/paperclip/references/api-reference.md` +`skills/paperclip/references/routines.md` ## Critical Rules diff --git a/skills/paperclip-routines/SKILL.md b/skills/paperclip/references/routines.md similarity index 66% rename from skills/paperclip-routines/SKILL.md rename to skills/paperclip/references/routines.md index 29bbc3df..1d1987fb 100644 --- a/skills/paperclip-routines/SKILL.md +++ b/skills/paperclip/references/routines.md @@ -1,24 +1,14 @@ ---- -name: paperclip-routines -description: > - Create, manage, and trigger Paperclip routines — recurring tasks that fire on - a schedule (cron), webhook, or API call and create an execution issue for the - assigned agent. Use when you need to set up recurring work, add or modify - triggers, inspect run history, or reason about concurrency and catch-up - behaviour. ---- - # Paperclip Routines Routines are recurring tasks. Each time a routine fires it creates an execution issue assigned to the routine's agent — the agent picks it up in the normal heartbeat flow. A routine has: - One assigned agent and one project -- One or more triggers (schedule, webhook, or API) +- One or more triggers (`schedule`, `webhook`, or `api`) - A concurrency policy (what to do when a previous run is still active) - A catch-up policy (what to do with missed scheduled runs) -**Authorization:** Agents can read all routines in their company but can only create/manage routines assigned to themselves. Board operators have full access including reassignment. +**Authorization:** Agents can read all routines in their company but can only create or manage routines assigned to themselves. Board operators have full access, including reassignment. --- @@ -59,8 +49,8 @@ POST /api/companies/{companyId}/routines | `projectId` | yes | | | `goalId` | no | Inherited by run issues | | `parentIssueId` | no | Run issues become children of this issue | -| `priority` | no | `critical` `high` `medium`(default) `low` | -| `status` | no | `active`(default) `paused` `archived` | +| `priority` | no | `critical` `high` `medium` (default) `low` | +| `status` | no | `active` (default) `paused` `archived` | | `concurrencyPolicy` | no | See below | | `catchUpPolicy` | no | See below | @@ -68,7 +58,7 @@ POST /api/companies/{companyId}/routines ## Concurrency Policies -Controls what happens when a trigger fires while the previous run issue is still open/active. +Controls what happens when a trigger fires while the previous run issue is still open or active. | Policy | Behaviour | |--------|-----------| @@ -80,7 +70,7 @@ Controls what happens when a trigger fires while the previous run issue is still ## Catch-Up Policies -Controls what happens with scheduled runs that were missed (e.g. server downtime). +Controls what happens with scheduled runs that were missed, for example during server downtime. | Policy | Behaviour | |--------|-----------| @@ -93,7 +83,7 @@ Controls what happens with scheduled runs that were missed (e.g. server downtime A routine can have multiple triggers of different kinds. -All trigger kinds accept an optional `label` field (max 120 chars) — useful for distinguishing multiple triggers of the same kind on one routine. +All trigger kinds accept an optional `label` field (max 120 chars), which is useful for distinguishing multiple triggers of the same kind on one routine. ``` POST /api/routines/{routineId}/triggers @@ -110,7 +100,7 @@ POST /api/routines/{routineId}/triggers ``` - `cronExpression`: standard 5-field cron syntax -- `timezone`: IANA timezone string (e.g. `UTC`, `America/New_York`) +- `timezone`: IANA timezone string (for example `UTC` or `America/New_York`) - The server computes `nextRunAt` automatically ### Webhook @@ -124,7 +114,7 @@ POST /api/routines/{routineId}/triggers ``` - `signingMode`: `bearer` (default) or `hmac_sha256` -- `replayWindowSec`: 30–86400 (default 300) +- `replayWindowSec`: 30-86400 (default 300) - Response includes the webhook URL (`publicId`-based) and the signing secret - Fire externally: `POST /api/routine-triggers/public/{publicId}/fire` - Bearer: `Authorization: Bearer ` @@ -151,7 +141,7 @@ PATCH /api/routine-triggers/{triggerId} DELETE /api/routine-triggers/{triggerId} ``` -To rotate a webhook secret (old secret is immediately invalidated): +To rotate a webhook secret (the old secret is immediately invalidated): ``` POST /api/routine-triggers/{triggerId}/rotate-secret @@ -189,25 +179,9 @@ PATCH /api/routines/{routineId} ## Reading Routines and Runs ``` -GET /api/companies/{companyId}/routines // list all -GET /api/routines/{routineId} // detail with triggers -GET /api/routines/{routineId}/runs?limit=50 // run history (default 50) +GET /api/companies/{companyId}/routines +GET /api/routines/{routineId} +GET /api/routines/{routineId}/runs?limit=50 ``` ---- - -## Key Endpoints - -| Action | Endpoint | -|--------|----------| -| List routines | `GET /api/companies/{companyId}/routines` | -| Get routine | `GET /api/routines/{routineId}` | -| Create routine | `POST /api/companies/{companyId}/routines` | -| Update routine | `PATCH /api/routines/{routineId}` | -| Add trigger | `POST /api/routines/{routineId}/triggers` | -| Update trigger | `PATCH /api/routine-triggers/{triggerId}` | -| Delete trigger | `DELETE /api/routine-triggers/{triggerId}` | -| Rotate webhook secret | `POST /api/routine-triggers/{triggerId}/rotate-secret` | -| Manual run | `POST /api/routines/{routineId}/run` | -| Fire webhook (external) | `POST /api/routine-triggers/public/{publicId}/fire` | -| List runs | `GET /api/routines/{routineId}/runs` | +Use the generic API endpoint tables in `skills/paperclip/references/api-reference.md` when you need a full cross-domain reference. Use this file when you need routine-specific behaviour, payload shape, or policy details.