
A Zapier action step has to return within 30 seconds, full stop, and a Claude API call is one of the easiest ways to blow past that window on exactly the requests you care about most — the long ones. Anthropic’s own documentation recommends streaming or the Message Batches API for anything that might run past a few minutes, which means the two systems disagree about what “normal” looks like before you’ve written a single line of your own code. This walks through one concrete Zap that times out, why “optimizing your code” doesn’t fix it, and the one asynchronous pattern Zapier’s documentation actually supports for actions.
The 30-second wall, exactly as Zapier documents it
Zapier’s operating constraints documentation and its dedicated page on action timeouts both give the same number: whatever your perform method does — call an external API, run your own code, parse the response — it has to hand back output within 30 seconds, every single time the step runs live, not just during testing in the Zap editor.
| Where the limit applies | Documented ceiling |
|---|---|
| Zap editor test step | 30 seconds |
| Polling trigger | 30 seconds |
| REST Hook trigger (ingest and payload scripting) | 30 seconds |
| Create or search action | 30 seconds |
Notice that a polling trigger carries the identical 30-second ceiling as an action. Switching your Zap from an action to a trigger-based design doesn’t dodge the limit — it just moves which documentation page describes the same failure.
Why a Claude call is one of the likeliest things to hit it
Anthropic’s own API error documentation tells you to reach for the streaming Messages API or the Message Batches API “for long-running requests, especially those over 10 minutes,” and separately warns against setting a large max_tokens value without one of those two approaches, because idle network connections can get dropped before a plain synchronous call ever finishes. A Zapier action calling the plain Messages API endpoint with a non-trivial prompt and a few thousand output tokens is precisely the shape of request Anthropic is warning you about — it just usually finishes in 15 to 45 seconds instead of 10 minutes, which feels safe until you remember Zapier’s ceiling is 30.
A Zap that works in testing and fails in production
Here’s the pattern that surfaces this almost every time: a new row lands in a spreadsheet, a Code step builds a prompt from that row’s content, a Webhooks by Zapier POST sends it to Claude’s Messages API, and the response gets posted to Slack. Short rows summarize in under ten seconds and the Zap looks completely healthy. Then a longer row comes through — more source text, a bigger prompt, a longer requested summary — and the run shows a timeout error in Zap history with no other explanation.
Zapier’s troubleshooting page suggests optimizing your perform method and cutting back on logging calls inside loops, which is the right advice when your own code is the slow part. It is the wrong advice here. The Code step and the webhook plumbing are not what is slow; the model generating the actual response is, and that time scales with how much text goes in and how much comes out. No amount of trimming your own script shortens Claude’s generation time, so this specific failure needs a structural fix, not a cleanup pass.
The one workaround Zapier’s documentation actually supports
For actions, Zapier’s developer platform documents exactly one way around the 30-second ceiling: webhook callbacks. Instead of your action waiting on the Claude response directly, it hands the job off to a service you control and returns immediately. That service does the actual work — including, if the job is large enough, using Claude’s own streaming or Message Batches API the way Anthropic recommends — and when it finishes, it sends a POST request to a callback URL that Zapier’s platform gives your action for exactly this purpose. Zap history shows the step as Waiting or Delayed until that POST arrives, then resumes the Zap with whatever data you sent back.
Concretely, that means moving the Claude call out of the Zap step entirely. The Zap’s webhook step calls a small endpoint of your own (a serverless function works fine) and passes along the callback URL Zapier provides; your endpoint queues the Claude request, returns a 200 to Zapier right away so the 30-second clock never matters, and POSTs the finished summary back to the callback URL once Claude responds — whether that takes 8 seconds or 90. Our walkthrough on logging Claude API costs to a Google Sheet with a Zapier webhook covers the webhook side of a similar integration, and the broader error-handling habits in scheduling a recurring Claude API call with cron apply just as well once the call lives outside Zapier’s own 30-second clock.
What the callback endpoint actually looks like
The piece most write-ups skip is the endpoint itself, so here is a complete one, trimmed to the parts that matter. It’s a small serverless function — the exact platform doesn’t matter, the shape stays the same on any of them — with two routes: one that Zapier calls immediately, and one Claude’s response triggers later.
// Route 1: Zapier calls this and gets an instant 200
app.post('/start-summary', async (req, res) => {
const { prompt, callback_url } = req.body;
// Hand off the real work and respond before Claude even starts
res.status(200).json({ status: 'queued' });
runClaudeJob(prompt, callback_url); // not awaited — fires in the background
});
// Background job: calls Claude, then reports back to Zapier
async function runClaudeJob(prompt, callback_url) {
const message = await anthropic.messages.create({
model: CLAUDE_MODEL, // your account's current model slug, from docs.claude.com/en/docs/about-claude/models
max_tokens: 2048,
messages: [{ role: 'user', content: prompt }],
});
// Whenever Claude actually finishes — 8 seconds or 90 — post the result back
await fetch(callback_url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ summary: message.content[0].text }),
});
}
- The first route never waits on Claude. It reads the callback URL Zapier’s webhook step hands it, responds
200immediately, and only then starts the Claude call in the background. That response is what keeps the Zap step itself under 30 seconds, regardless of how long the actual generation takes. callback_urlcomes from Zapier, not from your code. When you configure the action’s webhook step to use a callback, Zapier generates this URL per run and passes it in the request body; your endpoint’s only job is to store or forward it, never to construct one itself.- The background function is
asyncbut notawaitedby the route handler. That’s deliberate — awaiting it would just recreate the original timeout one layer down. The route returns, and the function keeps running after the HTTP response has already gone out. - A failed Claude call needs its own POST to the callback URL, with an error field instead of a summary, wrapped in a try/catch around the
runClaudeJobbody. Without it, a failed generation leaves the Zap sitting in Waiting status indefinitely instead of surfacing an error in Zap history.
Other limits worth knowing once the timeout is fixed
Fixing the timeout tends to surface the next constraint, especially once a Zap is handling real volume instead of test rows.
| Limit | Documented value |
|---|---|
| Webhook payload | 10 MB |
| Trigger/action input payload | 6 MB (35 MB on platform version 17.2.0+) |
| HTTP response payload | 20 MB |
| Downloaded files | ~120 MB |
| Polling trigger | 100 new items per poll by default |
| REST Hook trigger | 10,000 webhooks per 5 minutes, 30 per second |
None of these are the bottleneck in the Zap described above, but a team that fixes the timeout by batching several rows into one Claude call, or by having Claude return a larger structured response, can walk straight into the payload limits next. Worth checking the table once volume grows rather than waiting for the next silent failure — the same way a rate limit you didn’t plan for tends to show up only once you’ve actually scaled past testing.
FAQ
Does the 30-second limit cover my own code, or just the API call?
Both, added together. Zapier’s documentation describes the limit as covering everything your perform method does before returning output — your own Code step logic and the external request’s response time both count against the same 30 seconds.
Can I just switch to a polling trigger to get more time?
No. Zapier’s own operating constraints documentation lists the identical 30-second ceiling for polling triggers, so restructuring the Zap around a trigger instead of an action doesn’t change the actual limit you’re running into — it only changes which page of the documentation you’ll eventually find describing the same number.
Does Anthropic’s streaming API avoid the timeout by itself, without a callback endpoint?
Not inside a plain Zapier action. Streaming changes how the response arrives at whatever client requested it, but a Zapier action step still has to finish its own perform call and hand back output within the same 30 seconds; the callback endpoint is what lets something other than Zapier wait out the full generation, streamed or not.
If this Zap is also one of several places your team calls Claude, it’s worth comparing notes against the common mistakes in an AI email-triage workflow built on the Gmail API — a different trigger, the same category of “it worked in testing” failure once real traffic arrives.



