Skip to content

Integrations & data

CRM API and webhooks: connect your CRM to anything

REST APIs vs webhooks explained, common CRM integration use cases, how to keep API keys safe, verify HMAC signatures, and handle retries and idempotency.

The Exa teamUpdated 7 min read
Developer connecting a CRM to other business systems at a dual-monitor desk

Key takeaways

  • Use the API when your system needs to ask the CRM something or send it data; use webhooks when you want the CRM to tell your system something happened.
  • Treat API keys like passwords: scope them narrowly, keep them out of URLs and code repositories, and rotate them when people leave.
  • Verify every webhook's HMAC signature against the raw request body before you trust it.
  • Webhooks get retried, so make your receiver idempotent and process each event only once.
  • Respond to webhooks quickly and do slow work in the background, so a timeout doesn't trigger unnecessary retries.

Sooner or later, your CRM needs to talk to something else: a landing page builder, a lead marketplace, a data warehouse, a job-scheduling app, a Slack channel. Built-in integrations cover the common cases. For everything else there’s the API and webhooks.

This guide explains the difference between the two, the most common use cases for small teams, how to keep API keys safe, how to verify webhook signatures (with a short code example), and how to handle retries without creating duplicate records.

REST API vs webhooks

Both move data between systems over HTTPS. The difference is who starts the conversation.

Aspect REST API Webhooks
Who starts it Your system calls the CRM The CRM calls your system
When Whenever your code decides When an event happens in the CRM
Typical use Create a lead, look up a contact, update a deal Notify another system about a new lead, won deal or paid invoice
Authentication API key (or token) sent by your system Signature from the CRM, checked by your system
What you build A script or integration that sends requests An endpoint (a URL) that receives requests

A handy rule: use the API to ask or tell; use webhooks to be told. If you’re checking the CRM every five minutes for new leads, you probably want a webhook instead.

Common use cases

Sending leads in

  • Landing pages and site builders that can’t embed your CRM’s form can post submissions to a lead API.
  • Lead marketplaces and partners (home-services directories, referral partners, a realtor’s portal) can push leads straight in instead of emailing them.
  • Phone systems or chat tools can create leads after a conversation.

Pass the source along with the lead, including UTM parameters if you have them, so reporting stays accurate. Our guide to lead source tracking explains why.

Sending events out

  • Notify the team in a chat channel when a high-value deal is won.
  • Kick off fulfillment in a scheduling or project tool when a quote is accepted.
  • Sync to a data warehouse or spreadsheet for custom reporting.
  • Trigger work in other tools when an invoice is paid or a lead changes stage.

Many of these can start from an automation in your CRM, using a “call webhook” step. Our guide to sales automation covers how triggers, conditions and actions fit together.

Keep API keys safe

An API key is a password for a machine. Anyone who has it can act as your integration. OWASP’s REST Security Cheat Sheet sets out some sensible rules:

  • HTTPS only. OWASP says secure REST services “must only provide HTTPS endpoints”, because that protects credentials such as API keys in transit.
  • Keep keys out of URLs. OWASP specifically warns that API keys “should not appear in the URL”, because URLs end up in logs and browser history. Send them in a header instead.
  • Don’t rely on keys alone for high-value resources, and revoke keys that are misused.

Add a few practical habits:

  1. One key per integration. If the landing page builder is compromised, you revoke one key, not everything.
  2. Least privilege. A key that only creates leads shouldn’t be able to export your whole customer list. Use scoped keys where available. See CRM roles and permissions for the same principle applied to people.
  3. Store keys server-side in environment variables or a secrets manager. Never put them in browser JavaScript, mobile app code or a public code repository.
  4. Rotate on departures. When a contractor or employee who had access leaves, issue new keys.
  5. Watch the logs. An audit log of what each key did makes it easy to spot something odd.

Verify webhook signatures

Your webhook endpoint is a public URL. Anyone who finds it can send it requests. Signatures let you confirm a request really came from your CRM and wasn’t altered.

The standard approach is an HMAC, defined in RFC 2104 back in 1997 as a way to authenticate messages using a cryptographic hash function and a shared secret key. The sender computes an HMAC-SHA256 of the request body using a secret only you and the sender know, and puts the result in a header. Your endpoint computes the same HMAC and compares.

Here’s a minimal example in Node.js. The header name, encoding and exact signed content vary by sender, so check the sender’s documentation and adjust.

import crypto from 'node:crypto';

