Skip to main content
POST
/
v1
/
messages
/
template
Send an approved WhatsApp template
curl --request POST \
  --url https://api.keebai.com/v1/messages/template \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "to": "+5491155555555",
  "phone_number_id": "100000000000001",
  "template_name": "welcome_v2",
  "language": "es",
  "variables": {
    "nombre": "Lucio",
    "monto": "1500"
  },
  "meta_data": {}
}
'
{
  "message_id": "<string>",
  "status": "sent",
  "sent_at": "<string>"
}
Queues delivery of a Meta-approved template to a single recipient. Useful for transactional notifications, reminders, and 1-to-1 messages triggered from your backend. Under the hood, Keebai creates a broadcast with a single recipient, which lets you check its status later with GET /v1/messages/bulk/:broadcastId.

Endpoint

POST https://api.keebai.com/v1/messages/template

Required scope

messages:send

Headers

HeaderRequiredValue
AuthorizationYesBearer kbai_pk_<token>
Content-TypeYesapplication/json

Body

FieldTypeRequiredDescription
tostringYesRecipient phone number in E.164 format (e.g. +5491155555555).
channel_idstringYesObjectId of the WhatsApp channel used to send. Get it from the portal under Channels.
template_namestringYesTemplate name exactly as approved in Meta.
languagestringYesTemplate language code (es, en, pt_BR, etc.).
variablesobject<string, string>NoMap of named variables the template expects. Keys must match the template’s {{name}} placeholders. The expected list is available via GET /v1/templates.
meta_dataobjectNoFree-form metadata persisted with the message. Useful to correlate with your system.

Example request

curl -X POST https://api.keebai.com/v1/messages/template \
  -H "Authorization: Bearer kbai_pk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+5491155555555",
    "channel_id": "65a1f2b3c4d5e6f7a8b9c0d1",
    "template_name": "welcome_v2",
    "language": "es",
    "variables": {
      "nombre": "Lucio",
      "monto": "1500"
    },
    "meta_data": {
      "order_id": "ORD-2026-0042"
    }
  }'

Response

202 Accepted

The send was accepted and queued. Actual delivery to WhatsApp happens asynchronously.
{
  "broadcast_id": "65f4b5c6d7e8f9a0b1c2d3e4",
  "status": "PENDING",
  "total_recipients": 1,
  "scheduled_at": null
}
FieldTypeDescription
broadcast_idstringId of the created broadcast. Use it to check status via GET /v1/messages/bulk/:broadcastId.
statusstringInitial broadcast status: PENDING, IN_PROGRESS, COMPLETED, FAILED.
total_recipientsnumberAlways 1 for this endpoint.
scheduled_atstring | nullISO 8601 schedule date if applicable, null for immediate delivery.

400 Bad Request

Invalid body (incorrect phone format, malformed channel_id, missing fields).

401 Unauthorized

Missing, invalid, revoked, or expired token.

403 Forbidden

The token does not have the messages:send scope.
{
  "error": {
    "code": "INSUFFICIENT_SCOPE",
    "message": "Forbidden",
    "details": {
      "required": ["messages:send"],
      "missing": ["messages:send"]
    }
  }
}

502 Bad Gateway

Error contacting the upstream delivery service. Retry with backoff.

Common patterns

Transactional notification with correlation

import os, requests

def notify_order(order_id: str, customer_phone: str, customer_name: str, amount: float):
    resp = requests.post(
        "https://api.keebai.com/v1/messages/template",
        headers={"Authorization": f"Bearer {os.environ['KEEBAI_API_TOKEN']}"},
        json={
            "to": customer_phone,
            "channel_id": os.environ["KEEBAI_CHANNEL_ID"],
            "template_name": "order_confirmation",
            "language": "es",
            "variables": {
                "nombre": customer_name,
                "monto": f"{amount:.2f}",
            },
            "meta_data": {"order_id": order_id},
        },
        timeout=10,
    )
    resp.raise_for_status()
    return resp.json()["broadcast_id"]

Authorizations

Authorization
string
header
required

Personal Access Token con prefijo kbai_pk_. Generar desde el portal con permiso developer.manage_tokens.

Body

application/json
to
string
required
Example:

"+5491155555555"

phone_number_id
string
required

WhatsApp Business phone_number_id (numeric identifier issued by Meta for the sending number).

Example:

"100000000000001"

template_name
string
required
Example:

"welcome_v2"

language
string
required
Example:

"es"

variables
object

Named template variables (Meta parameter_name).

Example:
{ "nombre": "Lucio", "monto": "1500" }
meta_data
object

Free-form metadata persisted with the message. Returned on webhooks for correlation.

Response

202 - application/json
message_id
string
required

Meta message_id (wamid.*) of the sent WhatsApp message.

status
string
required
Example:

"sent"

sent_at
string
required

ISO-8601 timestamp of the dispatch.