n8n Node Reference
Exact field-level reference for the two nodes in the @rmyndharis/n8n-nodes-openwa package (v0.3.0): OpenWA (an action node) and OpenWA Trigger (a webhook trigger node). Use it to look up every resource, operation, field, and event, plus the HMAC signature the trigger verifies.
For installation and a first workflow, see the n8n integration guide. For the underlying HTTP API each operation calls, see the API Reference.
Package overview
| Node | n8n type | Direction | Purpose |
|---|---|---|---|
| OpenWA | openWa | Action | Send messages, query contacts, read sessions, manage webhooks |
| OpenWA Trigger | openWaTrigger | Trigger | Start a workflow when a subscribed event arrives |
Both nodes use the openWaApi credential and call your OpenWA server's /api endpoints.
Credential: OpenWA API
Both nodes require an OpenWA API credential with two fields.
| Field | Required | Description |
|---|---|---|
| Server URL | Yes | Base URL with no trailing slash and no /api suffix, for example http://localhost:2785 or https://wa.example.com. The node appends /api/... itself. |
| API Key | Yes | Sent as the X-API-Key header on every request. Get it from your OpenWA dashboard. |
The credential test issues an authenticated GET /api/sessions, so an invalid key fails at save time. To create the key, see Authentication.
OpenWA (action node)
The action node exposes four resources. Select a Resource, then an Operation; the visible fields change with each operation. Most operations take a Session ID (defaults to default); List All does not.
| Resource | Operation | Method + path |
|---|---|---|
| Session | Get Status | GET /api/sessions/{sessionId} |
| Session | List All | GET /api/sessions |
| Message | Send Text | POST /api/sessions/{sessionId}/messages/send-text |
| Message | Send Image | POST /api/sessions/{sessionId}/messages/send-image |
| Message | Send Document | POST /api/sessions/{sessionId}/messages/send-document |
| Message | Send Location | POST /api/sessions/{sessionId}/messages/send-location |
| Contact | Check Exists | GET /api/sessions/{sessionId}/contacts/check/{phoneNumber} |
| Contact | Get Info | GET /api/sessions/{sessionId}/contacts/{contactId} |
| Webhook | Create | POST /api/sessions/{sessionId}/webhooks |
| Webhook | Delete | DELETE /api/sessions/{sessionId}/webhooks/{webhookId} |
The Session ID is sanitized before use: it cannot be empty and cannot contain .., /, or \. A value that violates this fails the item with a clear error rather than building a malformed URL.
Session resource
| Operation | Fields | Notes |
|---|---|---|
| Get Status | Session ID | Returns the status of one session. |
| List All | (none) | Returns every session. Session ID is not used. |
Message resource
All four message operations share two required fields:
| Field | Type | Required | Description |
|---|---|---|---|
| Session ID | string | Yes | The session to send from. Defaults to default. |
| Chat ID | string | Yes | Recipient, for example 628123456789@c.us for a person or ...@g.us for a group. Empty values fail the item. |
The operation-specific fields follow.
Send Text — request body { chatId, text }.
| Field | Type | Required | Maps to |
|---|---|---|---|
| Message | string | Yes | text |
Send Image — choose an Image Source, which decides the remaining fields and the request body.
| Field | Type | Required | Notes |
|---|---|---|---|
| Image Source | options: binary, url, base64 | Yes | Default url. |
| Binary Property | string | Yes (binary) | Name of the binary property holding the image. Default data. |
| Image URL | string | Yes (url) | Public URL of the image. |
| Base64 Data | string | Yes (base64) | Base64-encoded image bytes. |
| MIME Type | string | Yes (base64) | For example image/png. Default image/jpeg. |
| Caption | string | No | Optional caption sent as caption. |
The request body is { chatId } plus the source-specific fields:
- Binary sends
base64(the buffer encoded) andmimetype(read from the binary metadata, falling back toapplication/octet-stream). - URL sends
url. - Base64 sends
base64andmimetype(the MIME Type field).
OpenWA rejects base64 media without a mimetype. The Binary source fills it in from the binary metadata and the URL source needs nothing extra, but the Base64 source requires you to set the MIME Type field.
Send Document — same source model as Send Image, with a filename.
| Field | Type | Required | Notes |
|---|---|---|---|
| Document Source | options: binary, url, base64 | Yes | Default url. |
| Binary Property | string | Yes (binary) | Default data. |
| Document URL | string | Yes (url) | Public URL of the document. |
| Base64 Data | string | Yes (base64) | Base64-encoded document bytes. |
| MIME Type | string | Yes (base64) | For example application/pdf. Default application/pdf. |
| Filename | string | No | Sent as filename. Default document.pdf. |
| Caption | string | No | Sent as caption when set. |
The request body is { chatId, filename } plus base64/mimetype, or url, depending on the source — and caption when provided.
Send Location — request body { chatId, latitude, longitude }.
| Field | Type | Required | Maps to |
|---|---|---|---|
| Latitude | number | Yes | latitude |
| Longitude | number | Yes | longitude |
| Location Name | string | No | Sent as description (OpenWA's field for the location label) when set. |
Contact resource
| Operation | Field | Type | Required | Notes |
|---|---|---|---|---|
| Check Exists | Phone Number | string | Yes | Digits only, for example 628123456789. The node strips +, spaces, -, and (); a value with any non-digit left over fails the item. |
| Get Info | Contact ID | string | Yes | For example 628123456789@c.us. Empty values fail the item. |
Check Exists returns whatsappId, the engine-canonical chat id. It can differ from the number you sent (for example an @lid id), so read the recipient id from the response rather than reconstructing it.
Webhook resource
Use these to register or remove a webhook from a workflow. For an event-driven workflow, prefer the Trigger node, which registers and removes its own webhook automatically.
Create — request body { url, events }, plus secret when set.
| Field | Type | Required | Notes |
|---|---|---|---|
| Webhook URL | string | Yes | Destination that receives event deliveries. |
| Events | multiOptions | Yes | One or more events. At least one must be selected. |
| Webhook Secret | string (password) | No | If set, OpenWA signs each delivery with X-OpenWA-Signature (HMAC-SHA256). Sent as secret. |
Delete — removes a webhook by id.
| Field | Type | Required | Notes |
|---|---|---|---|
| Webhook ID | string | Yes | Id of the webhook to delete. |
A successful DELETE returns 204 No Content; the node surfaces { "success": true } so downstream nodes receive a readable item instead of an empty one.
Output and error handling
On success, each input item produces one output item containing the OpenWA JSON response (or { "success": true } for a deleted webhook).
The node fails the workflow on the first error unless Continue On Fail is enabled, in which case the failing item's output is { "error": "<message>" } and processing continues. Validation problems (empty chat id, non-digit phone number, no event selected, malformed session id) surface as node errors carrying the offending item's index; HTTP failures from OpenWA surface as API errors carrying the server's status and message.
OpenWA Trigger (node)
The trigger node registers a webhook with OpenWA when the workflow activates and starts the workflow each time a subscribed event arrives. It has no input; its single output emits one item per delivery.
Fields
| Field | Type | Required | Notes |
|---|---|---|---|
| Session ID | string | Yes | Session to receive events from. Default default. Sanitized like the action node (no empty, .., /, or \). |
| Events | multiOptions | Yes | Events to subscribe to. Default ['message.received']. At least one is required. |
| Webhook Secret | string (password) | No | Shared secret for signature verification. See Signature verification. |
Webhook lifecycle
The node manages its own OpenWA webhook across activation and deactivation. It stores the returned webhook id in workflow static data and reuses it on later checks.
- On activate, the node verifies any stored webhook still exists with
GET /api/sessions/{sessionId}/webhooks/{webhookId}; if not, it creates one withPOST /api/sessions/{sessionId}/webhooks, sending{ url, events }plussecretwhen a secret is set. The webhook URL is n8n's own callback URL for the node. - On deactivate, the node issues
DELETE /api/sessions/{sessionId}/webhooks/{webhookId}. A404is treated as already deleted; any other error propagates.
The secret is registered with OpenWA only at webhook creation. Changing or clearing it takes effect on the next activation — deactivate and reactivate the workflow to re-register.
Events
The Events field offers the same list in both the trigger and the action node's Webhook → Create operation.
| Event | Fires when |
|---|---|
message.received | A new message is received. |
message.sent | A message is sent successfully. |
message.ack | A message delivery or read acknowledgement occurs. |
message.failed | A message fails to send. |
message.revoked | A message is deleted for everyone. |
message.reaction | A reaction is added to or removed from a message. |
session.status | Any session status change. |
session.qr | A new QR code is generated. |
session.authenticated | The session is authenticated. |
session.disconnected | The session loses connection. |
group.join | Reserved. Accepted on subscribe but not dispatched yet, so it never fires. |
group.leave | Reserved. Accepted on subscribe but not dispatched yet, so it never fires. |
group.update | Reserved. Accepted on subscribe but not dispatched yet, so it never fires. |
group.join, group.leave, and group.update are accepted when you subscribe but OpenWA does not emit them yet, so a trigger subscribed only to those events never runs. Subscribe to a delivered event to receive output.
Output shape
Each delivery is an envelope. The node passes the parsed JSON body straight through, so $json is the envelope and the event-specific payload is under data.
| Field | Description |
|---|---|
event | The event name, for example message.received. |
timestamp | ISO 8601 time the event was emitted, for example 2024-01-15T10:30:00Z. |
sessionId | Session the event belongs to. |
idempotencyKey | Stable key for the logical event. |
deliveryId | Per-delivery id. Repeated across retries of the same delivery. |
data | The event payload. Read message fields from here. |
{
"event": "message.received",
"timestamp": "2024-01-15T10:30:00Z",
"sessionId": "default",
"idempotencyKey": "a1b2c3d4-...",
"deliveryId": "e5f6a7b8-...",
"data": {
"id": "3EB0F5A2B4C...",
"chatId": "628123456789@c.us",
"from": "628123456789@c.us",
"body": "Hello!",
"type": "text",
"timestamp": 1705312200
}
}
Reading the output:
- Reference payload fields through
data, for example{{ $json.data.body }}and{{ $json.data.chatId }}. - Read the message identifier from
data.id. Incoming payloads useid, notmessageId. - OpenWA retries failed deliveries with the same
deliveryId. De-duplicate on it if your downstream actions are not idempotent. - Message
typeis engine-neutral: voice notes arevoice, shared contacts arecontact, and plain chats aretext.
If the request body is missing or not an object, the node emits no items for that delivery rather than failing.
Signature verification
When Webhook Secret is set, OpenWA signs each delivery and the node verifies it before running the workflow. The signature scheme:
- OpenWA computes
HMAC-SHA256(secret, rawBody)over the exact bytes it transmits and sends the result asX-OpenWA-Signature: sha256=<hex>. - The node reads the raw request body — it does not re-serialize the parsed JSON, which could reorder keys or change whitespace and reject a valid delivery — then recomputes the expected
sha256=<hex>and compares. - Comparison uses a constant-time check (
timingSafeEqual). A length mismatch is treated as a non-match before the comparison runs. - Verification returns false when either the secret or the signature header is absent. With a secret configured, a delivery whose signature is missing or wrong is rejected with HTTP 401 and produces no workflow run.
Leave Webhook Secret empty to skip verification and accept unsigned deliveries. For end-to-end webhook setup and the same signature scheme used outside n8n, see Webhooks.
Common errors
| Symptom | Cause | Fix |
|---|---|---|
| Credential test fails on save | API key rejected by GET /api/sessions | Use a valid key from the dashboard; see Authentication. |
Session ID contains invalid characters | Session id has .., /, or \ | Use a plain session id such as default. |
Chat ID cannot be empty | Message sent with no Chat ID | Provide a chat id like 628123456789@c.us. |
Phone number must contain only digits | Check Exists got non-digit input that survived stripping | Pass digits only, for example 628123456789. |
| Base64 image or document rejected by OpenWA | Missing MIME type on a base64 payload | Set the MIME Type field, or use the Binary or URL source. |
400 when creating a webhook with message.reaction | message.reaction needs OpenWA ≥ 0.7.2 | Upgrade the server, or drop that event. |
| Trigger subscribed to a group event never runs | group.* events are reserved and not emitted | Subscribe to a delivered event such as message.received. |
401 Unauthorized on every delivery | Signature mismatch between server and node secrets | Use the same Webhook Secret on both sides; reactivate the workflow after changing it. |
Compatibility
This package targets a self-hosted OpenWA server. The message.reaction event requires OpenWA ≥ 0.7.2; selecting it against an older server returns 400 at webhook creation.
Next steps
- n8n integration guide — install the package and build your first workflow.
- Webhooks — the event payloads and signing scheme behind the Trigger node.
- API Reference — the HTTP endpoints each operation calls.
- Sending messages — payload details for the message operations.