// rawBody: the exact bytes received (a Buffer), before any JSON parsing
// signature: the value from the signature header, e.g. a hex string
function isValidSignature(rawBody, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex');

  const a = Buffer.from(expected, 'hex');
  const b = Buffer.from(signature ?? '', 'hex');
  // Lengths must match before a constant-time comparison
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

Four details matter:

  • Use the raw body. If your framework parses and re-serializes the JSON first, the bytes change and the signature won’t match.
  • Compare in constant time. A plain === comparison can leak timing information; timingSafeEqual doesn’t.
  • Keep the secret secret. Store it like an API key. If it leaks, rotate it.
  • Reject failures quietly. Return an error status and log it, but don’t process the payload.

If the sender includes a timestamp, also reject requests that are too old, which limits replay attacks.

Retries and idempotency

Networks fail. Your server restarts during a deploy. A webhook times out. Good webhook senders handle this by retrying with backoff: trying again after a short wait, then a longer one. That’s what you want, but it means your endpoint will sometimes receive the same event more than once.

The fix is idempotency: processing the same event twice has the same effect as processing it once. HTTP’s own specification, RFC 9110, defines an idempotent request as one where the effect of “multiple identical requests” is “the same as the effect for a single such request”. It also says clients shouldn’t automatically retry non-idempotent requests unless they have a way to know it’s safe. Webhook receivers flip that around: you make your handling safe to repeat.

How to make a receiver idempotent:

  1. Record what you’ve processed. Store the event’s unique ID if the payload has one, or a hash of the payload if it doesn’t.
  2. Check before acting. If you’ve seen the event before, return success and do nothing.
  3. Use upserts. “Create or update the record with this ID” is naturally safe to repeat; “create a new record” isn’t.
  4. Respond fast. Return a success status as soon as the request is verified and stored, then do slow work (sending emails, calling other APIs) in a background job. Slow responses cause timeouts, and timeouts cause retries.
  5. Watch delivery logs. If you see repeated failures, fix the endpoint; the sender will usually let you see what failed and why.

The same thinking applies when you call a CRM API. If your script creates a lead and the connection drops before you get a response, retrying might create a duplicate. Look the lead up by email or phone first, or rely on the CRM’s duplicate detection.

A simple rollout checklist

Before you rely on an integration:

  1. Create a dedicated API key or webhook secret, scoped as narrowly as possible.
  2. Build against test data first.
  3. Verify signatures and log failures.
  4. Make the receiver idempotent and fast.
  5. Test failure: turn your endpoint off, confirm retries arrive later, and confirm nothing is duplicated.
  6. Document what the integration does, who owns it and where the keys live.

How Exa helps

Exa has a REST API and a server-to-server lead API that uses scoped API keys, stored hashed. Outgoing webhooks for CRM events are signed with HMAC-SHA256, and Exa retries failed deliveries automatically with backoff and keeps delivery logs so you can see what was sent and what failed. Webhook secrets and integration credentials are encrypted at rest, and an audit log records creates, updates and deletes.

Webhooks can also be called from automations, so you can send an event to another system only when your conditions match, for example when a deal over a certain value is won. Quote, invoice and payment events are available too, which covers most fulfillment and finance hand-offs.

Final thoughts

An API and webhooks turn your CRM from a closed box into the hub of your tools. Use the API to send data in, webhooks to be notified when things happen, and treat keys and secrets with the same care as passwords. Verify every signature, make receivers idempotent, respond quickly and watch the delivery logs. Get those basics right and your integrations will keep working quietly in the background.

Try it with your own leads

Exa puts leads, pipeline, inbox and an AI assistant in one simple app.

Start free trial

Sources

  1. IETF — RFC 2104: HMAC: Keyed-Hashing for Message Authentication (1997)
  2. OWASP Cheat Sheet Series — REST Security Cheat Sheet
  3. IETF — RFC 9110: HTTP Semantics (2022)

FAQ

Frequently asked questions

Short answers to the questions we hear most about this topic.

Still have questions?

Start a free trial and see Exa with your own leads and pipeline, or email our team.

What is the difference between an API and a webhook?

With an API, your system makes a request to the CRM when it wants something. With a webhook, the CRM sends a request to your system when something happens, such as a new lead or a won deal.

Do I need a developer to use a CRM API?

For custom integrations, usually yes, or someone comfortable with scripts or an integration platform. Many common jobs, like sending leads from a landing page, take only a short script.

What is an HMAC signature?

It is a code the sender calculates from the message and a shared secret. The receiver recalculates it with the same secret, and if the two match, the message is genuine and wasn't changed in transit.

Why do I receive the same webhook twice?

Senders retry when they don't get a timely success response, so a slow or failed reply can lead to duplicates. Store event identifiers or a hash of the payload and skip anything you've already processed.

How should I store API keys?

In a secrets manager or environment variables on the server, never in front-end code, URLs or a shared spreadsheet. Give each integration its own key with only the permissions it needs.

Can webhooks replace polling the API?

Mostly, yes. Webhooks tell you about changes as they happen. A periodic API check can still be useful as a safety net to catch anything missed during an outage.

Close more deals with less busywork

Set up your workspace in minutes, import your leads from a CSV and let Exa handle the follow-up.