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

Rate Limits

Rate limits protect both the platform and your WhatsApp number — sending too fast is the fastest way to get a number banned. Limits are enforced per Device Key.

Limits

ScopeLimitApplies to
Per device (global)120 requests / minuteEvery authenticated API call for that Device Key
Send burst20 / minutePOST /api/send-message
Group-send burst20 / minutePOST /api/group/send-message
Verify burst20 / minutePOST /api/verify-whatsapp
Tenant API key120 / minuteGET /api/devices/by-api-key

The single-send and verify paths have a tighter 20/min burst ceiling on top of the global 120/min. This stops a script from using single-send as an unpaced bulk channel — for real volume, use bulk send, which runs through a paced, anti-ban queue.

Handling 429

When you exceed a limit you get 429 RATE_LIMITED with a Retry-After header (seconds):

HTTP/1.1 429 Too Many Requests
Retry-After: 12
{ "success": false, "error": { "code": "RATE_LIMITED", "message": "Rate limit exceeded" } }

Back off for the number of seconds in Retry-After, then retry. A simple, robust client:

async function callRapiwa(url, body, key) {
  for (let attempt = 0; attempt < 5; attempt++) {
    const res = await fetch(url, {
      method: 'POST',
      headers: { Authorization: `Bearer ${key}`, 'Content-Type': 'application/json' },
      body: JSON.stringify(body),
    })
    if (res.status !== 429) return res
    const wait = Number(res.headers.get('Retry-After') || 5)
    await new Promise((r) => setTimeout(r, wait * 1000))
  }
  throw new Error('Rate limited: gave up after retries')
}

Best practices

  • Never hammer single-send in a tight loop. Use bulk send for broadcasts — it paces sends for you.
  • Respect Retry-After instead of retrying immediately.
  • Warm up new devices gradually; the engine also enforces warm-up and daily caps behind the scenes.
Last Updated: 7/7/26, 8:31 AM
Prev
Credits & Pricing
Next
Errors