# Messages

> Send any message type Meta supports. The body is Meta's /messages body plus from.

Canonical: https://docs.whabuzz.com/api/messages/

Send any message type Meta supports. The body is Meta's `/messages` body plus `from`.

Base URL `https://api.whabuzz.com`. Every request needs `Authorization: Bearer <key>` unless the operation says otherwise; see [Authentication](https://docs.whabuzz.com/authentication.md). Errors follow the [two-source contract](https://docs.whabuzz.com/errors.md).

Operations on this page:

- [`POST /v1/messages`](#sendMessage): Send a message
- [`POST /v1/messages/read`](#markRead): Mark an inbound message read, optionally showing a typing indicator
- [`POST /v1/messages/batch`](#createBatch): Send many messages from one number
- [`GET /v1/messages/batch/{batch_id}`](#getBatch): Batch progress
- [`GET /v1/messages/batch/{batch_id}/items`](#listBatchItems): Batch items with Meta's response for each
- [`POST /v1/messages/batch/{batch_id}/cancel`](#cancelBatch): Cancel the unsent part of a batch

## Send a message {#sendMessage}

`POST /v1/messages`

The body is Meta's `POST /{phone_number_id}/messages` body plus `from` (your number's
phone_number_id or E.164). WhaBuzz adds nothing and checks nothing about content, category
or the customer-service window. Meta decides; its answer comes back verbatim.

**Auth:** API key (tenant key, or app key with `X-WhaBuzz-Tenant`). **Operation id:** `sendMessage`.

**Parameters**

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `Idempotency-Key` | header | string | no | Repeat a send safely for 24 hours. Same key + same body returns the stored response; a different body returns 422. |

**Request body** (`application/json`, required)

| Field | Type | Required | Description |
|---|---|---|---|
| `from` | string | yes | phone_number_id or E.164 of one of your numbers |
| `messaging_product` | string | no | Default `"whatsapp"`. |
| `to` | string | yes |  |
| `type` | string | yes |  |

Request example, Text:

```json
{
  "from": "1013622581841046",
  "messaging_product": "whatsapp",
  "recipient_type": "individual",
  "to": "16505551234",
  "type": "text",
  "text": {
    "preview_url": false,
    "body": "Your trial is booked for 7:00 AM tomorrow."
  }
}
```

Request example, Template with body parameters:

```json
{
  "from": "+14692311132",
  "messaging_product": "whatsapp",
  "to": "16505551234",
  "type": "template",
  "template": {
    "name": "renewal_reminder",
    "language": {
      "code": "en"
    },
    "components": [
      {
        "type": "body",
        "parameters": [
          {
            "type": "text",
            "text": "Kerry"
          },
          {
            "type": "text",
            "text": "31 Oct"
          }
        ]
      }
    ]
  }
}
```

Request example, Authentication template (you send the copy-code button yourself):

```json
{
  "from": "1013622581841046",
  "messaging_product": "whatsapp",
  "to": "16505551234",
  "type": "template",
  "template": {
    "name": "login_code",
    "language": {
      "code": "en_US"
    },
    "components": [
      {
        "type": "body",
        "parameters": [
          {
            "type": "text",
            "text": "482913"
          }
        ]
      },
      {
        "type": "button",
        "sub_type": "url",
        "index": "0",
        "parameters": [
          {
            "type": "text",
            "text": "482913"
          }
        ]
      }
    ]
  }
}
```

Request example, Image by media id:

```json
{
  "from": "1013622581841046",
  "messaging_product": "whatsapp",
  "to": "16505551234",
  "type": "image",
  "image": {
    "id": "1479537139650973",
    "caption": "This week's timetable"
  }
}
```

Request example, Document by link:

```json
{
  "from": "1013622581841046",
  "messaging_product": "whatsapp",
  "to": "16505551234",
  "type": "document",
  "document": {
    "link": "https://example.com/invoice-1042.pdf",
    "filename": "invoice-1042.pdf"
  }
}
```

Request example, Reply buttons:

```json
{
  "from": "1013622581841046",
  "messaging_product": "whatsapp",
  "to": "16505551234",
  "type": "interactive",
  "interactive": {
    "type": "button",
    "body": {
      "text": "Confirm your 7:00 AM session?"
    },
    "action": {
      "buttons": [
        {
          "type": "reply",
          "reply": {
            "id": "confirm_yes",
            "title": "Yes"
          }
        },
        {
          "type": "reply",
          "reply": {
            "id": "confirm_no",
            "title": "Reschedule"
          }
        }
      ]
    }
  }
}
```

Request example, List:

```json
{
  "from": "1013622581841046",
  "messaging_product": "whatsapp",
  "to": "16505551234",
  "type": "interactive",
  "interactive": {
    "type": "list",
    "body": {
      "text": "Pick a slot"
    },
    "action": {
      "button": "Slots",
      "sections": [
        {
          "title": "Tomorrow",
          "rows": [
            {
              "id": "slot_0700",
              "title": "7:00 AM",
              "description": "Strength"
            },
            {
              "id": "slot_1800",
              "title": "6:00 PM",
              "description": "Conditioning"
            }
          ]
        }
      ]
    }
  }
}
```

Request example, Location:

```json
{
  "from": "1013622581841046",
  "messaging_product": "whatsapp",
  "to": "16505551234",
  "type": "location",
  "location": {
    "latitude": 17.3953,
    "longitude": 78.3363,
    "name": "Studio",
    "address": "Kokapet, Hyderabad"
  }
}
```

Request example, Reaction:

```json
{
  "from": "1013622581841046",
  "messaging_product": "whatsapp",
  "to": "16505551234",
  "type": "reaction",
  "reaction": {
    "message_id": "wamid.HBgLMTY1MDU1NTEyMzQVAgASGBQzQUY5QTdGNkU0RTFGMkI3QzFBMDEA",
    "emoji": "👍"
  }
}
```

Request example, Reply in thread (context):

```json
{
  "from": "1013622581841046",
  "messaging_product": "whatsapp",
  "to": "16505551234",
  "context": {
    "message_id": "wamid.HBgLMTY1MDU1NTEyMzQVAgASGBQzQUY5QTdGNkU0RTFGMkI3QzFBMDEA"
  },
  "type": "text",
  "text": {
    "body": "See you at 7."
  }
}
```

cURL:

```bash
curl -X POST "https://api.whabuzz.com/v1/messages" \
  -H "Authorization: Bearer $WHABUZZ_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "from": "1013622581841046",
  "messaging_product": "whatsapp",
  "recipient_type": "individual",
  "to": "16505551234",
  "type": "text",
  "text": {
    "preview_url": false,
    "body": "Your trial is booked for 7:00 AM tomorrow."
  }
}'
```

**Responses**

**200** Meta accepted the message. Body is Meta's, verbatim.

```json
{
  "messaging_product": "whatsapp",
  "contacts": [
    {
      "input": "16505551234",
      "wa_id": "16505551234"
    }
  ],
  "messages": [
    {
      "id": "wamid.HBgLMTY1MDU1NTEyMzQVAgARGBI5QTNDQTVCM0Q0Q0Q2RTY3RTcA",
      "message_status": "accepted"
    }
  ]
}
```

**400** Meta rejected the request (any Meta 4xx is passed through with its own status), or WhaBuzz rejected the body.

Meta 131030 passed through (HTTP 400):

```json
{
  "source": "meta",
  "error": {
    "message": "(#131030) Recipient phone number not in allowed list",
    "type": "OAuthException",
    "code": 131030,
    "error_data": {
      "messaging_product": "whatsapp",
      "details": "Recipient phone number not in allowed list: Add recipient phone number to recipient list and try again."
    },
    "fbtrace_id": "A1b2C3d4E5f6G7h8"
  }
}
```

Meta 132000 passed through (HTTP 400):

```json
{
  "source": "meta",
  "error": {
    "message": "(#132000) Number of parameters does not match the expected number of params",
    "type": "OAuthException",
    "code": 132000,
    "error_data": {
      "messaging_product": "whatsapp",
      "details": "body: number of localizable_params (1) does not match the expected number of params (2)"
    },
    "fbtrace_id": "B2c3D4e5F6g7H8i9"
  }
}
```

whabuzz_missing_from:

```json
{
  "source": "whabuzz",
  "error": {
    "code": "invalid_request",
    "message": "`from` is required: a phone_number_id or E.164 number of this tenant",
    "details": null
  },
  "request_id": "req_01JAB3P5S8V1X4Z7B0D3F6H9K2"
}
```

**409** Number not connected, or the same Idempotency-Key is still in flight.

not_connected:

```json
{
  "source": "whabuzz",
  "error": {
    "code": "number_not_connected",
    "message": "Number 1013622581841046 is not connected: no_verified_endpoint",
    "details": {
      "connection_detail": "no_verified_endpoint"
    }
  },
  "request_id": "req_01JAB3Q6T9W2Y5A8C1E4G7J0M3"
}
```

in_flight:

```json
{
  "source": "whabuzz",
  "error": {
    "code": "idempotency_conflict",
    "message": "A request with this Idempotency-Key is still in progress",
    "details": null
  },
  "request_id": "req_01JAB3R7V0X3Z6B9D2F5H8K1N4"
}
```

**422** Idempotency-Key reused with a different body

```json
{
  "source": "whabuzz",
  "error": {
    "code": "idempotency_conflict",
    "message": "Idempotency-Key was used with a different body",
    "details": null
  },
  "request_id": "req_01JAB3S8W1Y4A7C0E3G6J9M2P5"
}
```

**429** Meta throttled the send (passed through)

```json
{
  "source": "meta",
  "error": {
    "message": "(#130429) Rate limit hit",
    "type": "OAuthException",
    "code": 130429,
    "error_data": {
      "messaging_product": "whatsapp",
      "details": "Cloud API message throughput has been reached."
    },
    "fbtrace_id": "AbCdEf1234567890"
  }
}
```

**502** WhaBuzz could not reach Meta. The outcome is unknown; watch for `message.status` before resending.

```json
{
  "source": "whabuzz",
  "error": {
    "code": "meta_unreachable",
    "message": "Meta did not answer within 15000 ms",
    "details": {
      "timeout_ms": 15000
    }
  },
  "request_id": "req_01JAB49K4P7S0V3Y6B9E2G5J8M"
}
```

**Common errors.** Shape and meanings are on the [Errors page](https://docs.whabuzz.com/errors.md).

| HTTP | WhaBuzz code | Meaning |
|---|---|---|
| 401 | `unauthorized` | Missing or invalid credentials |
| 403 | `tenant_not_approved`, `tenant_suspended` | Tenant not approved or suspended |

## Mark an inbound message read, optionally showing a typing indicator {#markRead}

`POST /v1/messages/read`

**Auth:** API key (tenant key, or app key with `X-WhaBuzz-Tenant`). **Operation id:** `markRead`.

**Request body** (`application/json`, required)

| Field | Type | Required | Description |
|---|---|---|---|
| `from` | string | yes |  |
| `message_id` | string | yes |  |
| `typing_indicator` | object | no |  |
| `typing_indicator.type` | `text` | no |  |

Request example:

```json
{
  "from": "1013622581841046",
  "message_id": "wamid.HBgLMTY1MDU1NTEyMzQVAgASGBQzQUY5QTdGNkU0RTFGMkI3QzFBMDEA",
  "typing_indicator": {
    "type": "text"
  }
}
```

cURL:

```bash
curl -X POST "https://api.whabuzz.com/v1/messages/read" \
  -H "Authorization: Bearer $WHABUZZ_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "from": "1013622581841046",
  "message_id": "wamid.HBgLMTY1MDU1NTEyMzQVAgASGBQzQUY5QTdGNkU0RTFGMkI3QzFBMDEA",
  "typing_indicator": {
    "type": "text"
  }
}'
```

**Responses**

**200** Meta's response verbatim

```json
{
  "success": true
}
```

**Common errors.** Shape and meanings are on the [Errors page](https://docs.whabuzz.com/errors.md).

| HTTP | WhaBuzz code | Meaning |
|---|---|---|
| 400 | `131030` | Meta's error, passed through with Meta's HTTP status |

## Send many messages from one number {#createBatch}

`POST /v1/messages/batch`

Up to 10,000 Meta message bodies. WhaBuzz paces them to the number's throughput and records
Meta's answer for each, verbatim. Each item also produces a `message.outbound` event, and
the batch ends with `batch.completed`. WhaBuzz does not retry items Meta rejected.

**Auth:** API key (tenant key, or app key with `X-WhaBuzz-Tenant`). **Operation id:** `createBatch`.

**Request body** (`application/json`, required)

| Field | Type | Required | Description |
|---|---|---|---|
| `from` | string | yes |  |
| `client_ref` | string | no | Your reference. Unique per tenant; a repeat returns the existing batch. |
| `messages` | array of object | yes |  |

Request example:

```json
{
  "from": "1013622581841046",
  "client_ref": "renewals-2026-11",
  "messages": [
    {
      "messaging_product": "whatsapp",
      "to": "16505551234",
      "type": "template",
      "template": {
        "name": "renewal_reminder",
        "language": {
          "code": "en"
        },
        "components": [
          {
            "type": "body",
            "parameters": [
              {
                "type": "text",
                "text": "Kerry"
              },
              {
                "type": "text",
                "text": "31 Oct"
              }
            ]
          }
        ]
      }
    },
    {
      "messaging_product": "whatsapp",
      "to": "16505551235",
      "type": "template",
      "template": {
        "name": "renewal_reminder",
        "language": {
          "code": "en"
        },
        "components": [
          {
            "type": "body",
            "parameters": [
              {
                "type": "text",
                "text": "Ravi"
              },
              {
                "type": "text",
                "text": "2 Nov"
              }
            ]
          }
        ]
      }
    }
  ]
}
```

cURL:

```bash
curl -X POST "https://api.whabuzz.com/v1/messages/batch" \
  -H "Authorization: Bearer $WHABUZZ_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "from": "1013622581841046",
  "client_ref": "renewals-2026-11",
  "messages": [
    {
      "messaging_product": "whatsapp",
      "to": "16505551234",
      "type": "template",
      "template": {
        "name": "renewal_reminder",
        "language": {
          "code": "en"
        },
        "components": [
          {
            "type": "body",
            "parameters": [
              {
                "type": "text",
                "text": "Kerry"
              },
              {
                "type": "text",
                "text": "31 Oct"
              }
            ]
          }
        ]
      }
    },
    {
      "messaging_product": "whatsapp",
      "to": "16505551235",
      "type": "template",
      "template": {
        "name": "renewal_reminder",
        "language": {
          "code": "en"
        },
        "components": [
          {
            "type": "body",
            "parameters": [
              {
                "type": "text",
                "text": "Ravi"
              },
              {
                "type": "text",
                "text": "2 Nov"
              }
            ]
          }
        ]
      }
    }
  ]
}'
```

**Responses**

**202** Queued

```json
{
  "id": "bat_01JAB3T9X2Z5B8D1F4H7K0M3Q6",
  "status": "queued",
  "total": 2,
  "accepted": 0,
  "failed": 0,
  "rate_per_sec": 20,
  "client_ref": "renewals-2026-11",
  "created_at": "2026-10-16T10:00:00Z"
}
```

**Common errors.** Shape and meanings are on the [Errors page](https://docs.whabuzz.com/errors.md).

| HTTP | WhaBuzz code | Meaning |
|---|---|---|
| 409 | `number_not_connected` | Number not connected |

## Batch progress {#getBatch}

`GET /v1/messages/batch/{batch_id}`

**Auth:** API key (tenant key, or app key with `X-WhaBuzz-Tenant`). **Operation id:** `getBatch`.

**Parameters**

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `batch_id` | path | string | yes |  |

cURL:

```bash
curl -X GET "https://api.whabuzz.com/v1/messages/batch/$BATCH_ID" \
  -H "Authorization: Bearer $WHABUZZ_KEY"
```

**Responses**

**200** Batch

```json
{
  "id": "bat_01JAB3T9X2Z5B8D1F4H7K0M3Q6",
  "status": "completed",
  "total": 2,
  "accepted": 1,
  "failed": 1,
  "started_at": "2026-10-16T10:01:00Z",
  "completed_at": "2026-10-16T10:01:01Z"
}
```

## Batch items with Meta's response for each {#listBatchItems}

`GET /v1/messages/batch/{batch_id}/items`

**Auth:** API key (tenant key, or app key with `X-WhaBuzz-Tenant`). **Operation id:** `listBatchItems`.

**Parameters**

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `batch_id` | path | string | yes |  |
| `status` | query | `pending` or `accepted` or `failed` or `skipped` | no |  |
| `limit` | query | integer | no |  |
| `cursor` | query | string | no | `next_cursor` from the previous page. |

cURL:

```bash
curl -X GET "https://api.whabuzz.com/v1/messages/batch/$BATCH_ID/items" \
  -H "Authorization: Bearer $WHABUZZ_KEY"
```

**Responses**

**200** Items

```json
{
  "data": [
    {
      "idx": 1,
      "status": "failed",
      "http_status": 400,
      "wamid": null,
      "response": {
        "error": {
          "message": "(#131030) Recipient phone number not in allowed list",
          "type": "OAuthException",
          "code": 131030,
          "error_data": {
            "messaging_product": "whatsapp",
            "details": "Recipient phone number not in allowed list: Add recipient phone number to recipient list and try again."
          },
          "fbtrace_id": "A1b2C3d4E5f6G7h8"
        }
      },
      "event_id": "evt_01JAB3V0Y3A6C9E2G5J8M1P4R7",
      "sent_at": "2026-10-16T10:01:01Z"
    }
  ],
  "next_cursor": null
}
```

## Cancel the unsent part of a batch {#cancelBatch}

`POST /v1/messages/batch/{batch_id}/cancel`

**Auth:** API key (tenant key, or app key with `X-WhaBuzz-Tenant`). **Operation id:** `cancelBatch`.

**Parameters**

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `batch_id` | path | string | yes |  |

cURL:

```bash
curl -X POST "https://api.whabuzz.com/v1/messages/batch/$BATCH_ID/cancel" \
  -H "Authorization: Bearer $WHABUZZ_KEY"
```

**Responses**

**200** Cancelled

```json
{
  "id": "bat_01JAB3T9X2Z5B8D1F4H7K0M3Q6",
  "status": "cancelled",
  "total": 2000,
  "accepted": 640,
  "failed": 3
}
```
