Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ This repository provides:
| ------ | ----------- | ------- | ------ |
| [`after-hours`](./after-hours) | Auto-replies with a configurable away/closing message to messages received outside business hours. | 0.1.3 | stable |
| [`chat-flow`](./chat-flow) | Interactive, stateful auto-reply: a trigger word starts a greeting + numbered menu, replies traverse a configurable menu tree, and per-chat state expires after 15 minutes. | 1.0.6 | stable |
| [`chatwoot-adapter`](./chatwoot-adapter) | Two-way sync between a WhatsApp session and a Chatwoot inbox: relays WhatsApp messages (1:1 and groups, with media) into Chatwoot as an API-channel inbox, sends agent replies back to WhatsApp, and hands a chat over to a human agent — silencing other OpenWA bots — when an agent takes it in Chatwoot. First consumer of the OpenWA Integration SDK v1; runs sandboxed in the plugin worker. | 0.5.2 | beta |
| [`chatwoot-adapter`](./chatwoot-adapter) | Two-way sync between a WhatsApp session and a Chatwoot inbox: relays WhatsApp messages (1:1 and groups, with media) into Chatwoot as an API-channel inbox, sends agent replies back to WhatsApp, and hands a chat over to a human agent — silencing other OpenWA bots — when an agent takes it in Chatwoot. First consumer of the OpenWA Integration SDK v1; runs sandboxed in the plugin worker. | 0.5.3 | beta |
| [`faq-bot`](./faq-bot) | Auto-replies to inbound WhatsApp messages from configurable FAQ keyword/regex rules. | 0.1.7 | stable |
| [`group-translate`](./group-translate) | Auto-translates group messages between participants' languages via a LibreTranslate backend. Configure in-chat with /tr commands. Admin-gated; disabled until enabled. | 1.0.6 | stable |
| [`gsheets-logger`](./gsheets-logger) | Logs WhatsApp message events to a Google Sheet via a service account. | 0.2.3 | stable |
Expand Down
14 changes: 14 additions & 0 deletions chatwoot-adapter/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,20 @@ All notable changes to the Chatwoot Adapter plugin are documented here. The form

## [Unreleased]

## [0.5.3] — 2026-07-20

### Fixed

