Install
openclaw skills install whatsapp-gotify-relayUse when operating or extending this WhatsApp Gotify relay as the bridge to OpenClaw. Prefer Unix tools for Docker, logs, Gotify queue checks, webhook validation, and relay smoke tests.
openclaw skills install whatsapp-gotify-relayUse this skill when working on this repository as the WhatsApp bridge for OpenClaw.
This project sits between WhatsApp and OpenClaw.
It does two directions of communication:
OpenClaw posts JSON into the Gotify outbox application:
{
"type": "send",
"to": "+12025550101",
"text": "hello from openclaw"
}
The relay polls that outbox, sends to WhatsApp, deletes the queue item on success, and emits a send_result.
OpenClaw receives webhook JSON from the relay.
Webhook event types:
conversationsend_resultstatusOnly meaningful WhatsApp activity should produce conversation events. History sync, protocol chatter, and other Baileys internals should stay filtered out.
The relay should keep payloads flat and readable.
{
"type": "conversation",
"relay": "whatsapp-gotify-relay",
"direction": "inbound",
"jid": "12025550101@s.whatsapp.net",
"senderJid": "12025550101@s.whatsapp.net",
"pushName": "John",
"timestamp": 1776948451,
"messageId": "ABC123",
"text": "hello",
"contentType": "text"
}
{
"type": "send_result",
"relay": "whatsapp-gotify-relay",
"status": "sent",
"requestId": 5544,
"to": "12025550101@s.whatsapp.net",
"messageId": "3EB0...",
"error": null,
"timestamp": "2026-04-23T12:48:56.415Z"
}
{
"type": "status",
"relay": "whatsapp-gotify-relay",
"connection": "open",
"phase": "connected",
"qr": null,
"statusCode": null,
"details": null,
"timestamp": "2026-04-23T12:48:56.415Z"
}
If WhatsApp remains disconnected, the relay sends a status reminder every 3 hours by default.
The relay runtime env surface is:
PORTAPP_LOG_LEVELWHATSAPP_AUTH_DIRWHATSAPP_PAIRING_NUMBERWHATSAPP_SYNC_FULL_HISTORYGOTIFY_BASE_URLGOTIFY_EVENTS_APP_TOKENGOTIFY_OUTBOX_TOKENGOTIFY_OUTBOX_APPLICATION_IDGOTIFY_POLL_INTERVAL_MSGOTIFY_EVENTS_PRIORITYGOTIFY_RESULTS_PRIORITYWEBHOOK_URLWEBHOOK_BEARER_TOKENWEBHOOK_TIMEOUT_MSWEBHOOK_DISCONNECTED_INTERVAL_MSRELAY_NAMEOn the OpenClaw side, the important configuration concepts are:
Keep the names OpenClaw already uses if they exist. Do not rename OpenClaw env vars just to match the relay.
Prefer Unix tools and simple shell commands:
rgsed -nnpm testdocker compose psdocker compose logs --tail=... connectordocker compose up -d --build connectorcurlgit status --shortnpm test
docker compose up -d --build connector
docker compose logs -f connector
curl -sS "${GOTIFY_BASE_URL}/application/${GOTIFY_OUTBOX_APPLICATION_ID}/message?token=${GOTIFY_OUTBOX_TOKEN}&limit=10"
curl -sS \
-H 'Content-Type: application/json' \
-d '{"title":"smoke-test","message":"{\"type\":\"send\",\"to\":\"447550002572\",\"text\":\"smoke test\"}","priority":5}' \
"${GOTIFY_BASE_URL}/message?token=${GOTIFY_OUTBOX_APP_TOKEN}"
GOTIFY_OUTBOX_APP_TOKEN is an operator-side token for manually writing to the outbox app. It is not required by the relay runtime.
.env.example, README.md, and tests together when the contract changes.