Skip to main content
Automatite by GTM S t a c k
Integrations

Webhook vs API: When to Push, When to Pull

Webhook vs API explained for automation builders: push vs pull, a decision table, the hidden cost of polling, and how to make webhooks reliable.

Automatite Team 2026-10-12 10 min
webhooks apis integrations polling

“Webhook vs API” is usually framed as a choice between two technologies. It is not. A webhook is an API call — just one the other system makes to you, instead of one you make to it. The real question is about direction and timing: should your workflow pull data when it decides to, or should the source system push data the moment something happens?

Getting this wrong is expensive in both directions. Poll too often and you burn rate limits and task quotas checking for changes that did not happen. Rely on webhooks naively and you silently lose events when your receiver is down for ten minutes. This guide gives you a decision framework, a reliability checklist for each pattern, and a worked example routing CRM leads.

The one-sentence difference

  • API (pull): your system asks “what changed?” on its own schedule. You control timing, pagination and retries.
  • Webhook (push): the source system tells you “this changed” by sending an HTTP request to a URL you expose. The source controls timing; you control how you receive it.

Everything else — latency, cost, reliability, complexity — follows from who initiates the request.

Webhook vs API: decision table

QuestionPrefer webhookPrefer API polling
How fast must you react?Seconds (lead routing, alerts)Minutes or hours are fine (reports, syncs)
How often does the data change?Rarely or unpredictablyConstantly, and you only need a snapshot
Does the source offer webhooks for this event?Yes, with signatures and retriesNo, or only for some objects
Can you expose a public HTTPS endpoint?YesNo (locked-down network)
Do you need the full current state?Not necessarilyYes — pulling gives you the authoritative view
Do you need to backfill history?Webhooks cannot do thisYes — APIs can page through history
How costly is each check?—Cheap, high rate limits

In practice, most production integrations use both: a webhook for low-latency reaction, and a scheduled API reconciliation to catch anything the webhook missed. More on that below.

The hidden cost of polling

Polling looks simple: every N minutes, call GET /records?updated_since=.... The costs are easy to underestimate.

  1. Wasted calls. If you poll every minute and records change ten times a day, 99% of your calls return nothing. That is 1,440 calls a day per object type, per connected account.
  2. Rate limits. Those wasted calls count against the same API limits your other workflows need. See the dread of rate limits.
  3. Latency floor. A 5-minute poll means a lead can wait up to 5 minutes before anything happens. For speed-to-lead workflows that is the difference between a conversation and a voicemail.
  4. Platform billing. Some automation platforms limit polling frequency by plan. Zapier, for example, lists a 15-minute polling interval on its free plan and 2 minutes on Pro as of October 2026 (Zapier pricing).
  5. Cursor bugs. “Updated since last run” logic breaks on clock skew, records updated mid-page, and timezone mismatches. A safe poller overlaps windows and deduplicates.

Polling is still the right choice when the source has no webhooks, when you need a periodic full snapshot, or when you are behind a firewall. When you have to poll, do it well — see polling when webhooks are not an option.

The hidden cost of webhooks

Webhooks feel free: no wasted calls, near-instant delivery. But you have taken on new responsibilities.

  1. You must be up. If your endpoint returns errors or times out, delivery depends on the sender’s retry policy. Some retry for days with backoff; some retry a handful of times; some never retry.
  2. Ordering is not guaranteed. An updated event can arrive before the created event. Your handler must cope.
  3. Duplicates are normal. Retries mean the same event can arrive twice. Without idempotency you create duplicate records.
  4. Security. A public URL accepts requests from anyone. Without signature verification, anyone who learns the URL can inject fake events.
  5. Payloads may be thin. Many webhooks send only an ID and event type. You still need an API call to fetch the full record.

Making webhooks reliable: the receiver pattern

The pattern that holds up in production is: verify, persist, acknowledge, then process.

