← All articles
Dev Jain

Corsair vs Zapier: How to Verify and Route Webhooks Before an AI Agent Acts

create a short excerpt Before an AI agent acts on a webhook, two things have to be true: the event is really from the provider, and it belongs to the right customer. This post walks the full chain of checks and compares how Corsair and Zapier handle each.

Before an AI agent acts on a webhook, you need two answers: is this event really from the provider, and does it belong to the customer whose data the agent is about to touch? Getting either wrong turns a single bad request into a real write against the wrong record or the wrong account. This guide walks through the full chain of checks: webhook signature verification, payload validation, event filtering, and multi tenant webhook routing. Along the way it compares how Corsair and Zapier handle each step. Corsair establishes trust inside your own application before any action runs, while Zapier typically establishes it with workflow steps after the trigger has already fired.

Verifying and Routing Webhooks Before They Trigger AI Actions

verify the signature, check freshness, validate the payload, filter out events that do not matter, and route the event to the right customer, all before the agent takes any action. Each check answers a different question, and skipping one leaves a gap the others cannot cover.

Order matters because an AI agent turns an event into action. A fixed workflow runs the same steps every time. An agent reasons over the event, then picks which tools to call and which arguments to send. If a forged or misrouted event gets through, the cost is not a stray log line: it can be an overwritten CRM record, a wrong payment update, or a message sent to the wrong customer. That is what makes AI agent webhook security different from ordinary webhook handling.

Here are the five questions to settle, in order:

  1. Authenticity: Did the provider really send this?
  2. Freshness and uniqueness: Is it recent, and have we already processed it?
  3. Validity: Do the fields and values make sense?
  4. Relevance: Is this an event type the agent should act on?
  5. Ownership: Which customer does it belong to?

How to Tell an Incoming Event Is Trustworthy Before an AI Agent Acts

An event is trustworthy when its signature verifies against the raw request body using the correct secret, its timestamp sits inside the tolerance window, and its event ID has not been seen before. Providers differ on the details, which is exactly why verification is easy to get wrong.

Stripe sends a single Stripe-Signature header. It carries a timestamp and a signature computed with HMAC SHA256 over the timestamp, a dot, and the raw body, using your endpoint's signing secret. HubSpot's v3 scheme uses an X-HubSpot-Signature-v3 header plus an X-HubSpot-Request-Timestamp header. The signature covers the HTTP method, the URI, the body, and the timestamp, and it is Base64 encoded. Both providers recommend rejecting requests whose timestamps are older than about five minutes.

The most common reasons verification fails:

  • Parsed body: Body parsing middleware changes spacing or key order before you hash it. Verify against the raw body, then parse.
  • Wrong secret: The endpoint signing secret is not the API key, and secrets from a test setup or CLI forwarding differ from dashboard managed endpoints.
  • Encoding mismatch: Stripe and HubSpot v3 encode their digests differently, so a comparison against the wrong format never matches.
  • URI mismatch: For HubSpot, a proxy that changes the scheme or an unhandled URL encoding step produces a different string than the one HubSpot signed.
  • Clock drift: A server clock that is out of sync pushes valid requests outside the tolerance window.

Two more habits matter. Compare signatures with a timing safe function, not a plain equality check. And remember that a valid signature does not stop a replay inside the tolerance window, so pair it with event ID tracking, covered later in this guide.

Corsair vs Zapier: Is This Webhook Real, and Does It Belong to This Customer?

In Corsair, both answers are built into how webhooks arrive. Signature verification is handled inside each plugin, so you are not writing HMAC code per provider or tracking which header and encoding each service uses. For ownership, you register your single webhook endpoint with the provider and include the customer's stable ID in the callback URL, such as https://your-app.com/api/webhook?tenantId=user_abc123. Corsair reads that tenantId and scopes everything that follows to that customer. The webhooks concept page in the Corsair docs covers the setup.

Zapier's Catch Hook trigger works differently. Each Zap gets its own unique URL, and third party guides point out that anyone who holds that URL can trigger the Zap. In the Zapier sources we reviewed, no built in signature verification for Catch Hook is described. The common workaround is adding a secret to the URL query string and checking it in a Filter step right after the trigger.

The difference is what each approach proves:

  • Corsair: The plugin checks a cryptographic signature tied to the request body, so the check fails if the payload was altered.
  • Shared URL secret: It shows the sender knew the secret, but the secret is not bound to the body, and it travels inside a URL that can appear in logs.

Signature Checks, Payload Validation, and Customer Routing for AI Agent Events

These three layers answer separate questions, and a verified event can still be wrong for the agent. A valid signature proves who sent the request. It says nothing about whether the values make sense or whether the target record belongs to the right customer.

