> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.voicebip.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.voicebip.com/_mcp/server.

# WhatsApp AI Agent

> An AI agent that holds a full WhatsApp conversation — answers questions, sends a template to open the window, hands off to a human. The channel most of Nigeria actually uses.

**What you build:** a WhatsApp identity that, when a customer messages it, is answered by an AI agent. A hosted agent replies automatically; you can also send messages yourself, pull answers from a [knowledge base](/use-cases/knowledge-base-deep-dive), and switch a conversation to a human. You can reach out first with an approved template.

```
Customer → WhatsApp message ──▶ message.received webhook (notification)
                                    │
        hosted agent auto-replies ──┤   (or) your app → POST /v1/messages
                                    ▼
Customer ◀── AI reply in the same WhatsApp thread
```

**Who it's for:** Nigerian D2C brands, informal commerce, POS agents, and anyone whose customers live on WhatsApp rather than email. This is Voicebip's clearest differentiator — a genuine WhatsApp-first AI channel, not a voice tool with messaging bolted on.

> **Note**
>
> **WhatsApp's 24-hour window & billing.** You can freely reply within **24 hours** of the customer's last message (a "service" conversation). To message a customer *outside* that window you must send a pre-approved **template**, which opens a new billable conversation. Voicebip bills **per 24-hour conversation, per category** (not per message).

## Prerequisites

* A WhatsApp-enabled sender (a Voicebip number with the `whatsapp` channel) and its `phone_number_id`.
* An agent to run the conversation. A **hosted** agent auto-replies; a **BYOM** agent receives each inbound message at its `webhook_url` and you compose the reply.
* A webhook receiver for `message.received` / `message.delivered`.

## Step 1 — Receive an inbound message

When a customer messages your WhatsApp number, Voicebip fires `message.received` to your workspace webhook:

```json
{
  "event_id": "evt_1c…",
  "event_type": "message.received",
  "channel": "whatsapp",
  "from": "+2348031234567",
  "number": "+2347000001111",
  "timestamp": "2026-07-02T10:00:00Z",
  "payload": {
    "conversation_id": "conv_7d…",
    "message_id": "msg_9a…",
    "text": "Do you deliver to Ibadan?"
  }
}
```

For a **hosted** agent this is a notification — the AI dispatcher answers automatically while the conversation's `ai_mode` is `ai`. For a **BYOM** agent, the inbound message is instead POSTed to the agent's `webhook_url` as a `BYOMMessagingWebhookRequest` (`{agent_id, conversation_id, channel, from_number, to_number, inbound_message, history, metadata}`) and you return the reply text.

## Step 2 — Send a message yourself

To send (or when a human is driving the thread), call `POST /v1/messages`. All of `agent_id`, `channel`, `from_number`, `to_number`, `body` are required; WhatsApp also needs `phone_number_id`:

```bash
curl -X POST https://api.voicebip.com/v1/messages \
  -H "Authorization: Bearer pk_xxx" -H "Content-Type: application/json" \
  -d '{
    "agent_id": "agt_PAEZ_njcfm2kycpjs",
    "channel": "whatsapp",
    "from_number": "+2347000001111",
    "to_number": "+2348031234567",
    "phone_number_id": "1234567890",
    "body": "Yes — we deliver to Ibadan in 2 to 3 business days. Want to place an order?"
  }'
```

```json
{ "message_id": "msg_2f…", "status": "queued" }
```

To ground the reply first, query a [knowledge base](/use-cases/knowledge-base-deep-dive) (`POST …/query`), compose from the returned chunks, then send.

## Step 3 — Reach out first with a template

To start a conversation (or re-engage after 24h), send a pre-approved template. Positional variables go in `parameters` (an array of strings, filling `{{1}}`, `{{2}}`, …):

```bash
curl -X POST https://api.voicebip.com/v1/messages/template \
  -H "Authorization: Bearer pk_xxx" -H "Content-Type: application/json" \
  -d '{
    "agent_id": "agt_PAEZ_njcfm2kycpjs",
    "from_number": "+2347000001111",
    "to_number": "+2348031234567",
    "template_name": "order_shipped",
    "language_code": "en",
    "parameters": ["Ada", "AC-4821", "tomorrow"]
  }'
```

This opens a new billable conversation window; once the customer replies you're back in the free 24h service window.

## Step 4 — Hand off to a human

Conversations carry an `ai_mode`. To let a human take over a thread, transition it to `human` (the AI dispatcher stops answering):

```bash
curl -X PATCH https://api.voicebip.com/v1/conversations/conv_7d… \
  -H "Authorization: Bearer pk_xxx" -H "Content-Type: application/json" \
  -d '{ "ai_mode": "human", "reason": "billing dispute — agent escalated" }'
```

`ai_mode` values: `ai` (AI dispatcher answers), `human` (operator has taken over), `closed` (terminated — the next inbound message starts a fresh conversation). The PATCH is idempotent (same-mode returns `changed: false`). Read the full history any time via `GET /v1/conversations/{id}` or stream it live with `GET /v1/conversations/{id}/stream` (SSE).

## Step 5 — Respect opt-outs (NDPR)

If a customer sends a stop keyword, Voicebip enrols them in your workspace opt-out list and further sends to that number are refused. Don't try to bypass it. (Opt-out enforcement is automatic; you'll see sends to opted-out numbers rejected.)

## Config summary

| Concern                  | How                                                                                      |
| ------------------------ | ---------------------------------------------------------------------------------------- |
| Inbound trigger (hosted) | `message.received` webhook (agent auto-replies)                                          |
| Inbound trigger (BYOM)   | `BYOMMessagingWebhookRequest` POSTed to the agent's `webhook_url`                        |
| Send in-window           | `POST /v1/messages` `{agent_id, channel, from_number, to_number, body, phone_number_id}` |
| Proactive / re-engage    | `POST /v1/messages/template` (billable conversation)                                     |
| Human takeover           | `PATCH /v1/conversations/{id}` `{ai_mode: "human"}`                                      |
| Billing                  | per 24h conversation, per category                                                       |

## Test it (sandbox)

```bash
# Simulate an inbound WhatsApp message hitting your webhook
curl -X POST https://api.voicebip.com/v1/webhooks/test \
  -H "Authorization: Bearer pk_test_xxx" -H "Content-Type: application/json" \
  -d '{ "webhook_url": "https://you.example.com/webhooks", "event_type": "message.received" }'
```

The test catalogue also covers `message.sent`, `message.delivered`, and `message.failed`, each with a realistic Nigerian payload and a real HMAC signature. See [Sandbox Mode](/reference/sandbox-mode).

## Troubleshooting

| Symptom                      | Likely cause                                                                                                                     |
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `POST /v1/messages` rejected | Missing a required field — `agent_id`, `from_number`, `to_number`, `body` (and `phone_number_id` for WhatsApp) are all required. |
| Template send fails          | Template not approved, or `parameters` doesn't fill every `{{n}}` slot.                                                          |
| Customer never gets replies  | Conversation is `human`/`closed`, or the number is on the opt-out list.                                                          |
| `402 WORKSPACE_BLOCKED`      | Workspace balance hit zero — top up (billing fail-closed).                                                                       |

## Next steps

* Ground WhatsApp replies in your docs → [Knowledge Base deep-dive](/use-cases/knowledge-base-deep-dive).
* Reach customers who don't reply on WhatsApp by also trying voice and SMS → [Multi-channel cascade](/use-cases/multi-channel-cascade).
* Send WhatsApp at list scale → [Campaigns deep-dive](/use-cases/campaigns-deep-dive).