Guides

How Do I Receive Webhooks From Third-Party Platforms?

How to receive webhooks from third-party platforms: expose an endpoint, verify signatures, ack fast, dedupe, and process asynchronously, plus where it gets hard across many providers and how Paragon handles it.

Garrett Scott
,
Head of Marketing

To receive a webhook from a third-party platform, you register a public HTTPS endpoint with that platform, and it sends an HTTP POST to your URL every time a subscribed event happens. On the receiving end your job is four things: verify the payload is authentic, store it durably and return a 2xx quickly, deduplicate so a retry doesn't double-process, and do the real work on a queue instead of inline. The hard part isn't a single webhook. It shows up when you do this across every app your customers use, each with its own auth, payload shape, and retry behavior.

What is a webhook, and how is it different from polling?

A webhook is a message a third-party platform sends you when something happens, so you don't have to keep asking. Instead of your service calling Salesforce every minute to check for new records (polling), Salesforce calls you the moment a record changes.

Polling burns API quota and adds latency: you find out about a change on your next poll, not when it happens. Webhooks push the event to you in near real time. The cost is that a webhook puts an endpoint on the public internet that has to stay up, verify what it receives, and tolerate duplicates. And not every provider offers webhooks, so polling never fully goes away; you keep it as the fallback for the apps that don't push.

How do I receive a webhook, step by step?

Expose an HTTPS endpoint, subscribe to the events you want, then verify, acknowledge, and process each delivery. Here is the sequence most providers expect:

  1. Expose a public HTTPS endpoint. Something like POST /webhooks/stripe, reachable from the public internet over TLS.

  2. Subscribe to the events. Register your endpoint with the provider, through its dashboard or its subscription API. This step is where providers diverge the most (more on that below).

  3. Verify before you trust anything. Check the signature header against your shared secret, and check the signed timestamp for freshness (see the next section). Do this first, on every request.

  4. Store it durably, then return 2xx. Providers expect an acknowledgment in single-digit seconds; budget for the tightest one (about 1 to 3 seconds) or they treat the delivery as failed and retry. The catch: a 2xx tells the provider "I have this," so only send it once the event is written somewhere durable. Acking before you persist is how events quietly disappear when your process restarts.

  5. Deduplicate with an atomic write. Delivery is at-least-once, so you will see the same event more than once. Make the store write an atomic insert keyed on the provider's event ID; a duplicate hits the unique constraint and becomes a no-op. A read-then-write check is a race under concurrent retries, so let the database enforce it.

  6. Process asynchronously, and don't assume order. A worker reads from the store and does the real work off the request path. Assume events can arrive out of order (a "record updated" can beat its "record created"), so reconcile against the provider's current state or an event version rather than trusting arrival order.

Here is the shape of it in Node and Express:

How do I verify a webhook is authentic?

Verify the signature the provider sends in the request headers against a shared signing secret, and reject anything that doesn't match. Your endpoint is public, so anyone who learns the URL can POST to it; the signature is how you tell a real event from a forged one.

Most providers sign the raw request body with HMAC-SHA256 and put the result in a header (Stripe-Signature, X-Hub-Signature-256, and so on). You recompute the HMAC with your secret and compare. Three things trip people up. Verify against the raw bytes rather than the re-serialized JSON, because parsing and re-encoding changes the bytes and breaks the hash. Use a constant-time comparison so you aren't leaking the secret through timing. And remember that a valid signature proves the payload is authentic, not that it is fresh: an attacker who captures one signed request can replay it later. Providers sign a timestamp alongside the body for exactly this reason, so reject anything outside a short tolerance (Stripe uses five minutes). Two related details worth planning for: some providers make you answer a one-time verification challenge before they start sending events, and you will want a path to rotate the signing secret without downtime.

Why does receiving webhooks get hard across many platforms?

One webhook is a weekend project. Receiving webhooks reliably from every app your customers connect is a system you have to own and keep running. The work piles up in five places:

  • Every provider is different. Stripe signs one way, GitHub another, and Salesforce has no simple webhook at all (you go through Change Data Capture and the Streaming API). Different subscription APIs, payload schemas, retry policies, and timeouts, and those schemas drift as providers version their events.

  • Some don't support webhooks. For those you build and run polling, with its own scheduling, cursors, and rate-limit handling.

  • Auth is per customer. In multi-tenant software you subscribe on behalf of each user, which means storing and refreshing OAuth tokens for every customer and re-subscribing when a token rotates. This is usually the layer that gets ugly fastest. (We wrote about the managed authentication side of this separately.)

  • Events have to route to the right tenant. An incoming payload has to map back to the specific customer it belongs to. Get it wrong and you leak one customer's data into another's account.

  • No silent failures. You need retries with backoff, dead-letter handling for what never delivers, and logs that tell you what fired, what delivered, and what didn't, broken out per provider and per customer.