Payload validation covers what a signature cannot:

  • Required fields and allowed values: A CRM status of almost_active is well formed but not an allowed value when your system accepts only prospect, active, or paused.
  • Event type: Confirm the event is one your agent is meant to act on before it reaches the agent.
  • Object matching: A record ID that exists is not enough. It has to match the customer in context, so an event for crm_2087 never updates a record during a session for the customer who owns crm_1042.
  • Business rules: A status change to active might require finished onboarding and billing setup first.

Corsair puts this logic in before hooks, which run before an operation executes. They receive the arguments being submitted and expose database clients, so you can look up application state. Throwing an error inside the hook stops the operation before any external API write happens. These hooks guard the operation the agent is about to run, which makes them the last gate after a webhook has been verified. For a closer look at this layer, see our post on validating AI agent inputs before they reach your APIs.

Customer routing is the third layer, and the next section explains how each platform handles it.

Corsair vs Zapier: Where Trust Gets Established When a Webhook Reaches an AI Agent

Corsair establishes trust inside your application, before any action runs. A trigger based workflow typically establishes it after the event has already fired the workflow. Everything else about the two designs follows from that difference.

With Corsair, the chain looks like this:

  1. The plugin verifies the signature.
  2. The tenantId in the callback URL identifies the customer.
  3. A before hook can reject the operation.
  4. Writes land in a tenant scoped database.

For multi tenant webhook routing, the scoping is enforced in code. With multiTenancy: true, every call must go through withTenant(), and forgetting it is a TypeScript compile error. The database adapter adds tenant_id to every insert and filters every read by it. Credentials are encrypted per tenant with a key you control through kek. This keeps one customer's event from landing in another customer's data, and it is the same isolation model we cover in multi tenant OAuth for AI agents.

Zapier does its trust and routing work downstream of the trigger. The trigger fires on receipt, then Filter, Search, and Paths steps decide what happens. To route to a customer, a Zap looks up a record using an identifier from the payload, such as an email or account ID, then branches on whether the record was found. A Zapier connection also belongs to the account that authorized it, so serving many customers means building the lookup logic into the workflow itself.

That model works well when the audience for the event is your own team and the volume of customers is small. The tradeoff is that isolation depends on how carefully the workflow is built, not on rules your code and type system enforce.

Corsair vs Zapier: Filtering Out Irrelevant Webhook Events Before They Reach Your AI Agent

Filter by event type, by customer relevance, and by duplicates, and only then hand the event to the agent. Every irrelevant event that reaches an agent costs reasoning time and creates another chance for a wrong action.

With Corsair, filtering is ordinary TypeScript in your handler and in before hooks, so you decide exactly which event types ever reach the agent. Three habits keep it reliable:

  • Skip event types the agent does not handle instead of passing everything through.
  • Deduplicate by event ID: Store each ID with a unique constraint, and if the insert fails, skip the action and return success.
  • Acknowledge fast: Verify the signature, queue the work, and return a 2xx quickly, because agent reasoning can outlast a provider's response timeout and trigger a retry.

Zapier handles this with the Filter step. You set rules on payload fields with AND or OR logic, and if the data fails, the Zap stops and later steps do not run. Paths can then branch the events that pass. Halted runs are not billed as tasks, which makes filters a cheap way to cut noise in internal automations.

The practical difference is where the line sits. In Zapier, filtering happens after the trigger has already accepted the request. In Corsair, it happens in your code, before the agent step ever begins.

If you want AI agents to act on webhooks only when the event is genuine, relevant, and tied to the right customer, Corsair gives you the pieces in one open source TypeScript layer. Plugins handle signature verification, withTenant() keeps every customer's data and credentials separate, and before hooks let you reject any operation that fails your own rules. You can self host the SDK for free and add the optional hosted relay for OAuth when you need it. Start with one plugin and a single tenant, then watch how an event flows from verification to a scoped database write.

FAQs

What is the difference between verifying and validating a webhook?
Verifying proves the request came from the provider and was not altered, usually with an HMAC signature. Validating checks that the content makes sense: required fields, allowed values, and a record that belongs to the right customer. You need both before an agent acts.

Why does webhook signature verification keep failing?
The usual causes are verifying a parsed body instead of the raw one, using the wrong secret, comparing digests in the wrong encoding, or letting clock drift push the timestamp outside the tolerance window. For HubSpot, a changed URI behind a proxy is another common cause.

How should a multi tenant app route webhooks to the right customer?
Carry the customer's identity with the event, for example in a per customer callback URL, then scope every read and write to that tenant. Enforcing that scoping in code and in the database is safer than relying on a lookup step inside a workflow.

Does Zapier verify webhook signatures on Catch Hook triggers?
In the sources we reviewed, no built in signature verification is described for Catch Hook. The usual approach is a shared secret in the URL checked by a Filter step, which is weaker than a signature tied to the request body.

How do I stop an AI agent from running the same action twice?
Store each event's unique ID and skip any event you have already processed. Acknowledge the webhook quickly, then run the agent step from a queue, so provider retries do not start a second run.