- **Setup guide no longer prescribes a mint path that can never verify webhooks**
([OpenWA #821](https://github.com/rmyndharis/OpenWA/issues/821)). It previously told you to mint the
instance from the dashboard and "paste the Chatwoot webhook secret" there — but the dashboard's
instance form has no secret field and auto-generates one, which can never match Chatwoot's, so every
Chatwoot → OpenWA delivery failed HMAC verification with a 401 while inbound (which uses the API
token, not the webhook secret) kept working. Setup now mints via the REST API (the only path that
accepts a secret), states the concrete minimum Chatwoot version (v4.12.0, the first release with
per-webhook secrets + timestamped webhook signatures), and a new Troubleshooting section maps the 401
symptom to its causes. Documentation only — no runtime code changed.

## [0.5.2] — 2026-07-04

### Fixed
Expand Down
61 changes: 53 additions & 8 deletions chatwoot-adapter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
| Field | Value |
| ----- | ----- |
| **Identifier** | `chatwoot-adapter` |
| **Version** | 0.5.2 |
| **Released** | 2026-07-04 |
| **Version** | 0.5.3 |
| **Released** | 2026-07-20 |
| **Status** | beta |
| **Author** | Yudhi Armyndharis |
| **License** | MIT |
Expand Down Expand Up @@ -47,16 +47,44 @@ sees it.

## Setup

> **Chatwoot version:** the adapter verifies the webhook signature, so you need a Chatwoot version that
> HMAC-signs **account-level** webhooks with a timestamp (an `X-Chatwoot-Timestamp` header). Agent-bot / inbox
> webhooks are unsigned and are **not** supported — use an account-level webhook (Integrations → Webhooks).
> **Chatwoot version:** you need Chatwoot **v4.12.0 or newer** — the first release whose account-level
> webhooks carry a per-webhook secret and a timestamped HMAC signature (`X-Chatwoot-Signature` +
> `X-Chatwoot-Timestamp`). Older releases send unsigned webhooks, which OpenWA rejects with a 401.
> Agent-bot / inbox webhooks are **not** supported — use an account-level webhook (Integrations → Webhooks).

1. **Chatwoot — API-channel inbox.** Create an API-channel inbox and note its **inbox ID**.
2. **Chatwoot — account-level webhook.** Integrations → Webhooks → add a webhook subscribed to
`message_created` and `conversation_updated`; copy the webhook **secret** shown on the edit form.
3. **OpenWA — mint an instance.** In the dashboard's Instances tab for this plugin: set the **session scope**,
paste the Chatwoot webhook **secret**, and fill the config (`baseUrl`, `apiToken`, `accountId`, `inboxId`).
Copy the **ingress URL** it shows: `{BASE_URL}/api/ingress/chatwoot-adapter/{instanceId}/chatwoot`.
Chatwoot generates this secret itself and won't accept a custom one — so it must be copied **into**
OpenWA (the reverse direction is impossible).
3. **OpenWA — mint an instance with that secret.** OpenWA verifies every webhook delivery against the
instance's ingress secret, so it must equal the Chatwoot secret from step 2. Mint via the REST API
(the only path that accepts a secret today):

```bash
curl -X POST "$OPENWA/api/integration/plugins/chatwoot-adapter/instances" \
-H "X-API-Key: $ADMIN_KEY" -H "Content-Type: application/json" \
-d '{
"instanceId": "main",
"sessionScope": "<your-whatsapp-session-id>",
"secret": "<chatwoot webhook secret from step 2>",
"config": {
"baseUrl": "https://chatwoot.example.com",
"apiToken": "<chatwoot access token>",
"accountId": 2,
"inboxId": 8
}
}'
```

The response reveals the **ingress URL** (once):
`{BASE_URL}/api/ingress/chatwoot-adapter/{instanceId}/chatwoot`.

> ⚠️ **Do not mint the instance from the dashboard**: its instance form has no secret field and
> auto-generates a random one that can never match Chatwoot's — every agent reply then fails with a
> 401 (see [Troubleshooting](#troubleshooting)). If you already did, delete the instance and re-mint
> via the API above; an instance's secret cannot be edited after minting (only regenerated to a new
> random one).
4. **Chatwoot — set the webhook URL** to the ingress URL from step 3.

## Install
Expand Down Expand Up @@ -103,6 +131,23 @@ public host is added to the outbound allowlist). To use a self-hosted Chatwoot:
the limit (e.g. nginx `client_max_body_size`, or your tunnel's max request size). Oversized inbound media that
the engine already dropped for size is relayed as a short placeholder instead of an empty message.

## Troubleshooting

**Inbound works (WhatsApp messages reach Chatwoot), but agent replies never reach WhatsApp and the
Chatwoot logs show `WebhookJob ... 401 Unauthorized`.** OpenWA rejected the webhook's HMAC signature.
Work down this list:

| Cause | Check | Fix |
| --- | --- | --- |
| The instance's ingress secret ≠ the Chatwoot webhook secret (by far the most common — every instance minted from the dashboard has an auto-generated secret that can't match Chatwoot's) | Compare the secret on the Chatwoot webhook edit form with the one the instance was minted with | Delete the instance and re-mint via the REST API with `secret` = the Chatwoot webhook secret (Setup step 3) |
| The Chatwoot webhook was re-created (or its secret reset) after the instance was minted | Same as above | Re-mint the instance with the new secret |
| Clock skew beyond the 300-second signature tolerance | Compare `date -u` on the Chatwoot and OpenWA hosts | Sync both hosts with NTP |
| Chatwoot older than v4.12.0 | Its account webhooks are unsigned | Upgrade Chatwoot |

Inbound is unaffected by all of these because it authenticates to Chatwoot's REST API with the
`apiToken`, not through the webhook. A **404** (instead of 401) means the URL itself is wrong — unknown
instance id or route — so re-copy the ingress URL from the mint response.

## Compatibility

- **OpenWA** ≥ 0.8.7 — needs Integration SDK v1 (webhook ingress, `ctx.mappings`, the session+chat handover
Expand Down
2 changes: 1 addition & 1 deletion chatwoot-adapter/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "chatwoot-adapter",
"name": "Chatwoot Adapter",
"version": "0.5.2",
"version": "0.5.3",
"type": "extension",
"main": "dist/index.js",
"description": "Two-way sync between a WhatsApp session and a Chatwoot inbox: relays WhatsApp messages (1:1 and groups, with media) into Chatwoot as an API-channel inbox, sends agent replies back to WhatsApp, and hands a chat over to a human agent — silencing other OpenWA bots — when an agent takes it in Chatwoot. First consumer of the OpenWA Integration SDK v1; runs sandboxed in the plugin worker.",
Expand Down
6 changes: 3 additions & 3 deletions plugins.json
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@
{
"id": "chatwoot-adapter",
"name": "Chatwoot Adapter",
"version": "0.5.2",
"version": "0.5.3",
"type": "extension",
"status": "beta",
"description": "Two-way sync between a WhatsApp session and a Chatwoot inbox: relays WhatsApp messages (1:1 and groups, with media) into Chatwoot as an API-channel inbox, sends agent replies back to WhatsApp, and hands a chat over to a human agent — silencing other OpenWA bots — when an agent takes it in Chatwoot. First consumer of the OpenWA Integration SDK v1; runs sandboxed in the plugin worker.",
Expand All @@ -387,11 +387,11 @@
],
"minOpenWAVersion": "0.8.7",
"testedOpenWAVersion": "0.8.7",
"releasedAt": "2026-07-04",
"releasedAt": "2026-07-20",
"repoPath": "chatwoot-adapter",
"repoUrl": "https://github.com/rmyndharis/OpenWA-plugins",
"homepage": "https://github.com/rmyndharis/OpenWA-plugins/tree/main/chatwoot-adapter",
"download": "https://github.com/rmyndharis/OpenWA-plugins/releases/download/chatwoot-adapter-v0.5.2/chatwoot-adapter.zip"
"download": "https://github.com/rmyndharis/OpenWA-plugins/releases/download/chatwoot-adapter-v0.5.3/chatwoot-adapter.zip"
},
{
"id": "faq-bot",
Expand Down
Loading