# Sending messages

> Text, templates and buttons via the API, with the 24-hour window and common errors.

Source: https://developers.converzap.com/en/enviar-mensagens

## Before sending

WhatsApp has two Meta rules that the API applies exactly like the app:

- **24-hour window:** up to 24 h after the contact's last message you can send **text**, **buttons** or a **list**. The conversation shows it in `window.open` and `window.expires_at`.
- **Outside the window**, only an **approved template** (`GET /v1/templates?status=approved`).

Contacts who opted out don't get templates; you can reply only if they write again.

## Text

```bash
curl -X POST https://api.converzap.com/v1/conversations/CONVERSATION_ID/messages \
  -H "Authorization: Bearer czk_live_YOUR_KEY" \
  -H "Idempotency-Key: 6c1f0e2a-5b7d-4c1e-9b1a-1f2e3d4c5b6a" \
  -H "Content-Type: application/json" \
  -d '{ "type": "text", "text": "Hi Ana! Your order is on its way." }'
```

## Template (outside the window)

```json
{
  "type": "template",
  "template": {
    "name": "appointment_reminder",
    "language": "pt_BR",
    "params": { "body": ["Ana", "tomorrow at 3pm"] }
  }
}
```

Variables: `body` as a list (`{{1}}`, `{{2}}`…) or an object (named: `{ "name": "Ana" }`), `header` the same, `buttons: { "0": "url-suffix" }`. `template.id` also works instead of name + language.

## Buttons and list

```json
{
  "type": "interactive",
  "interactive": {
    "type": "buttons",
    "body": "Confirm tomorrow's appointment?",
    "buttons": [{ "id": "yes", "title": "Confirm" }, { "id": "no", "title": "Reschedule" }]
  }
}
```

The contact's reply arrives as a text message with the button title (and in the `message.received` webhook).

## What happens when you send

- The sender becomes the conversation **assignee** if it had none.
- The number's **AI agent** logs the human reply and pauses, if configured to.
- The message shows in the inbox as sent by the key's user.

## Common errors

| code | What to do |
|---|---|
| `outside_24h_window` | Use an approved template. |
| `opt_out` | The contact opted out; wait for them to write. |
| `template_invalid` | Wrong name/language or template not approved for this number. |
| `template_param_missing` | A variable is missing; `detail` says which. |
| `number_disconnected` / `number_blocked` | Number disconnected or blocked by Meta; check WhatsApp Health in the app. |
| `meta_error` | Meta refused; `detail` has its message. |

Always send `Idempotency-Key`: if the network drops and you retry, the message isn't sent twice.
