SpedySpedy Docs

Claude Routines

Integration layer to trigger your Anthropic Claude Routines directly from a Spedy ticket — with ticket-context variables, optional board/repo scope, pre- and post-actions, and results posted back into the ticket.

Claude Routines are an Anthropic product: reusable work instructions you define in your Anthropic account and Claude executes for you. Spedy doesn't host or run the routines — Spedy provides the integration layer so you can trigger one of your routines directly from a ticket.

Concretely, this integration:

  • resolves ticket context (title, description, status, board, URL) into your prompt template,
  • POSTs the resolved prompt to your Anthropic routine webhook with your secret,
  • runs optional pre- and post-steps on the ticket (status change, self-assign, PR-link comment),
  • tracks each execution and surfaces its status on the ticket.

The routines themselves, the model usage, and the cost remain in your Anthropic account.

The Spedy integration is part of the Pro plan and must be enabled at the organization level via the CLAUDE_ROUTINES feature flag.

Concepts

In Spedy, a routine entry has four layers:

  1. Metadata — name, slug, description
  2. Scope — optional board and repository scope
  3. Instructions — the prompt template (supports variables like {{ticket.title}})
  4. Pre- and post-actions — server-side ticket steps that run before/after the hand-off to Claude

Every trigger creates a RoutineExecution that tracks the status of the hand-off, the resolved prompt, and completion metadata. The actual AI work happens on Anthropic — RoutineExecution is only Spedy's view of it.

Permissions and Feature Flag

Routines are gated by:

