npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@laburen/openclaw-plugin-whatsapp-api

v0.5.0

Published

WhatsApp API channel plugin for OpenClaw

Readme

WhatsApp API Plugin for OpenClaw

WhatsApp Cloud API channel for OpenClaw: your router receives Meta webhooks and forwards them to OpenClaw; replies go straight to the Meta Graph API.

Install

openclaw plugins install @laburen/openclaw-plugin-whatsapp-api

Setup

  1. In Meta for Developers, create or open an app with WhatsApp product enabled and note your Phone number ID and a long-lived System User or Temporary access token with whatsapp_business_messaging (and webhook permissions as required by your setup).
  2. Point Meta’s webhook callback URL to your public HTTPS endpoint (router / reverse proxy). That service should forward the raw POST body to OpenClaw at the path you set as webhookPath (default below).
  3. Set the same verify token / shared secret flow your deployment uses: configure inboundSharedSecret in OpenClaw and send it from your router as the header x-openclaw-shared-secret (recommended).

Via OpenClaw Config

Minimal example — set secrets and IDs (use env-backed config in production; never commit tokens):

openclaw config set channels.whatsapp-api.enabled true
openclaw config set channels.whatsapp-api.inboundSharedSecret "your-internal-secret"
openclaw config set channels.whatsapp-api.outboundPhoneNumberId "123456789012345"
openclaw config set channels.whatsapp-api.outboundAccessToken "EAAG..."

Allow the plugin and enable its entry, then restart the gateway:

openclaw config set plugins.allow '["whatsapp-api"]'
openclaw config set plugins.entries.whatsapp-api.enabled true
openclaw gateway restart

How It Works

  • Registers channel id whatsapp-api and exposes an inbound POST route (default /webhook/whatsapp-api).

  • Parses WhatsApp Cloud API webhook payloads (entry[].changes[].value.messages[]) and sends inbound text into the OpenClaw reply pipeline.

  • Outbound replies are sent directly to Meta:

    https://graph.facebook.com/{apiVersion}/{phoneNumberId}/messages

    with Authorization: Bearer <outboundAccessToken>.

  • Transient failures (429, 5xx, timeouts) are retried according to maxRetries, retryBackoffMs, and requestTimeoutMs.

WhatsApp 24-hour context window (reminder)

WhatsApp Cloud API lets you send session messages (normal replies) only within about 24 hours of the user’s last inbound message. After that window, outbound traffic is limited to approved templates until the user writes again.

This plugin can nudge you before the window closes:

  1. Snapshot on inbound: For each user message handled by the channel, a hook writes <OpenClaw state dir>/whatsapp-api/last-inbound-message.json with from, content, timestamp, channel/account/conversation ids when present, and notified: false. That reset means a new user message clears any previous “we already warned” state.
  2. Cron from the host: On service start, the plugin runs setup.sh (shipped under src/scripts/ in the npm package). The script registers an OpenClaw cron job that periodically invokes check.sh via the exec tool (see the job’s description in setup.sh).
  3. check.sh behavior: It reads the JSON file, skips if missing or notified is already true, and compares elapsed time since timestamp to a threshold (default 23 hours). If the threshold is met, it runs openclaw message send to the user’s phone (parsed from from) with a configurable warning text, then sets notified: true in the same file so the warning is not sent again until the next inbound message.

Useful environment variables for the scripts: OPENCLAW_DIR (defaults to /home/<user>/.openclaw), THRESHOLD_MINUTES, WARNING_MESSAGE, and EVERY for the cron interval when installing (default 30m). To remove the job: bash /path/to/node_modules/@laburen/openclaw-plugin-whatsapp-api/src/scripts/setup.sh --uninstall (adjust path to your install).

Inbound webhook (from your router to OpenClaw)

| Item | Detail | |------|--------| | Method | POST | | Path | Value of webhookPath | | Header (recommended) | x-openclaw-shared-secret: <inboundSharedSecret> | | Body | Raw WhatsApp Cloud webhook JSON forwarded by your router |

Responses: 403 if the shared secret does not match, 400 if the payload is invalid, 200 when accepted (processing continues asynchronously after ACK).

Configuration

{
  "plugins": {
    "allow": ["whatsapp-api"],
    "entries": {
      "whatsapp-api": {
        "enabled": true
      }
    }
  },
  "channels": {
    "whatsapp-api": {
      "enabled": true,
      "webhookPath": "/webhook/whatsapp-api",
      "inboundSharedSecret": "replace-with-internal-secret",
      "outboundPhoneNumberId": "123456789012345",
      "outboundAccessToken": "EAAG...",
      "outboundApiVersion": "v22.0",
      "requestTimeoutMs": 10000,
      "maxRetries": 2,
      "retryBackoffMs": 500,
      "dedupeTtlMs": 300000,
      "maxBodyBytes": 524288,
      "accounts": {
        "default": {
          "enabled": true
        }
      }
    }
  }
}

| Option | Description | Default | |--------|-------------|---------| | plugins.entries.whatsapp-api.enabled | Turn the plugin on or off | — | | channels.whatsapp-api.enabled | Turn the channel on or off | — | | webhookPath | HTTP path OpenClaw listens on for inbound webhooks | /webhook/whatsapp-api | | inboundSharedSecret | Secret your router must send (e.g. header x-openclaw-shared-secret) | — | | outboundPhoneNumberId | WhatsApp Phone number ID from Meta | — | | outboundAccessToken | Bearer token for Graph API sends | — | | outboundApiVersion | Graph API version segment in the URL | e.g. v22.0 | | requestTimeoutMs | HTTP timeout for outbound calls (ms) | 10000 | | maxRetries | Retries on transient errors | 2 | | retryBackoffMs | Base backoff between retries (ms) | 500 | | dedupeTtlMs | Deduplication window for inbound events (ms) | 300000 | | maxBodyBytes | Max accepted webhook body size (bytes) | 524288 | | accounts | Per-account overrides (multi-tenant); keys are account ids | { "default": { "enabled": true } } |

Per-account fields can override phone id, token, retries, etc. under channels["whatsapp-api"].accounts.<accountId>.

Notes

  • Outbound mode is direct-to-Meta only (no third-party relay in this plugin).
  • Keep tokens out of logs and rotate them on a schedule.

Links