None of this is exotic. It is very doable for one or two providers. It stops being a side project somewhere around the fifth, and it never stops asking for maintenance the next time a provider changes an API without much warning.

How does Paragon receive third-party webhooks for you?

ActionKit Triggers receives third-party webhooks for you through a single API. You subscribe to the events you care about across hundreds of apps, and every event is delivered to one webhook URL you configure once, verified and tagged with the customer it belongs to. The payoff is roadmap math: provider number ten is the same one API call as provider number one, so reactive features (an agent that acts the moment a ticket is created) ship in days across every app a customer connects, instead of one integration at a time. For engineering, you stop owning per-provider listener code, token refresh, and dedupe infrastructure.

In practice, one API call turns on the triggers you want: Slack message received, Salesforce record updated, GitHub issue opened. Deliveries are signed with a signing secret so you can confirm they came from Paragon, and each one carries a credential ID (in the X-Paragon-Credential header) that tells you which of your users the event belongs to, so tenant routing arrives in the payload instead of being something you reverse-engineer. Failed deliveries retry with exponential backoff, and an endpoint that keeps failing is disabled so it isn't hammered, with the misses visible in the event logs (which you can also forward to your own observability stack). The catalog lists which apps and events are live so you can check coverage before you commit.

Postman uses Triggers to power event handling in their Flow builder, so a Flow can react to a third-party event without Postman maintaining a listener for each app. Crew AI uses them so their agents can act on events across their users' apps. When you need to run logic after an event lands, like fanning out, transforming a payload, or calling another API, Workflows handles that orchestration with durable retries.

The tradeoff, said plainly: if you integrate one provider and never add another, a hand-rolled listener is less machinery to reason about. And because every event routes through Paragon, the fair question a security reviewer will ask is where that data goes; Paragon is SOC 2 Type II, isolates each tenant's data, and can be deployed in your own cloud, so that review has an answer. The Triggers docs have the API shapes and the signature-verification steps if you want to read the mechanics before you decide.

FAQ

Do I need a public endpoint to receive webhooks?
Yes, for direct provider webhooks: the provider has to reach your URL over the public internet. With Paragon you configure one webhook URL and receive every app's events there, so you set the endpoint once instead of per provider.

How do I test webhooks locally?
Give the provider a public URL that points back to your machine. Tools like ngrok or Cloudflare Tunnel expose your local server on a temporary HTTPS URL, and many providers ship a CLI that forwards events to localhost and lets you replay past deliveries while you debug. Because Paragon delivers every app's events to one URL, you point that URL at your tunnel once instead of reconfiguring per provider.

What happens if my endpoint is down when an event fires?
Most providers retry for a while and then give up, so a long outage can lose events. Paragon retries failed deliveries with exponential backoff and disables an endpoint that keeps failing so it isn't hammered; the failed deliveries stay visible in the event logs rather than vanishing silently.

How do I avoid processing the same webhook twice?
Treat delivery as at-least-once and make your handler idempotent. Write each event to durable storage with an atomic insert keyed on the provider's event ID, so a duplicate delivery is a no-op instead of a second round of work.

Are webhook events ordered?
Don't assume so. Across most providers, delivery is at-least-once and not guaranteed to be in order, so an update can arrive before the create it depends on. Reconcile against the provider's current state or an event version rather than trusting the order events land in.

Should I use webhooks or polling?
Use webhooks when the provider supports them; they are near real time and easier on your API quota. Keep polling as the fallback for providers that don't offer webhooks at all.

How many apps support webhooks through Paragon?
Hundreds of apps, with hundreds of event types across them, through one subscription API and one delivery URL. The integration catalog lists what is live.

The short version

The build-versus-own decision isn't the first webhook; it's the second provider, and the fifth, and the maintenance that never makes the roadmap but always makes the on-call rotation. Receiving one webhook well is a known recipe: verify, store, ack, dedupe, process off the request path. Receiving them reliably from every app your customers use, verified and routed to the right tenant, is a standing system someone has to own. If you would rather spend that time on your product, that is what ActionKit Triggers is for.

TABLE OF CONTENTS
    Table of contents will appear here.
Ship native integrations 7x faster with Paragon

Ready to get started?

Join hundreds of SaaS companies that are scaling their integration roadmaps with Paragon

Ready to get started?

Join hundreds of SaaS companies that are scaling their integration roadmaps with Paragon

Ready to get started?

Join hundreds of SaaS companies that are scaling their integration roadmaps with Paragon

Ready to get started?

Join hundreds of SaaS companies that are scaling their integration roadmaps with Paragon