Connecting n8n to OpenWA — First Integration
The Setup
n8n and OpenWA run on the same machine. OpenWA is localhost-only — it never needs a public URL. n8n is the only service that needs to be reachable: either via your Cloudflare Tunnel domain or locally at http://localhost:5678.
OpenWA reaches n8n at the webhook URL you register in its dashboard. This URL must be publicly accessible — it cannot be localhost. Options:
The n8n → OpenWA direction (n8n sends messages via HTTP Request to localhost:2785) always works locally regardless of how n8n is exposed.
Step 1: Add the OpenWA Credential in n8n
Open n8n at your domain — for example: https://n8n.yourdomain.com
1. Click Credentials in the left sidebar
2. Click Add Credential
3. Search for and select HTTP Header Auth
4. Name it: OpenWA API
5. Under Headers, click Add Header:
- Name: X-API-Key
- Value: (your key)
Finding the API key:
sudo docker exec openwa-api cat /app/data/.api-key
Not sure where this key comes from? See OpenWA data volume — the API key file.
Step 2: Send a Text Message
Create a new workflow. Add a Manual Trigger.
Add an HTTP Request node:
http://localhost:2785/api/send/text
{
"session": "default",
"to": "+1XXXXXXXXXX",
"text": "Hello from n8n"
}
Replace +1XXXXXXXXXX with a real phone number in international format (no spaces, no dashes, with country code).
Click Test Step. If the WhatsApp session is "ready", the message sends immediately.
Common errors:
401 Unauthorized — API key is wrong or not set in the credential404 Not Found — session name "default" does not exist (create one in the OpenWA dashboard first)403 Forbidden — the session exists but is not in "ready" state500 — WhatsApp rejected the message (rate limit, recipient blocked, or session revoked)Step 3: Send a Media Message
Same HTTP Request node. Change the URL and body:
http://localhost:2785/api/send/media
{
"session": "default",
"to": "+1XXXXXXXXXX",
"mediaType": "image",
"mediaUrl": "https://example.com/image.jpg",
"caption": "Look at this"
}
OpenWA fetches the media URL server-side, stores it in the media directory, and attaches it to the WhatsApp message.
Step 4: Trigger a Workflow on Incoming Messages
In the OpenWA dashboard at http://localhost:2785:
1. Go to Webhooks → Add Webhook
2. URL: https://n8n.yourdomain.com/webhook/wa-incoming
3. Events: Select "message.received"
4. Save
Now set up the n8n side. Create a new workflow with a Webhook node:
wa-incoming{ "received": true }Test it: send a WhatsApp message from your phone to the connected WhatsApp account. Within seconds, n8n receives the payload.
The incoming webhook payload looks like:
{
"event": "message.received",
"session": "default",
"message": {
"id": "false_91XXXXXXXXXX_XXXXXXXXXX",
"from": "+1XXXXXXXXXX",
"fromMe": false,
"text": "Hello",
"timestamp": 1719000000,
"mediaType": null
}
}
Step 5: Reply to an Incoming Message
The webhook receives the message. Use the sender phone to reply.
Add a Telegram node, Discord node, or another OpenWA HTTP Request node in the same workflow.
For an auto-reply via OpenWA:
http://localhost:2785/api/send/text
{
"session": "default",
"to": "{{ $json.message.from }}",
"text": "Got your message! We'll get back to you shortly."
}
The {{ $json.message.from }} is n8n's expression syntax — it reads the from field from the incoming webhook JSON and substitutes the sender's phone number as the reply target.
Putting It Together: A Simple Auto-Reply Bot
Trigger: Webhook (wa-incoming)
↓
Switch: {{ $json.message.text.toLowerCase() }}
- contains "order" → HTTP Request (send order confirmation template)
- contains "help" → HTTP Request (send help text)
- default → HTTP Request (generic reply)
↓
End
Or connect the Switch branches to an AI node:
Switch → AI Agent (Claude) → HTTP Request (send via OpenWA)
For full AI chat, group bots, and keyword routing — see the workflow varieties post.
Session Management from n8n
Beyond sending messages, the full OpenWA API is accessible:
POST /api/sessions/:id/start — start a sessionPOST /api/sessions/:id/stop — stop a sessionGET /api/sessions/:id/qr — get current QR code as base64POST /api/sessions/:id/restart — restart Chromium without losing the session auth stateRate Limiting
OpenWA applies rate limiting per API key:
RATE_LIMIT_MEDIUM_TTL=60000 — 60 second windowRATE_LIMIT_MEDIUM_LIMIT=100 — 100 requests per window100 requests per minute is generous for personal use. WhatsApp's own rate limits are stricter — around 20-30 messages per minute for a standard WhatsApp account.
For bulk sending, space messages with a Delay node in n8n: 3 seconds between each message → Loop over contact list.
Series: ← OpenWA data volume backup | Next: Workflow varieties →
Related Posts
Built something similar or want to talk through the architecture? Get in touch.