Your Zapier Step Keeps Timing Out on Claude API Calls: The Documented 30-Second Limit and the One Workaround That’s Actually Supported

An hourglass filled with sand, representing a timeout
An hourglass filled with sand, representing a timeout
Photo: John Morgan, licensed CC BY 2.0, via Wikimedia Commons.

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 appliesDocumented ceiling
Zap editor test step30 seconds
Polling trigger30 seconds
REST Hook trigger (ingest and payload scripting)30 seconds
Create or search action30 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 200 immediately, 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_url comes 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 async but not awaited by 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 runClaudeJob body. 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.

LimitDocumented value
Webhook payload10 MB
Trigger/action input payload6 MB (35 MB on platform version 17.2.0+)
HTTP response payload20 MB
Downloaded files~120 MB
Polling trigger100 new items per poll by default
REST Hook trigger10,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.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top