app.post('/webhooks/crm', express.raw({ type: 'application/json' }), async (req, res) => {
  // 1. Verify the signature against the raw body
  const expected = crypto.createHmac('sha256', process.env.CRM_WEBHOOK_SECRET).update(req.body).digest('hex');
  const given = req.get('X-Signature') || '';
  if (given.length !== expected.length || !crypto.timingSafeEqual(Buffer.from(given), Buffer.from(expected))) {
    return res.status(401).end();
  }

  const event = JSON.parse(req.body.toString('utf8'));

  // 2. Persist with the event id as a unique key (idempotent insert)
  await db.query('INSERT INTO webhook_events (event_id, payload) VALUES ($1, $2) ON CONFLICT (event_id) DO NOTHING', [
    event.id,
    event,
  ]);

  // 3. Acknowledge fast — before doing any slow work
  res.status(200).end();

  // 4. Process asynchronously from the stored row (queue, worker, or workflow trigger)
  queue.publish('crm.event', { eventId: event.id });
});

Header names and signature formats differ per provider (Stripe, GitHub, HubSpot each have their own), so follow the sender’s docs. The structure stays the same:

  • Verify on the raw body. Parsing JSON and re-serialising changes bytes and breaks HMAC checks.
  • Acknowledge within the sender’s timeout. Slow handlers cause retries, which cause duplicates.
  • Store before you process. If processing fails, you can replay from the stored event instead of hoping the sender retries.
  • Deduplicate on event ID. We explain why this matters everywhere in idempotency: the property that saves you.

Worked example: routing a new CRM lead

Goal: when a new inbound lead lands in the CRM, assign an owner and notify them in Slack within one minute.

Pull-only design: poll the CRM every minute for leads created since the last cursor. Simple, but makes 1,440 calls a day, has up to a minute of latency, and breaks if the cursor logic slips.

Push-only design: subscribe to the CRM’s contact.created webhook. Fast, but if your endpoint is down during a deploy and the CRM gives up retrying, that lead is never routed — and nobody notices.

What we recommend — push with pull reconciliation:

  1. Subscribe to the created webhook. On receipt, verify, store, acknowledge.
  2. Fetch the full record via API (webhook payloads are often partial).
  3. Run routing logic (territory, round-robin, account ownership) and write the owner back via API.
  4. Post the Slack notification, using the event ID as an idempotency key so retries do not double-notify.
  5. Every 15 minutes, run a small reconciliation job via API: “leads created in the last hour with no owner.” Route any it finds and alert, because each one means a webhook was missed.

The reconciliation job is the piece most teams skip. It turns “we think webhooks work” into “we know within 15 minutes when they don’t.” For more on routing logic itself, see lead routing: what changed in 2026.

What most people get wrong

  • Treating webhooks as guaranteed delivery. They are best-effort with retries. Design for loss.
  • Doing slow work inside the webhook handler. Calling three APIs before returning 200 is the most common cause of duplicate events.
  • Polling too frequently “just in case.” If the business can tolerate 15 minutes, poll every 15 minutes. Spend the rate limit on something useful.
  • Skipping signature verification on internal tools. Internal URLs leak into logs, screenshots and browser history.
  • Thinking it is either/or. The best integrations combine both.

How Automatite handles this

Our platform treats both patterns as first-class triggers: webhook triggers with idempotency keys and replay, and scheduled or polling triggers for sources that cannot push. Whichever tool you use, check that it gives you replay of stored events and a way to see failed deliveries — that is where reliability actually lives.

FAQ

Is a webhook an API?

Yes. A webhook is an HTTP request the source system sends to your endpoint when an event happens. It is sometimes called a “reverse API” because the direction is flipped.

Which is faster, a webhook or an API?

Webhooks, for reacting to changes. They deliver events within seconds, while polling is limited by how often you check.

When should I use polling instead of webhooks?

When the source has no webhook for the event you need, when you cannot expose a public endpoint, when you need a periodic full snapshot, or when you need to backfill history.

How do I stop duplicate webhook events?

Store each event with its unique event ID under a unique constraint and skip any ID you have already processed. Acknowledge quickly so the sender does not retry unnecessarily.

Do I still need an API if I use webhooks?

Usually yes. Many webhook payloads contain only an ID, so you fetch the full record via API, and you need API access for reconciliation and backfills.

Stay in the loop

Get workflow automation playbooks, integration recipes, and product updates delivered to your inbox.

No spam. Unsubscribe anytime.

Get workflow automation playbooks delivered weekly

Join GTM and ops teams who get actionable automation playbooks, integration recipes, and product updates every week.