By industry

WhatsApp API for CRM: the conversation inside the lead record

A WhatsApp API for CRM connects the number of each customer of your CRM and delivers conversations to your system via webhook, so they show up on the lead record. The rep replies from inside the CRM and the manager sees the full history, with no screenshots and no copy and paste.

By D-API engineering team6 min read

What your CRM users are already asking for

In many markets, a large share of consultative selling happens on WhatsApp. If the CRM doesn't show those conversations, the recorded pipeline is fiction: the lead moved forward, went cold or closed in a conversation nobody but the rep ever saw. When the rep leaves the company, the history leaves with their phone.

That is why WhatsApp became a checklist item in CRM evaluations. These are the four features that come up in almost every sales conversation about your product:

  • Inbox inside the CRM: a conversations screen where the rep reads and replies without switching apps.
  • History on the lead record: every message sent or received sits on the contact timeline, next to calls, emails and stage changes.
  • Multiple reps and multiple numbers: one number shared by the team or one number per rep, with the manager seeing everything.
  • Synced contacts: anyone who messages for the first time becomes a lead automatically, with name and phone already filled in.

How the architecture fits into your CRM

The WhatsApp API handles the connection to WhatsApp. The CRM handles what it already owns: accounts, users, permissions and the pipeline. The boundary between the two is simple:

  • Each CRM customer (each account) has one or more connections. A connection is a WhatsApp number, identified by a sessionId you choose.
  • An incoming message becomes an event. D-API calls the CRM webhook with the messages.received event, which carries the sessionId, the sender and the content.
  • A rep's reply becomes a request. When someone replies in the inbox, the CRM calls the send route with that account's sessionId.

On D-API, each connection runs in an isolated environment, with its own credentials, webhook and IP. If one customer's number drops or gets blocked, the other CRM customers keep working. In a CRM, that is the kind of incident that turns into a ticket from every customer at once when the infrastructure is shared.

Example: provision the connection when the customer turns on WhatsApp

The right moment to create the connection is when the account admin clicks "Connect WhatsApp" in the CRM settings. With the Node SDK, provisioning and showing the QR code look like this:

import { DApi } from 'd-api-sdk'

const dapi = new DApi({ apiKey: process.env.DAPI_API_KEY })

export async function connectWhatsapp(accountId, userId) {
  const sessionId = 'crm-' + accountId + '-' + userId

  await dapi.sessions.create({
    sessionId,
    connectionMode: 'qr',
    webhookUrl: 'https://app.yourcrm.com/webhooks/whatsapp',
    metadata: { accountId, userId, plan: 'pro' },
  })

  const { qrCodeImage } = await dapi.sessions.getQRCode(sessionId)
  return qrCodeImage // shown on the CRM settings screen
}

The sessionId carries the account id and the rep id. When the webhook arrives, the CRM knows which account and which book of business the message belongs to without any mapping table. The metadata field stores anything else useful for auditing or support.

From webhook to lead record

The webhook handler is where the integration starts to feel like a CRM. A flow that works well, in order:

  1. Validate the sessionId and return 200 fast; processing goes to an internal queue.
  2. Normalize the phone number from from.jid and look up the contact in the account. If it doesn't exist, create the lead with the name from from_name and source "WhatsApp".
  3. Write the message to the lead timeline. If fromMe is true, it was sent from the number itself, for example typed by the rep on their phone.
  4. Assign the conversation: if the lead already has an owner, notify the owner; if not, apply the account's round-robin rule.
  5. For media, download it through the download endpoint and attach it to the record, instead of storing just the link.

Two details prevent production bugs. An edited message arrives as messages.received with type set to edited_message, so the CRM should update the existing record instead of creating another one. And webhook delivery retries up to 7 times with exponential backoff, which means the same event can arrive again: use the message id as a unique key. The WhatsApp webhooks guide covers the envelope and the events in detail.

Implementation roadmap for the CRM team

  1. Week 1, connection: settings screen with the QR code, connection created via API and a status indicator fed by the connection.status event.
  2. Week 2, inbound: webhook, automatic lead creation and history on the record.
  3. Week 3, inbox: conversations screen, replies from the CRM, file sending and assignment per rep.
  4. Week 4, pilot: release to a small group of customers, measure disconnections and tune the reconnect prompt.

The timeline depends on team size, but the hard part is usually the inbox, not the API. With the 14-day free trial available through sales, your developers build the integration with support from our team in a WhatsApp group, in English.

One number per account or one per rep?

There is no single answer, and the CRM should let the customer choose. A shared number gives the manager full control and keeps the contact from being "stuck" with one person. A number per rep respects the relationship each one built, but multiplies connections and needs a clear rule for when someone leaves. The page on multiple WhatsApp numbers explains what it means to run several numbers in the same account.

If your CRM also handles post-sale support with queues and SLAs, see how that changes in WhatsApp API for helpdesks. The commercial model for companies that resell WhatsApp inside their own product is in WhatsApp API for SaaS, and per-connection prices are on the pricing page.

Frequently asked questions

Does every sales rep in the CRM need their own number?
Not necessarily. The team can share one company number and the CRM decides who answers each conversation. When each rep wants their own book of business, each one connects their own number and it becomes a separate connection in the same account.
Can the CRM show conversations the rep had on their phone?
Yes. With the unofficial WhatsApp API the number keeps working on the phone, and message events carry a fromMe field indicating the message was sent from the number itself. The CRM stores those messages in the same history.
How does the CRM know which customer account each incoming message belongs to?
Every webhook carries the connection sessionId. If the sessionId follows a pattern tied to the customer id in your database, the message arrives already addressed to the right account, with no extra lookup.
Can I use the official API for some customers and the unofficial one for others?
Yes. The type is chosen when each connection is created, and the send routes and webhooks are the same. The CRM treats both the same way; only the onboarding for each customer changes.
How much does it cost to offer WhatsApp to every customer of the CRM?
D-API charges per connection, not per message, and the unit price drops as your connection base grows. Current prices are on the pricing page.

Put WhatsApp in your product without becoming an infra team

14 days free through our sales team, with implementation support in a WhatsApp group.