Skip to main content
When users send messages to your WhatsApp Business number, Chirp delivers them to your application via webhooks.

Message Types

You can receive various types of incoming messages:
TypeDescription
textPlain text messages
imageImages with optional captions
videoVideo files
audioVoice messages and audio files
documentPDF, Word, and other document files
stickerWhatsApp stickers
locationShared location pins
contactsShared contact cards (vCard format)
reactionEmoji reactions to your messages
interactiveButton/list selection responses
orderProduct orders (WhatsApp Commerce)
systemSystem events (number changes, identity updates)

Webhook Payload Structure

When you receive a message webhook, the payload follows this structure:
Webhook Payload
{
  "event": "messages.whatsapp.received",
  "timestamp": "2024-01-15T12:00:00.000Z",
  "data": {
    "message": {
      "id": "msg_wa_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "from": "+15559876543",
      "to": "+15551234567",
      "type": "text",
      "direction": "inbound",
      "text": "Hello, I have a question about my order",
      "receivedAt": "2024-01-15T12:00:00.000Z",
      "conversationWindow": {
        "id": "wacw_abc123",
        "originType": "user_initiated",
        "expiresAt": "2024-01-16T12:00:00.000Z"
      }
    },
    "app": {
      "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI"
    }
  }
}

Message Type Payloads

Text Messages

Text Message
{
  "type": "text",
  "text": "Hello, I need help!",
  "context": null
}

Media Messages (Image, Video, Audio, Document)

Image Message
{
  "type": "image",
  "text": null,
  "media": {
    "url": "https://cdn.buildwithchirp.com/media/abc123.jpg",
    "id": "med_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
    "mimeType": "image/jpeg",
    "caption": "Here's a photo of the issue",
    "fileSize": 102400,
    "filename": null,
    "sha256": "a1b2c3d4..."
  }
}

Audio Messages

Audio messages have additional voice note detection:
Voice Note
{
  "type": "audio",
  "audio": {
    "url": "https://cdn.buildwithchirp.com/media/voice123.opus",
    "id": "med_audio123",
    "mimeType": "audio/ogg; codecs=opus",
    "fileSize": 51200,
    "isVoiceNote": true,
    "sha256": "x1y2z3..."
  }
}

Sticker Messages

Sticker Message
{
  "type": "sticker",
  "sticker": {
    "url": "https://cdn.buildwithchirp.com/media/sticker123.webp",
    "id": "med_sticker123",
    "mimeType": "image/webp",
    "fileSize": 25600,
    "isAnimated": false,
    "sha256": "s1t2u3..."
  }
}

Location Messages

Location Message
{
  "type": "location",
  "location": {
    "latitude": "37.7749",
    "longitude": "-122.4194",
    "name": "My Store",
    "address": "123 Main St, San Francisco, CA"
  }
}

Contact Messages

Contacts are shared in vCard format with full structured data:
Contacts Message
{
  "type": "contacts",
  "contacts": {
    "contacts": [
      {
        "name": {
          "formattedName": "John Doe",
          "firstName": "John",
          "lastName": "Doe",
          "middleName": null,
          "prefix": null,
          "suffix": null
        },
        "phones": [
          { "phone": "+15551234567", "type": "CELL", "waId": "15551234567" },
          { "phone": "+15559999999", "type": "WORK", "waId": null }
        ],
        "emails": [
          { "email": "[email protected]", "type": "WORK" }
        ],
        "addresses": [
          {
            "street": "123 Main St",
            "city": "San Francisco",
            "state": "CA",
            "zip": "94105",
            "country": "United States",
            "countryCode": "US",
            "type": "WORK"
          }
        ],
        "org": {
          "company": "Acme Inc",
          "department": "Engineering",
          "title": "Senior Engineer"
        },
        "urls": [
          { "url": "https://example.com", "type": "WORK" }
        ],
        "birthday": "1990-01-15"
      }
    ]
  }
}

Reaction Messages

Reaction Message
{
  "type": "reaction",
  "reaction": {
    "messageId": "wamid.HBgLMTUwMzMwNzk5NzQ...",
    "emoji": "👍"
  }
}
An empty emoji string indicates the user removed their reaction.

