Rapiwa API
Guide
Sessions
Messages
Groups
Webhooks
Pricing
  • Website
  • Dashboard
  • Support
Guide
Sessions
Messages
Groups
Webhooks
Pricing
  • Website
  • Dashboard
  • Support
  • Getting Started

    • Getting Started
    • Authentication
    • Credits & Pricing
    • Rate Limits
    • Errors
  • Sessions & Devices

    • Link a Device (QR)
    • Get Session Info
    • Validate a Device Key
    • Log Out
    • List All Devices
  • Messages

    • Send a Message
    • Send Bulk Messages
    • Delete a Message
    • Check a Number on WhatsApp
  • Groups

    • Create a Group
    • List Groups
    • Get Group Metadata
    • Get Invite Link
    • Add Members
    • Join a Group
    • Leave a Group
    • Delete a Group
    • Send to a Group
  • Webhooks & Integrations

    • Inbound Messages Webhook
    • Delivery Status Webhook
    • n8n & Integrations
  • Reference

    • Pricing Catalog

Inbound Messages Webhook

When someone messages your linked WhatsApp number, Rapiwa POSTs the message to the Webhook URL you set on the device (in the dashboard). This is how you build bots, auto-replies, and inbox integrations.

  • Direction: Rapiwa → your server
  • Method: POST with a JSON body
  • Configure: set the device's Webhook URL in the dashboard
  • Reliability: deliveries retry with backoff on failure

Payload — receive-message

{
  "session_id": "1024",
  "from": "8801234567890@s.whatsapp.net",
  "contact_id": "8801234567890",
  "name": "Sender Name",
  "message_id": "3EB0A1B2C3…",
  "message_type": "text",
  "message": "Hi, is this available?",
  "timestamp": "1755923552",
  "media_info": []
}
FieldDescription
session_idThe device that received the message
fromSender JID
contact_idSender's phone number (digits only)
nameSender's WhatsApp display name
message_idMessage id — pass to delete / quote when you reply
message_typetext · image · video · audio · document · location · interactive · sticker
messageBody / caption. For location, a https://www.google.com/maps?q=lat,lng URL
timestampUnix seconds (string)
media_infoSee below

media_info

Message typemedia_info shape
Text[] (empty)
Media (image/video/audio/document){ "mimetype": "...", "fileName": "...", "file_url": "https://…" }
Location{ "latitude": 37.77, "longitude": -122.41 }

For media, Rapiwa downloads the file, stores it, and gives you a public file_url — you don't need to fetch it from WhatsApp yourself.

Responding

Reply by calling POST /api/send-message with the sender's number. To thread the reply, pass the inbound message_id as quoted_message_id.

// Express example
app.post('/rapiwa/webhook', async (req, res) => {
  const { contact_id, message, message_id } = req.body
  res.sendStatus(200) // ack fast

  if (/price/i.test(message)) {
    await fetch('https://app.rapiwa.com/api/send-message', {
      method: 'POST',
      headers: { Authorization: `Bearer ${DEVICE_KEY}`, 'Content-Type': 'application/json' },
      body: JSON.stringify({
        number: contact_id,
        message_type: 'text',
        message: 'Our price list: https://example.com/pricing',
        quoted_message_id: message_id,
      }),
    })
  }
})

Verifying deliveries (recommended)

Legacy webhooks are unsigned. Rapiwa can additionally send an X-Rapiwa-Signature header — an HMAC of the raw request body — so you can confirm a delivery really came from Rapiwa. Compute the same HMAC with your webhook secret and compare. Keep accepting unsigned bodies only if you must support older setups.

Ack quickly

Return 200 as soon as you've received the payload, then do slow work (DB writes, replies) asynchronously. Non-200 responses cause Rapiwa to retry.

Delivery gating

Inbound delivery requires your tenant wallet balance to be above the minimum. If the balance is too low, delivery is paused until you top up — see Credits.

Last Updated: 7/7/26, 8:31 AM
Next
Delivery Status Webhook