whatsapp-cloud-api logo

whatsapp-cloud-api

whatsapp cloud api

SKILL.md

Full skill instructions

WhatsApp Cloud API

When to Use

Activate this skill when:

  • Building or modifying WhatsApp messaging features
  • Sending messages (text, media, templates, interactive)
  • Processing incoming webhooks from WhatsApp
  • Working with template messages or conversation windows
  • Handling phone number formatting (E.164)
  • Debugging WhatsApp API errors or status updates
  • Implementing message status tracking (sent, delivered, read)
  • Running a number on both the WhatsApp Business App and Cloud API (Coexistence)

Quick Reference

ItemValue
Base URLhttps://graph.facebook.com/v21.0
Send MessagePOST /{phone-number-id}/messages
Upload MediaPOST /{phone-number-id}/media
AuthAuthorization: Bearer {access-token}
Required Field"messaging_product": "whatsapp"
Phone FormatE.164: +{country}{number} (e.g., +18091234567)
Rate Limit80 messages/second (Cloud API)

Core API — Send Message

All messages go through a single endpoint:

POST https://graph.facebook.com/v21.0/{phone-number-id}/messages
Authorization: Bearer {access-token}
Content-Type: application/json

Response:

{
  "messaging_product": "whatsapp",
  "contacts": [{ "input": "+16505555555", "wa_id": "16505555555" }],
  "messages": [{ "id": "wamid.HBgL..." }]
}

Message Types

Typetype FieldDetails
TexttextPlain text, max 4096 chars, supports URL preview
ImageimageJPEG/PNG, max 5MB, optional caption
VideovideoMP4, max 16MB, optional caption
AudioaudioAAC/MP3/OGG, max 16MB
DocumentdocumentAny format, max 100MB, optional filename
StickerstickerWebP, static 100KB / animated 500KB
Locationlocationlatitude, longitude, name, address
ContactscontactsStructured contact cards
ReactionreactionEmoji reaction to a message
InteractiveinteractiveButtons, lists, products
TemplatetemplatePre-approved message templates

For full specs and code examples, see references/MESSAGING.md.

Webhooks

Your server receives POST requests for incoming messages and status updates.

Incoming message structure:

{
  "object": "whatsapp_business_account",
  "entry": [{
    "changes": [{
      "value": {
        "messaging_product": "whatsapp",
        "metadata": { "phone_number_id": "ID", "display_phone_number": "NUM" },
        "contacts": [{ "profile": { "name": "John" }, "wa_id": "16315551234" }],
        "messages": [{
          "from": "16315551234",
          "id": "wamid.ABC...",
          "timestamp": "1683229471",
          "type": "text",
          "text": { "body": "Hello" }
        }]
      },
      "field": "messages"
    }]
  }]
}

Status update types: sentdeliveredread | failed

For webhook verification, payload parsing, and all status types, see references/WEBHOOKS.md.

Conversation Window

  • When a customer messages you, a 24-hour service window opens
  • Inside the window: send any message type freely (service messages are FREE)
  • Outside the window: only template messages can be sent (paid per message)
  • No API endpoint to "close" a conversation — windows expire automatically
  • Template messages open their own 24h window per category (marketing, utility, auth)

For full lifecycle, pricing, and category rules, see references/CONVERSATIONS.md.

Coexistence

Run one number on the WhatsApp Business App and the Cloud API simultaneously — the business keeps chatting from the app while you integrate via the API.

  • Onboard via a customized Embedded Signup flow (featureType: "whatsapp_business_app_onboarding"), not standard registration
  • Onboarding triggers a one-time sync of past messages (history, up to 180 days) and contacts (smb_app_state_sync)
  • Messages the business sends from the app are mirrored to your webhook via smb_message_echoes
  • App-sent messages are FREE; coexistence numbers are capped at 20 msg/sec
  • Chat history is preserved; template messages and the 24h window still apply

For onboarding, sync, status checks, and webhook payloads, see references/COEXISTENCE.md.

Common Patterns

Send a text message

{
  "messaging_product": "whatsapp",
  "to": "+18091234567",
  "type": "text",
  "text": { "body": "Hello! How can we help you?" }
}

Send a template message

{
  "messaging_product": "whatsapp",
  "to": "+18091234567",
  "type": "template",
  "template": {
    "name": "hello_world",
    "language": { "code": "en_US" }
  }
}

Mark a message as read

{
  "messaging_product": "whatsapp",
  "status": "read",
  "message_id": "wamid.HBgL..."
}

Error Handling

CodeErrorAction
131030Recipient not on WhatsAppValidate number before sending
131047Re-engagement requiredSend a template message first
131050User stopped marketing messagesRespect opt-out, send only service/utility
131056Pair rate limit hitSlow down, implement backoff
130429Rate limit exceededQueue messages, max 80/sec

For full error reference and retry strategies, see references/ERROR-CODES.md.

Best Practices

  1. Always use E.164 phone format+{country}{number}, no spaces or dashes
  2. Verify webhooks — Respond to GET challenge with hub.challenge value
  3. Return 200 immediately on webhook POST — process asynchronously
  4. Store wamid IDs — Needed for replies, reactions, and read receipts
  5. Use template messages to re-engage after the 24h window expires
  6. Handle idempotency — Webhook may deliver the same event multiple times
  7. Check wa_id vs input — The API normalizes phone numbers; wa_id is canonical
  8. Rate limit awareness — 80 msg/sec for Cloud API; implement queue + backoff

References