GateValueScope
Organization feature flagCLAUDE_ROUTINESAll /routines/* endpoints and UI require this to be enabled
Permission routines:manageDefault for Admin + Team MemberCreate/read/update/delete your own routines
Permission routines:triggerDefault for Admin + Team MemberTrigger and cancel executions on tickets you can access

Customers (organization role CUSTOMER) are explicitly excluded from both permissions.

Board-level access is also enforced: triggering a routine on a ticket whose board you cannot access returns 403 Forbidden.

Prompt Variables

Inside instructions, the following {{variable}} placeholders are resolved at trigger time:

VariableSource
{{ticket.id}}Ticket ID
{{ticket.displayId}}Human-readable ticket key (e.g. WEB-42)
{{ticket.title}}Ticket title
{{ticket.description}}Ticket description
{{ticket.status}}Status name
{{ticket.statusKey}}Status key (BACKLOGDONE)
{{ticket.boardId}}Board ID
{{ticket.boardName}}Board name
{{ticket.boardSlug}}Board prefix
{{ticket.url}}Relative URL to the ticket

If the trigger request includes an optional text field, it is appended to the resolved prompt under a --- separator as Additional instructions for this run:.

Pre- and Post-Actions

Three server-side action types are supported in preActions and postActions:

TypeParamsWhen it runsEffect
move_statusstatusKey: BACKLOG | TODO | IN_PROGRESS | BLOCKED | DONEpre / postTransitions the ticket to the matching board status
assign_selfpre / postAssigns the triggering user as the ticket assignee
post_pr_commentpostPosts the returned PR link as an internal comment on the ticket

Actions execute in order. Pre-actions run synchronously before Claude is notified; post-actions run when Claude reports completion.

Scoping

Two fields narrow where a routine may run:

  • boardIds — if non-empty, the routine is only offered on tickets whose board is in this list. A trigger against a board outside the list returns 400.
  • allowedRepos — a list of owner/repo strings. Only repositories that are linked to the ticket's board and appear in this list are passed to Claude as repo context. An empty list means "no repo constraint".

Use the GET /routines/available-repos helper to discover valid allowedRepos values for your organization.

Outgoing Webhook

To hand off the work to Anthropic's Claude Code Routines endpoint, each routine can set:

FieldDescription
webhookTargetUrlHTTPS URL on api.anthropic.com. On trigger, Spedy POSTs { "text": resolvedPrompt } to this URL.
webhookTargetSecretSent as Authorization: Bearer <secret>. Never returned in list/read responses (only the boolean flag webhookTargetSecretSet).
webhookTargetHeadersAdditional non-secret headers merged into the outgoing request (e.g. {"anthropic-version": "2023-06-01"}). Spedy supplies sensible defaults for api.anthropic.com if you don't.

On a successful hand-off the execution flips from PENDING to CLAIMED (with claimedAt set), and the ticket card shows Handed off to Claude.

API Reference

All endpoints are mounted under /api/v1/routines, protected by JwtAuthGuard, and support Personal Access Tokens.

GET /routines/me

List the current user's routines.

Permission: routines:manage

Query params

NameTypeDescription
boardIdstringOptional. Returns routines that are either unscoped or explicitly include this board

Response 200 — an array of routines. Secret fields (webhookTargetSecret) are stripped; webhookTargetSecretSet indicates whether one is stored.

POST /routines/me

Create a routine for the current user.

Permission: routines:manage

Request body

FieldTypeRequiredNotes
namestringyes2–120 chars
slugstringyes2–120 chars, lowercase kebab-case, unique per user
descriptionstringno≤ 500 chars
boardIdsstring[]noUp to 100 board IDs. Empty = all boards
instructionsstringyes10–20000 chars. Supports {{ticket.*}} variables
preActionsRoutineAction[]noSee pre/post-actions above
postActionsRoutineAction[]noSame shape as pre-actions
expectPrLinkbooleannoDefault true. Whether post-actions expect a PR link to post
isActivebooleannoDefault true
allowedReposstring[]noUp to 50 owner/repo strings
webhookTargetUrlstring | nullnoMust be an https://api.anthropic.com/… URL
webhookTargetSecretstring | nullnoStored; never returned
webhookTargetHeadersobjectnoMap of string → string

Response 201 — the created routine (secret stripped).

GET /routines/me/:id

Read a single routine owned by the current user.

Permission: routines:manage

PATCH /routines/me/:id

Update a routine. Only the fields present in the body are changed. Passing webhookTargetSecret: "" clears the secret; omitting it leaves it untouched.

Permission: routines:manage

DELETE /routines/me/:id

Soft-delete a routine (marks deletedAt, sets isActive=false).

Permission: routines:manage

Response: 204 No Content

GET /routines/available-repos

Return distinct repoFullName values across all boards in the current organization — the allowed inputs for allowedRepos.

Permission: routines:manage

POST /routines/executions

Trigger a routine on a specific ticket.

Permission: routines:trigger

Request body

FieldTypeRequiredNotes
routineIdstringyesA routine owned by the caller, isActive = true
ticketIdstringyesA ticket on a board the caller can access
textstringno≤ 4000 chars. Appended to the resolved prompt for this single run

Behavior

  1. Asserts CLAUDE_ROUTINES is enabled and the caller can access the ticket's board.
  2. If the routine has boardIds set, rejects tickets from other boards with 400.
  3. Interpolates {{ticket.*}} variables and appends the repo context + optional text.
  4. Runs any preActions server-side.
  5. Creates a RoutineExecution with status PENDING.
  6. If webhookTargetUrl is set, fires the outgoing webhook (fire-and-forget) and flips the execution to CLAIMED on success.

Response 201 — the RoutineExecution row.

GET /routines/executions?ticketId=…

List the last 20 executions for a given ticket (any user in the org who has board access).

Permission: routines:trigger

Response 200 — executions sorted by enqueuedAt descending, each including routine and triggeredBy summaries.

POST /routines/executions/:id/cancel

Cancel one of your own PENDING or CLAIMED executions. Sets status to CANCELLED and completedAt.

Permission: routines:trigger

Errors

CodeReason
403Caller is not the user who triggered the execution
400Execution is not in PENDING or CLAIMED status

Using Routines from the UI

  • Manage routines: Account → Claude Routines. Create, edit, delete, and walk through the 4-step setup wizard.
  • Run a routine: open any ticket on a board you belong to. The Claude Routines card offers every routine that is either unscoped or scoped to this board. Pick one, optionally add extra instructions, and click Trigger.
  • See history: the card lists the most recent executions for this ticket, with status and a Cancel button for your own runs.