A practical field guide from Automation Ace.
Short answer: to trigger a Claude Code agent via API, create a cloud scheduled task (formerly called a routine) at claude.ai/code/routines with a prompt, repositories, and connectors, add an API trigger, generate its token, and send POST https://api.anthropic.com/v1/claude_code/routines/{id}/fire with Authorization: Bearer <token>, an anthropic-version header, and an optional JSON body {"text": "..."}. The call returns right away with a Claude Code session ID and URL; the agent then works in the cloud on its own.
This feature was in research preview at the time of writing, and Anthropic says request shapes, limits, and token behavior may change. Check the official fire endpoint reference before you build on it.
Short answer
- Create a Claude Code scheduled task with a self-contained prompt.
- Add an API trigger; copy the Fire URL and the token (shown once).
- POST to the Fire URL with the bearer token and
anthropic-version. - Pass run-specific context in
text, and tell the prompt to use it. - Save the returned session URL; open it to watch or continue the run.
- Handle 429s, avoid duplicate calls, and keep the token in a secret store.
What you are triggering
A Claude Code scheduled task is a saved Claude Code configuration: a prompt, one or more GitHub repositories, a cloud environment, and a set of connectors. When it runs, Anthropic starts a full Claude Code session in the cloud that clones your repos, runs commands, uses skills and connectors, and pushes its work to a claude/-prefixed branch. It keeps working with your laptop closed.
A task can have several triggers: a schedule, a GitHub event, and an API endpoint. This guide covers the API trigger. To run the same task on a timer as well, see how to run the same Claude Code agent on a schedule and on demand.
Before you start
- A claude.ai plan that includes Claude Code on the web; Anthropic lists Pro, Max, Ultra, Team, and Enterprise at the time of writing.
- GitHub connected to Claude Code for the repositories the task will use.
- Organization settings: on Team and Enterprise, an Owner can turn scheduled tasks off for everyone, so check if the option is missing.
- A place to store secrets: your CI secrets, alerting tool, or automation platform.
Step 1: Create the task and write a payload-aware prompt
Go to claude.ai/code/routines and create a new task (the button may say New task or New routine). Name it, select the repositories and a cloud environment, choose a model, and remove connectors the task does not need: every included connector can be used during a run, including for writes.
Write the prompt as if for a new teammate who will never be able to ask you a question. Because API calls usually carry context, tell the prompt to look for it:
You are the on-call triage agent for the checkout service.
When this task is started by an API call, the alert details arrive in the
routine-fire-payload block. Investigate the alert described there:
1. Find the failing code path from the stack trace or endpoint named.
2. Check commits merged in the last 48 hours that touch that path.
3. If you find a likely cause, open a draft pull request with a fix and
link the alert ID in the description.
4. If you cannot find a cause, write a short summary of what you checked.
Never merge, deploy, or change production settings.
If the payload is empty, reply "No alert details received" and stop.
For writing agent instructions in general, see how to build your first AI agent.
Step 2: Add an API trigger and copy the token
- In the task's create or edit dialog, click + in the Trigger row and choose API.
- Copy the Fire URL. It contains the task ID, which starts with
trig_. - Click Generate token and copy it immediately. It starts with
sk-ant-oat01-and is shown only once. - Store both in your secret store. The trigger is live as soon as the token exists.
Tokens are managed only in the web UI. Regenerate creates a new token and stops the old one; Delete token removes the API trigger.
Step 3: Send the request
curl -X POST "https://api.anthropic.com/v1/claude_code/routines/$ROUTINE_ID/fire" \
-H "Authorization: Bearer $ROUTINE_TOKEN" \
-H "anthropic-version: 2023-06-01" \
-H "anthropic-beta: experimental-cc-routine-2026-04-01" \
-H "Content-Type: application/json" \
-d '{"text": "Sentry alert SEN-4521 fired in prod. Error rate 4.2% on /checkout since 14:05 UTC."}'
| Part | Value | Notes |
|---|---|---|
| Method and URL | POST https://api.anthropic.com/v1/claude_code/routines/{id}/fire | The ID starts with trig_; the web UI shows the full Fire URL |
Authorization | Bearer sk-ant-oat01-... | A per-task token, not a Claude API key |
anthropic-version | For example 2023-06-01 | Required; the reference says versions from 2023-06-01 on are accepted |
anthropic-beta | experimental-cc-routine-2026-04-01 | The docs show it; the reference says requests work with or without it |
Content-Type | application/json | When you send a body |
| Body | {"text": "..."} | Optional, freeform, up to 65,536 characters |
Step 4: Read the response
200 OK
{
"type": "routine_fire",
"claude_code_session_id": "session_01HJKLMNOPQRSTUVWXYZ",
"claude_code_session_url": "https://claude.ai/code/session_01HJKLMNOPQRSTUVWXYZ"
}
The request returns once the session is created. It does not wait for the agent to finish or stream its output. Save claude_code_session_url wherever the requester will look: a Slack thread, an incident ticket, or a CI log. Opening it shows the run live, the changes, and lets you continue the conversation. Every run also appears under History on the task's page.
If you need the result back in another system, have the prompt deliver it: open a pull request, comment on an issue, or post to Slack through a connector.
Examples in Node, Python, and GitHub Actions
// Node.js 18+ (built-in fetch). Store the URL and token as secrets.
const res = await fetch(process.env.ROUTINE_FIRE_URL, {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.ROUTINE_FIRE_TOKEN}`,
"anthropic-version": "2023-06-01",
"anthropic-beta": "experimental-cc-routine-2026-04-01",
"Content-Type": "application/json",
},
// JSON.stringify escapes quotes and newlines in the alert text for you
body: JSON.stringify({ text: `Alert ${alert.id}: ${alert.title}\n\n${alert.body}`.slice(0, 65000) }),
});
if (res.status === 429) {
const wait = res.headers.get("retry-after"); // seconds until the window resets
// queue the alert and try again later; do not loop immediately
} else if (!res.ok) {
console.error(res.status, await res.text()); // log the error envelope
} else {
const { claude_code_session_url } = await res.json();
console.log("Claude Code session:", claude_code_session_url);
}
# Python 3 with requests
import os, requests
r = requests.post(
os.environ["ROUTINE_FIRE_URL"],
headers={
"Authorization": f"Bearer {os.environ['ROUTINE_FIRE_TOKEN']}",
"anthropic-version": "2023-06-01",
"anthropic-beta": "experimental-cc-routine-2026-04-01",
},
json={"text": "Nightly build failed on main. Log tail:\n" + log_tail[-60000:]},
timeout=30,
)
r.raise_for_status()
print(r.json()["claude_code_session_url"])
# GitHub Actions: start a Claude Code run when CI fails
- name: Ask Claude Code to investigate
if: failure()
env:
ROUTINE_FIRE_URL: ${{ secrets.ROUTINE_FIRE_URL }}
ROUTINE_FIRE_TOKEN: ${{ secrets.ROUTINE_FIRE_TOKEN }}
run: |
curl -sS -X POST "$ROUTINE_FIRE_URL" \
-H "Authorization: Bearer $ROUTINE_FIRE_TOKEN" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d "{\"text\": \"CI failed: $GITHUB_WORKFLOW run $GITHUB_RUN_ID on $GITHUB_REF\"}"
Other callers, such as monitoring tools, deploy scripts, and internal apps, follow the same pattern. For no-code callers, see triggering Claude Code from Zapier, Make, or n8n.
What to put in text (and why the prompt must opt in)
- It is plain text. The endpoint does not parse it. Send JSON and the agent receives it as a literal string, which is fine if the prompt explains the fields.
- It is labeled untrusted. Claude Code wraps the text in a
<routine-fire-payload>block and tells Claude not to follow instructions inside it unless the saved prompt says to. Write the prompt to reference the payload explicitly, as in Step 1. - Keep it focused: the alert ID, the error, a short log tail, a diff, a ticket link. Long logs cost usage and the limit is 65,536 characters.
- No secrets in text. Use the environment's network secrets for API keys the agent needs.
Errors and how to handle them
| Status | Error type | Usual cause | What to do |
|---|---|---|---|
| 400 | invalid_request_error | Missing anthropic-version, text too long, or the task is paused | Fix the header, trim the text, or resume the task |
| 401 | authentication_error | No token, or a token for a different task | Check the secret; regenerate if it was rotated |
| 403 | permission_error | The account or organization lacks access | Check your plan and organization settings |
| 404 | not_found_error | Wrong or deleted task ID | Copy the Fire URL again |
| 429 | rate_limit_error | Hourly fire limit reached | Wait for Retry-After; queue, do not hammer |
| 500 | api_error | Unexpected server error | Retry with backoff, then check History for a duplicate run |
| 503 | overloaded_error | Temporarily overloaded | Retry after a short delay |
Errors use Anthropic's standard error envelope with type and message. For rate limit handling in general, see 429 rate limit errors.
Limits, retries, and duplicates
| Limit | Amount (at the time of writing) | Counted for |
|---|---|---|
| API fires, Run now, and one-off re-runs, combined | 30 per hour | Each scheduled task |
| API fires | 100 per hour | Your account, across all tasks |
| Fire text length | 65,536 characters | Each request |
| Usage | Same subscription usage as interactive sessions | Your claude.ai account |
- No idempotency key: every successful call starts a new session. If your caller retries, you get two runs.
- Deduplicate before you call: keep the alert or event ID and skip repeats; see why a webhook fires twice.
- Batch noisy sources: send one call per incident, not per error, to stay under the hourly limits.
- Make the work safe to repeat: have the prompt check for an existing branch or pull request before opening a new one.
Security checklist
- Store the Fire URL and token as secrets; never commit them or paste them in tickets.
- The token can only start this one task; it cannot read data or reach other tasks. Rotate it if it leaks.
- Runs act as you: commits and pull requests use your GitHub identity, and connector actions use your linked accounts.
- Limit repositories, connectors, and network access to what the task needs.
- Protect important branches with GitHub branch protection or rulesets.
- Runs start in auto mode where available; risky actions may stop for approval, so check History for runs waiting on you.
For a full framework, see permissions, approvals, and audit trails for AI agents, and testing and monitoring agents.
Fire endpoint vs the Claude Platform API
| Claude Code fire endpoint | Claude Platform API (Messages, agents) | |
|---|---|---|
| What it starts | A full Claude Code cloud session with your repos and connectors | A model call or an agent you host or configure |
| Auth | Per-task bearer token from claude.ai | API key from the Claude Console |
| Billing | Your Claude Code subscription usage | Pay-as-you-go API usage |
| Returns | A session ID and URL, immediately | The model's response (or a stream) |
| SDK support | None; plain HTTP | Official SDKs |
| Best for | Coding and repo work started by alerts, CI, or tools | Building your own apps and agents |
Other platforms offer similar “trigger an agent by HTTP” endpoints. For example, OpenAI workspace agents in ChatGPT were documented with a trigger endpoint that queues a run and returns a conversation link. For the general pattern across platforms, see how to trigger an AI agent from an API or webhook and where to build AI agents.
Using ChatGPT instead? See how to trigger a ChatGPT workspace agent via API and how to monitor workspace agent runs.
Frequently asked questions
How do I trigger a Claude Code agent via API?
Create a Claude Code scheduled task (formerly a routine) at claude.ai/code/routines, add an API trigger, generate its token, and POST to https://api.anthropic.com/v1/claude_code/routines/{id}/fire with Authorization: Bearer and an anthropic-version header. An optional JSON body with a text field passes run-specific context.
What does the Claude Code routine fire endpoint return?
A 200 response with type routine_fire, a claude_code_session_id, and a claude_code_session_url. It returns as soon as the session is created and does not wait for the agent to finish.
Do I use a Claude API key to trigger Claude Code routines?
No. You use a per-task bearer token generated in the Claude Code web UI, which starts with sk-ant-oat01- and can only trigger that one task. Runs use your Claude Code subscription usage, not Claude Platform API billing.
How do I pass data to a Claude Code routine?
Send a JSON body with a text field of up to 65,536 characters. The text is freeform and arrives wrapped in a routine-fire-payload block marked as untrusted, so the saved prompt must tell Claude to act on that block.
What are the rate limits for triggering Claude Code via API?
At the time of writing, each task accepts up to 30 fires per hour shared with Run now, and each account can make up to 100 API fires per hour. Over the limit, the endpoint returns 429 with a Retry-After header. There is no idempotency key, so retries create extra runs.
Disclaimer: Claude Code scheduled tasks (formerly routines) and their API are in research preview, and agent platforms, endpoints, limits, and features change quickly; details reflect public documentation and coverage at the time of writing, so confirm current details with each provider before building. Automation Ace is not affiliated with the companies named here. This article may include links to apps, products, or services; some links may be affiliate links, which means Automation Ace may earn a commission at no extra cost to you.