Interactive Responses

When users click buttons or select list items:
Button Reply
{
  "type": "interactive",
  "interactive": {
    "type": "button_reply",
    "buttonReply": {
      "id": "support_tech",
      "title": "Technical Help"
    },
    "listReply": null
  }
}
List Reply
{
  "type": "interactive",
  "interactive": {
    "type": "list_reply",
    "buttonReply": null,
    "listReply": {
      "id": "row_option_1",
      "title": "Option 1",
      "description": "First option description"
    }
  }
}

Order Messages (WhatsApp Commerce)

Order Message
{
  "type": "order",
  "order": {
    "catalogId": "1234567890",
    "text": "Please ship to my home address",
    "productItems": [
      {
        "productRetailerId": "sku_123",
        "quantity": "2",
        "itemPrice": "1999",
        "currency": "USD"
      }
    ]
  }
}

System Messages

System messages notify you of account-level events:
Number Change Event
{
  "type": "system",
  "system": {
    "body": "User's phone number has changed",
    "type": "customer_changed_number",
    "identity": null,
    "waId": "15551234567",
    "newWaId": "15559876543"
  }
}

Reply Context

When a user replies to a specific message:
Reply with Context
{
  "type": "text",
  "text": "Yes, that works for me",
  "context": {
    "replyToMessageId": "wamid.HBgLMTUwMzMwNzk5NzQ...",
    "from": "+15551234567"
  }
}

Message Handler Example

Message Handler
function handleWebhook(payload) {
  const { message } = payload.data;

  switch (message.type) {
    case "text":
      handleTextMessage(message);
      break;
    case "image":
    case "video":
    case "audio":
    case "document":
      handleMediaMessage(message);
      break;
    case "sticker":
      handleStickerMessage(message);
      break;
    case "location":
      handleLocationMessage(message);
      break;
    case "contacts":
      handleContactsMessage(message);
      break;
    case "reaction":
      handleReaction(message);
      break;
    case "interactive":
      handleInteractiveResponse(message);
      break;
    case "order":
      handleOrder(message);
      break;
  }
}

function handleTextMessage(message) {
  console.log(`Received from ${message.from}: ${message.text}`);
}

function handleMediaMessage(message) {
  console.log(`Received ${message.type} from ${message.from}`);
  // Download media from message.media.url
}

function handleInteractiveResponse(message) {
  const { interactive } = message;
  if (interactive.type === "button_reply") {
    console.log(`Button selected: ${interactive.buttonReply.id}`);
  } else if (interactive.type === "list_reply") {
    console.log(`List item selected: ${interactive.listReply.id}`);
  }
}

function handleReaction(message) {
  const { reaction } = message;
  if (reaction.emoji) {
    console.log(`User reacted with ${reaction.emoji}`);
  } else {
    console.log(`User removed their reaction`);
  }
}

Replying to Messages

To reply to an incoming message, use the sender’s number as the to field and optionally include replyTo with the message ID:
Reply to Message
curl -X POST https://api.buildwithchirp.com/v1/whatsapp/messages \
  -H "Authorization: Bearer YOUR_APP_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "+15551234567",
    "to": "+15559876543",
    "type": "text",
    "text": {
      "body": "Thanks for reaching out! How can I help?"
    },
    "replyTo": "msg_wa_2DbBs7GWhGvVNJGrDXr5RG0mBWI"
  }'

24-Hour Messaging Window

When a user messages you, you have a 24-hour window to respond with any message type. After this window closes, you must use Template Messages to re-initiate contact.
The conversationWindow object in the webhook payload tells you:
  • expiresAt - When the window closes
  • originType - How the conversation started (user_initiated, business_initiated, referral_conversion)

Best Practices

  1. Respond quickly - Users expect fast responses on WhatsApp
  2. Acknowledge receipt - Send a quick reply or reaction to let users know you received their message
  3. Handle all types - Gracefully handle message types you don’t expect
  4. Download media promptly - Media URLs may expire; download files you need to keep
  5. Track conversations - Store conversation history for context
  6. Use reactions - React to messages with emoji for quick acknowledgment