Integrations

Typebot on WhatsApp: how to connect your flow to the WhatsApp API

For a Typebot flow to talk on WhatsApp through the D-API WhatsApp API, you need a middleware: it receives the message webhook, passes it to Typebot through its chat API and sends the replies back through the REST API. There is no direct connection between the two, and this guide shows what that service does.

By D-API engineering team5 min read

What Typebot does and what it does not do on its own

Typebot is good at designing the conversation: questions, answer validation, variables, conditions. What it does not do is talk to a number connected by QR code. The WhatsApp integration that ships with Typebot is designed for Meta’s official platform, configured with your Meta account credentials.

D-API does not have a native Typebot connector either. So, to run the flow on a D-API number, the conversation goes through a third component. Being upfront about this saves you the frustration of looking for a "connect" button that does not exist.

The architecture: three pieces and two APIs

  1. The person writes on WhatsApp. D-API fires the messages.received event to your middleware’s URL.
  2. The middleware checks whether that phone number already has a Typebot session. If not, it calls POST /api/v1/typebots/YOUR_PUBLIC_ID/startChat. If it does, it calls POST /api/v1/sessions/SESSION_ID/continueChat with the received text.
  3. Typebot responds with a messages array (the bot bubbles) and the input it expects next.
  4. The middleware sends each bubble through D-API, in order, and stores the Typebot sessionId for the same person’s next message.

On Typebot cloud, the base for these routes is https://typebot.io/api/v1. If you self-host Typebot, use your own domain. The flow must be published.

The middleware in code

A lean Node.js example, with the d-api-sdk SDK for sending and a Map standing in for storage. In production, replace the Map with Redis or a database, because process memory is lost on deploy and does not work with more than one instance:

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

const dapi = new DApi({ apiKey: process.env.DAPI_KEY })
const TYPEBOT = 'https://typebot.io/api/v1'
const sessions = new Map() // phone -> Typebot sessionId

const app = express()
app.use(express.json())

app.post('/webhook/dapi', async (req, res) => {
  res.sendStatus(200) // answer fast; processing continues below
  const { event, sessionId, data } = req.body
  if (event !== 'messages.received' || data.fromMe || data.is_group) return

  const phone = data.from.jid.split('@')[0] // e.g. 14155550123
  const typebotSession = sessions.get(phone)
  const url = typebotSession
    ? `${TYPEBOT}/sessions/${typebotSession}/continueChat`
    : `${TYPEBOT}/typebots/${process.env.TYPEBOT_PUBLIC_ID}/startChat`

  const reply = await fetch(url, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      message: { type: 'text', text: data.message },
      textBubbleContentFormat: 'markdown',
    }),
  }).then((r) => r.json())

  if (reply.sessionId) sessions.set(phone, reply.sessionId)

  for (const bubble of reply.messages ?? []) {
    if (bubble.type !== 'text') continue
    await dapi.messages.sendText({ sessionId, to: phone, text: bubble.content.markdown })
  }
})

app.listen(3000)

Requesting textBubbleContentFormat: 'markdown' makes Typebot return each bubble as plain text with markup, which is much easier to forward than the default rich format.

What the example above does not cover yet

The code shows the skeleton. A middleware that handles real usage also takes care of:

  • Buttons and choices: when the Typebot input is a choice, turn the options into a list through the /api/v1/interactive/send/list route or into numbered text. Details for each format are in WhatsApp buttons and lists.
  • Media: image, video or audio bubbles go to the matching media send routes, with the URL Typebot returns.
  • End of flow: when Typebot no longer returns an input, delete the stored session. Otherwise, that person’s next message lands in a finished flow.
  • Repeated messages: D-API may resend a webhook when your URL is slow or fails. Keep the data.id of processed messages for a few minutes and ignore duplicates.
  • Handoff to a human: define a variable in the flow that, when set, makes the middleware stop calling Typebot and route the conversation to support.

Where the HTTP request block comes in

Inside the flow, Typebot has the HTTP request block, which calls any API mid-conversation, with URL, method, a body with variables in the {{Variable}} format and the option to save the response into variables. It does not replace the middleware, because it does not receive messages, but it is useful for side actions. An example: when the lead finishes qualification, the flow notifies the rep on WhatsApp.

POST https://api.d-api.cloud/api/v1/messages/send/text
Authorization: YOUR_API_KEY
Content-Type: application/json

{
  "sessionId": "sales",
  "to": "14155550199",
  "text": "Qualified lead: {{Name}}, company {{Company}}, budget {{Budget}}."
}

By default the block waits 10 seconds for a response, and the timeout can be adjusted in the advanced options. Since the key lives inside the block, restrict who can edit the flow.

Your own middleware or n8n

If your team already writes code, the middleware above becomes a small service next to your product. If not, you can build the same bridge in n8n: a Webhook receives the D-API event, an HTTP Request node calls Typebot and the native D-API node sends the replies.

Either way, the WhatsApp piece is the same D-API WhatsApp API, with per-instance isolation and a dedicated IP per connection. To compare this design with a bot built on a language model, see WhatsApp AI chatbot. For other automation uses, the WhatsApp API for automation page brings the options together, and the WhatsApp webhooks guide details the payload the middleware receives.

Frequently asked questions

Can I connect Typebot to D-API without writing code?
Not entirely. Typebot does not receive the D-API webhook directly, so you need a small service in between that translates messages in both directions. That service can be your own code or an n8n flow.
Doesn’t Typebot already have a WhatsApp integration?
It does, but it is built on Meta’s official platform, using the credentials of your WhatsApp Business Platform account. To use a number connected by QR code on D-API, the path is Typebot’s chat API with a middleware.
How does the middleware know where each person is in the flow?
By storing the sessionId Typebot returns from startChat, keyed by phone number. On the same person’s next message, the middleware calls continueChat with that sessionId. Redis with expiry works well.
Do Typebot choice buttons show up on WhatsApp?
Not in the same way. The middleware has to convert the options, either into an interactive list through the D-API list route or into numbered text that the person answers by typing the number.
What is the HTTP request block for in this setup?
It lets the flow call other systems mid-conversation, including D-API itself. A common use is notifying the sales team on WhatsApp when a lead finishes qualification.

Try D-API's WhatsApp API

3-day trial with full access. No credit card, no lock-in.