API Reference
The Wapicore Messaging API lets you send WhatsApp messages using your connected WABA. All requests are authenticated with an API key created in your dashboard.
| Value | |
|---|---|
| Base URL | https://msg.wapicore.com.br/v1 |
| Protocol | HTTPS only |
| Format | JSON (application/json) |
Include your API key in every request:
Authorization: Bearer sk_live_xxxxxxxxxxxxMessages
Send a WhatsApp message to any recipient. The phone_number_id is found in your dashboard under Numbers.
/v1/messagesmessages:send| Field | Type | Required | Description |
|---|---|---|---|
| phone_number_id | string | ✓ | Your WhatsApp phone number ID |
| to | string | ✓ | Recipient in E.164 format — e.g. +5511999999999 |
| type | string | ✓ | text | template | image | audio | video | document | interactive |
| text | object | — | Required when type = text |
| template | object | — | Required when type = template |
| image / audio / … | object | — | Required for the matching media type |
| interactive | object | — | Required when type = interactive |
Text
curl -X POST https://msg.wapicore.com.br/v1/messages \
-H "Authorization: Bearer sk_live_xxxx" \
-H "Content-Type: application/json" \
-d '{
"phone_number_id": "1234567890",
"to": "+5511999999999",
"type": "text",
"text": { "body": "Hello from Wapicore!" }
}'// 200 OK
{
"messaging_product": "whatsapp",
"contacts": [{ "input": "+5511999999999", "wa_id": "5511999999999" }],
"messages": [{ "id": "wamid.xxx" }]
}Template
Required to initiate a conversation outside the 24-hour customer service window. Templates must be pre-approved by Meta before use.
curl -X POST https://msg.wapicore.com.br/v1/messages \
-H "Authorization: Bearer sk_live_xxxx" \
-H "Content-Type: application/json" \
-d '{
"phone_number_id": "1234567890",
"to": "+5511999999999",
"type": "template",
"template": {
"name": "order_confirmed",
"language": { "code": "pt_BR" },
"components": [
{
"type": "body",
"parameters": [
{ "type": "text", "text": "Pedido #4821" }
]
}
]
}
}'Media
Supported types: image, audio, video, document, sticker. Pass either a public link or a Meta media id.
curl -X POST https://msg.wapicore.com.br/v1/messages \
-H "Authorization: Bearer sk_live_xxxx" \
-H "Content-Type: application/json" \
-d '{
"phone_number_id": "1234567890",
"to": "+5511999999999",
"type": "image",
"image": {
"link": "https://example.com/image.jpg",
"caption": "Your order is packed!"
}
}'Interactive
Supports button (up to 3 reply buttons) and list (up to 10 items).
curl -X POST https://msg.wapicore.com.br/v1/messages \
-H "Authorization: Bearer sk_live_xxxx" \
-H "Content-Type: application/json" \
-d '{
"phone_number_id": "1234567890",
"to": "+5511999999999",
"type": "interactive",
"interactive": {
"type": "button",
"body": { "text": "Choose an option:" },
"action": {
"buttons": [
{ "type": "reply", "reply": { "id": "yes", "title": "Yes" } },
{ "type": "reply", "reply": { "id": "no", "title": "No" } }
]
}
}
}'Webhooks
Receive real-time events from WhatsApp — inbound messages, delivery status updates, and template status changes. Webhook endpoints are managed in your dashboard under Webhooks.
Setup
In the dashboard, create a webhook endpoint by providing:
| Field | Description |
|---|---|
| URL | Your HTTPS endpoint — must return 200 within 5 seconds |
| Events | message | message_status | template_status |
| Secret | Minimum 16 characters — used to verify HMAC signatures |
Event payloads
All events share the same envelope:
{
"event": "message",
"timestamp": "2026-07-09T14:22:00.000Z",
"phoneNumberId": "1234567890",
"data": { /* event-specific payload from Meta */ }
}| Event | Description | data content |
|---|---|---|
| message | Inbound message received | Meta message object |
| message_status | Delivery / read status update | Meta status object |
| template_status | Template approved / rejected / paused | Meta template status object |
HMAC verification
Every delivery includes a X-Wapicore-Signature-256 header. Always verify it before processing the event.
import crypto from "crypto";
function verifyWebhook(rawBody, signature, secret) {
const expected = "sha256=" + crypto
.createHmac("sha256", secret)
.update(rawBody) // raw bytes — do NOT parse JSON first
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
// Express example
app.post("/webhook", express.raw({ type: "application/json" }), (req, res) => {
const sig = req.headers["x-wapicore-signature-256"];
if (!verifyWebhook(req.body, sig, process.env.WEBHOOK_SECRET)) {
return res.status(401).send("Invalid signature");
}
const event = JSON.parse(req.body.toString());
// ... process event
res.status(200).send("OK");
});Templates
Message templates must be approved by Meta before use. This API proxies to the Meta Graph API using your WABA credentials.
List templates
/v1/whatsapp/numbers/:numberId/templatestemplates:readcurl https://msg.wapicore.com.br/v1/whatsapp/numbers/NUMBER_ID/templates \
-H "Authorization: Bearer sk_live_xxxx"{
"templates": [
{
"id": "123456789",
"name": "order_confirmed",
"status": "APPROVED",
"category": "UTILITY",
"language": "pt_BR"
}
]
}Create template
/v1/whatsapp/numbers/:numberId/templatestemplates:writeSubmits a template for Meta review. Simple utility templates are usually approved within minutes; marketing templates may take longer.
curl -X POST https://msg.wapicore.com.br/v1/whatsapp/numbers/NUMBER_ID/templates \
-H "Authorization: Bearer sk_live_xxxx" \
-H "Content-Type: application/json" \
-d '{
"name": "order_confirmed",
"language": "pt_BR",
"category": "UTILITY",
"components": [
{
"type": "BODY",
"text": "Olá! Seu pedido {{1}} foi confirmado e será entregue em até {{2}} dias úteis."
}
]
}'| Category | Use case |
|---|---|
| UTILITY | Transactional — order confirmations, shipping updates, reminders |
| MARKETING | Promotions, offers, newsletters |
| AUTHENTICATION | OTPs and login verification codes |
Delete template
/v1/whatsapp/numbers/:numberId/templates/:templateNametemplates:writecurl -X DELETE https://msg.wapicore.com.br/v1/whatsapp/numbers/NUMBER_ID/templates/order_confirmed \
-H "Authorization: Bearer sk_live_xxxx"Errors
All errors return a JSON object with a human-readable message:
{ "error": "Human-readable error message" }| Status | Meaning |
|---|---|
| 400 | Bad request — validation error, see message for details |
| 401 | Unauthorized — missing or invalid API key |
| 403 | Forbidden — valid key but missing required scope |
| 404 | Resource not found |
| 429 | Too Many Requests — rate limit exceeded, see Retry-After header |
| 500 | Internal server error |
Rate limits
Limits are applied per API key. When exceeded the API returns 429 with a Retry-After header indicating when to retry.
| Endpoint | Limit | Window |
|---|---|---|
| POST /v1/messages | 100 requests | 1 minute |
| All other endpoints | 120 requests | 1 minute |