Zapier Catch Raw Hook: verify a Sume webhook signature
Zapier's Catch Raw Hook returns unparsed data plus headers, which a Sume HMAC check needs. Here is what to verify and the size limits to know.

Use Catch Raw Hook if you want to verify a Sume webhook inside Zapier. Sume signs the raw JSON body, and Zapier documents Catch Raw Hook as returning unparsed data together with headers, so it is the trigger the page describes as keeping the bytes and the x-sume-webhook-signature header you need.
Zapier facts are from its help article; Sume facts from Webhooks, both read 2026-09-30.
What does Sume sign?
When signing is configured, Sume computes HMAC SHA 256 over <timestamp>.<raw_body> and sends x-sume-webhook-timestamp and x-sume-webhook-signature: sume-v1=<hex_signature>. During a secret rotation the header carries one entry per live secret, so accept the delivery when any sume-v1= entry matches. Reject a timestamp outside your tolerance; five minutes is the docs' reasonable default.
Why Catch Raw Hook and not Catch Hook?
A parsed body is not the raw body, so re-serialising it can change the bytes and break the HMAC. Zapier's page says Catch Hook parses the request body, while Catch Raw Hook returns it unparsed and includes headers.
| Trigger | Max payload |
|---|---|
| Catch Hook | 10 MB |
| Catch Raw Hook | 2 MB, includes headers |
Do Zapier's size limits matter for Sume?
Job webhooks carry a small public result with artifact URLs. For Format run receipts, Sume's Run webhooks page says a receipt over 1 MiB is not delivered inline: the body has payload: null and a result_url to fetch. 1 MiB is below Zapier's 2 MB raw limit, so an oversized receipt reaches the Zap as that small envelope.
What does a verifier look like?
A Node check, for example in a Code step or your own endpoint. It refuses an empty secret and compares in constant time.
import { createHmac, timingSafeEqual } from "node:crypto";
export function verifySume(rawBody, timestamp, header, secret) {
if (!secret) throw new Error("signing secret is empty");
const age = Math.abs(Date.now() / 1000 - Number(timestamp));
if (!Number.isFinite(age) || age > 300) return false;
const want = createHmac("sha256", secret)
.update(timestamp + "." + rawBody)
.digest("hex");
return header.split(",").some((part) => {
const got = part.trim().replace(/^sume-v1=/, "");
return (
got.length === want.length &&
timingSafeEqual(Buffer.from(got), Buffer.from(want))
);
});
}What if verification fails?
Do not act on the event. Read the job by id from status_url instead, and treat job_id as the idempotency key. For a delayed or missing delivery see Zapier 200 then delayed.
Sources
Related posts
More in Integrations
- Zapier MCP on the Free plan, and Sume's own MCP endpoint
Zapier says MCP is now in its Free, Pro and Team plans. Sume's hosted MCP is a separate server at mcp.sume.com/mcp, reached with OAuth or an API key.
- Zed MCP OAuth scopes: what Sume asks for (mcp:read, mcp:write)
Zed 1.18.0 fixed OAuth for MCP servers with non-default scopes. Sume has two scopes, mcp:read (required) and mcp:write (opt-in on the consent page).
- Claude highlight edit from a long video: Resolve 21.1 vs Sume MCP
Resolve 21.1 lets Claude edit highlights inside Resolve. Sume's hosted MCP can do a cloud version: inspect, trim ranges, join with timeline_create.
- fal MCP "why did my request fail": the Sume job equivalent
fal's Platform MCP lets an assistant debug a failed request. For a failed Sume media job, read jobs_events and the error, then retry by the error rules.
Written by Sume