# Pull Request Template
## Description
This PR adds support for WhatsApp campaigns to Chatwoot, allowing
businesses to reach their customers through WhatsApp. The implementation
includes backend support for WhatsApp template messages, frontend UI
components, and integration with the existing campaign system.
Fixes#8465
Fixes https://linear.app/chatwoot/issue/CW-3390/whatsapp-campaigns
## Type of change
- [x] New feature (non-breaking change which adds functionality)
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] Breaking change (fix or feature that would cause existing
functionality not to work as expected)
- [ ] This change requires a documentation update
## How Has This Been Tested?
- Tested WhatsApp campaign creation UI flow
- Verified backend API endpoints for campaign creation
- Tested campaign service integration with WhatsApp templates
- Validated proper filtering of WhatsApp campaigns in the store
## Checklist:
- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules
## What we have changed:
We have added support for WhatsApp campaigns as requested in the
discussion.
Ref: https://github.com/orgs/chatwoot/discussions/8465
**Note:** This implementation doesn't exactly match the maintainer's
specification and variable support is missing. This is an initial
implementation that provides the core WhatsApp campaign functionality.
### Changes included:
**Backend:**
- Added `template_params` column to campaigns table (migration + schema)
- Created `Whatsapp::OneoffCampaignService` for WhatsApp campaign
execution
- Updated campaign model to support WhatsApp inbox types
- Added template_params support to campaign controller and API
**Frontend:**
- Added WhatsApp campaign page, dialog, and form components
- Updated campaign store to filter WhatsApp campaigns separately
- Added WhatsApp-specific routes and empty state
- Updated i18n translations for WhatsApp campaigns
- Modified sidebar to include WhatsApp campaigns navigation
This provides a foundation for WhatsApp campaigns that can be extended
with variable support and other enhancements in future iterations.
---------
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
## Description
This PR introduces WhatsApp Embedded Signup functionality, enabling
users to connect their WhatsApp Business accounts through Meta's
streamlined OAuth flow without manual webhook configuration. This
significantly improves the user experience by automating the entire
setup process.
**Key Features:**
- Embedded signup flow using Facebook SDK and Meta's OAuth 2.0
- Automatic webhook registration and phone number configuration
- Enhanced provider selection UI with card-based design
- Real-time progress tracking during signup process
- Comprehensive error handling and user feedback
## Required Configuration
The following environment variables must be configured by administrators
before this feature can be used:
Super Admin Configuration (via
super_admin/app_config?config=whatsapp_embedded)
- `WHATSAPP_APP_ID`: The Facebook App ID for WhatsApp Business API
integration
- `WHATSAPP_CONFIGURATION_ID`: The Configuration ID for WhatsApp
Embedded Signup flow (obtained from Meta Developer Portal)
- `WHATSAPP_APP_SECRET`: The App Secret for WhatsApp Embedded Signup
flow (required for token exchange)

## How Has This Been Tested?
#### Backend Tests (RSpec):
- Authentication validation for embedded signup endpoints
- Authorization code validation and error handling
- Missing business parameter validation
- Proper response format for configuration endpoint
- Unauthorized access prevention
#### Manual Test Cases:
- Complete embedded signup flow (happy path)
- Provider selection UI navigation
- Facebook authentication popup handling
- Error scenarios (cancelled auth, invalid business data, API failures)
- Configuration presence/absence behavior
## Related Screenshots:





Fixes
https://linear.app/chatwoot/issue/CW-2131/spec-for-whatsapp-cloud-channels-sign-in-with-facebook
---------
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Co-authored-by: iamsivin <iamsivin@gmail.com>
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Co-authored-by: Sojan Jose <sojan@pepalo.com>
All migrations will automatically be wrapped in a transaction. There are
queries that you can’t execute inside a transaction. Adding index
concurrently is one of them, we have to disable the transaction. I
missed this in the earlier PR. #11831
This PR adds a composite index (:account_id, :content_type, :created_at)
on the table messages.
This index is added as a temporary fix for performance issues in the
CSAT responses controller where we query messages with account_id,
content_type and created_at. The current implementation
(account.message.input_csat.count) times out with millions of messages.
TODO: Create a dedicated csat_survey table and add entries when surveys
are sent, then query this table instead of the entire messages table for
better performance.
This PR introduces a new channel type for voice conversations.
ref: #11481
## Changes
- Add database migration for channel_voice table with phone_number and
provider_config
- Create Channel::Voice model with E.164 phone number validation and
Twilio config validation
- Add voice channel association to Account model
- Extend inbox helpers and types to support voice channels
- Add voice channel setup UI with Twilio configuration form
- Include voice channel in channel factory and list components
- Add API routes and store actions for voice channel creation
- Add comprehensive translations for voice channel management
---------
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
Co-authored-by: iamsivin <iamsivin@gmail.com>
- Add API support for creating a thread
- Add API support for creating a message
- Remove uuid from thread (no longer required, we will use existing
websocket connection to send messages)
- Update message_type to a column (user, assistant, assistant_thinking)
# Pull Request Template
## Description
This PR introduces basic customization options for the CSAT survey:
* **Display Type**: Option to use star ratings instead of emojis.
* **Message Text**: Customize the survey message (up to 200 characters).
* **Survey Rules**: Send surveys based on labels — trigger when a
conversation has or doesn't have a specific label.
Fixes
https://linear.app/chatwoot/document/improve-csat-responses-a61cf30e054e
## Type of change
- [x] New feature (non-breaking change which adds functionality)
## How Has This Been Tested?
### Loom videos
**Website Channel (Widget)**
https://www.loom.com/share/7f47836cde7940ae9d17b7997d060a18?sid=aad2ad0a-140a-4a09-8829-e01fa2e102c5
**Email Channel (Survey link)**
https://www.loom.com/share/e92f4c4c0f73417ba300a25885e093ce?sid=4bb006f0-1c2a-4352-a232-8bf684e3d757
## Checklist:
- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules
---------
Co-authored-by: Pranav <pranavrajs@gmail.com>
The agents can see the previous conversations with the copilot if needed
with this change. We would have to cleanup the data after a while. For
now, that is not considered.
This PR adds:
- A new model for copilot_threads (intentionally named thread instead of
conversation to avoid confusion), copilot_messages
- Add the controller to fetch previous threads and messages.
### Summary
- Converts conversation auto-resolution duration from days to minutes
for more
granular control
- Updates validation to allow values from 10 minutes (minimum) to 999
days (maximum)
- Implements smart messaging to show appropriate time units in activity
messages
### Changes
- Created migration to convert existing durations from days to minutes
(x1440)
- Updated conversation resolver to use minutes instead of days
- Added dynamic translation key selection based on duration value
- Updated related specs and documentation
- Added support for displaying durations in days, hours, or minutes
based on value
### Test plan
- Verify account validation accepts new minute-based ranges
- Confirm existing account settings are correctly migrated
- Test auto-resolution works properly with minute values
- Ensure proper time unit display in activity messages
---------
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
- Updates ACCOUNT_LEVEL_FEATURE_DEFAULTS installation config to enable
chatwoot_v4
- Enables chatwoot_v4 for all existing accounts in batches of 100
- Clears GlobalConfig cache after update
- Add agent bots management UI in settings with avatar upload
- Enable agent bot configuration for all inbox types
- Implement proper CRUD operations with webhook URL support
- Fix agent bots menu item visibility in settings sidebar
- Remove all CSML-related code and features
- Add migration to convert existing CSML bots to webhook bots
- Simplify agent bot model and services to focus on webhook bots
- Improve UI to differentiate between system bots and account bots
## Video
https://github.com/user-attachments/assets/3f4edbb7-b758-468c-8dd6-a9537b983f7d
---------
Co-authored-by: iamsivin <iamsivin@gmail.com>
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
Co-authored-by: Pranav <pranav@chatwoot.com>
* feat: baileys provider and placeholder for link device modal
* chore: drop qrcode.vue in favor of just img tag
* chore: update modal props
* feat: setup channel provider connection
* chore: update .env.example with Baileys API default configuration
* feat: add support for Baileys provider in WhatsApp events processing
* chore: rename Baileys API default host variable to DEFAULT_BAILEYS_URL
* feat: add setup and disconnect methods for Baileys channel provider in inboxes controller that will be implemented
* feat: add CHANNEL_CONNECTION_UPDATE event and include it in broadcast data preparation
* refactor: simplify channel retrieval logic in WhatsappEventsJob
* refactor: revert CHANNEL_UPDATE_EVENTS constant from ActionCableBroadcastJob
* feat: add 'baileys' as a provider option in Whatsapp channel model
* feat: add provider_connection field to Whatsapp channel model and migration
* refactor: remove unnecessary CHANNEL_CONNECTION_UPDATE event type
* feat: implement channel provider connection with baileys API
* feat: add inbox association to Whatsapp channel model and update webhook URL handling
* feat: enhance Baileys service to handle webhook multiple event types
* refactor: simplify webhook verification logic in Baileys service
* feat: add setup channel provider call, and refactor some logic
* chore: adapt logic to new API
* refactor: fix typo
* refactor: fix import
* refactor: fix typo
* chore: add fixme comment about race condition
* fix: remove double disconnect call
* feat: implement message processing for incoming WhatsApp messages
* refactor: streamline message type determination and improve readability
* chore: increase cache key granularity
provider connection info might be updated multiple times within 1 second, so updates might be lost due to cache key not being updated. changing cache key to milliseconds solves this
* feat: add `is-loading` to buttons
* feat: update send_message method to use 'to' parameter and improve error handling
* refactor: simplify test setup and update API key in specs
* chore: add setup and disconnect channel provider specs
* test: fix spec after increase cache key granularity
* feat: handle reconnecting state on modal
* style: centered error text
* feat: advanced options on create inbox
* feat: handle new reconnecting on backend
* refactor: update inbox controller specs and leave a FIXME note
* test: add specs for Whatsapp::IncomingMessageBaileysService
* feat: add baileys configuration page
* feat: link device button when disconnected on conversation
* chore: refactor .env.example
* feat: add TODO for unimplemented methods in IncomingMessageBaileysService
* fix: correct method name and update environment variable references in WhatsappBaileysService
* refactor: simplify channel lookup by removing redundant method and handling phone number check directly
* chore: add TODO for unimplemented event processing methods in IncomingMessageBaileysService
* fix: update environment variable references in WhatsappBaileysService tests
* chore(webhook): add pt-BR translations
* chore: add pt-br translations
* chore: inboxname component margin
* refactor: inboxname computed prop
* feat: enhance WhatsApp provider connection handling and message processing
* test: inbox controller
* chore: improve baileys connection and messages handling
* test: incoming message service baileys
* refactor: update provider config validation and improve test setup for WhatsApp Baileys service
* fix: ensure only text messages are sent and update message source ID
* fix: create message
* fix: only update message on success
* test: fix broken specs
* chore: raise error on unsupported message content type
* feat: hide provider connection data from non-admins
* fix: update advanced options
* chore: move class definition
* fix: issue with send_message not returning id
---------
Co-authored-by: gabrieljablonski <contact@gabrieljablonski.com>
* chore: lint files
* chore: suppress warning
* chore: disable suggest extensions
* chore: do not stage changes in pre-commit
* chore: remove git add from FE lint and `-a` flag from rubocop on husky
* feat(migration): add name column to webhook table
* feat(webhooks): add name parameter to webhook params
* feat(webhooks): add example webhook name constant and input field to form
* fix(webhooks): add webhook name label and placeholder to multiple locales in the form
* feat(webhooks): display webhook name in the UI and include it in the API response
* Revert 'fix(webhooks): add webhook name label and placeholder to multiple locales in the form'
This reverts commit e547778a1c038c934e22ceb25935f541cb09e2cd.
* test(webhooks): add tests for creating and updating webhooks with name attribute
* chore(webhooks): add name property to webhook definitions in Swagger documentation
* chore(webhooks): remove unnecessary input touch event for webhook name field
* chore(webhooks): apply review changes requested
* chore(webhooks): revert auto lint changes in commit 18ec4cafeb72fd385b70f65f1873d7cfb65216a6
- Removes the portal_members table and all associated records
- Updates policies to use custom roles with knowledge_base_manage
permission
- Updates controllers, models, and views to work without portal
membership
- Adds tests for the new permission model
The UI displays only six articles, and this update introduces a per_page
parameter to control the number of articles returned per API call. The
value is capped between 1 and 100, with a default fallback if a lower
number is set.
This change is necessary due to high website traffic, where excessive
payloads are returned without adding value.
**Changes:**
- Add index to status, account_id, portal_id, views.
- Add per_page param in the API.
- Update the code in the frontend to fetch only 6
This PR adds service to automate account abuse detection. Currently
based on the signup name and URL, could potentially add more context
such as usage analysis, message metadata etc.
# Pull Request Template
## Description
This PR adds the ability to see the shared contact name in Telegram
channels.
## Type of change
- [x] New feature (non-breaking change which adds functionality)
## How Has This Been Tested?
**Loom video**
https://www.loom.com/share/cd318056ad4d44d4a1fc4b5d4ad38d60?sid=26d833ae-ded9-4cf0-9af7-81eecfa37f19
## Checklist:
- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules
---------
Co-authored-by: Shivam Mishra <scm.mymail@gmail.com>
Fixes#10721
This PR addresses an issue where the data migration in the CE edition
was failing due to missing models. The change ensures that the migration
process runs only when the deployment is using the EE image.
Currently, it’s unclear whether an FAQ item is generated from a
document, derived from a conversation, or added manually.
This PR resolves the issue by providing visibility into the source of
each FAQ. Users can now see whether an FAQ was generated or manually
added and, if applicable, by whom.
- Move the document_id to a polymorphic relation (documentable).
- Updated the APIs to accommodate the change.
- Update the service to add corresponding references.
- Updated the specs.
<img width="1007" alt="Screenshot 2025-01-15 at 11 27 56 PM"
src="https://github.com/user-attachments/assets/7d58f798-19c0-4407-b3e2-748a919d14af"
/>
---------
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
This PR introduces a review step for generated FAQs, allowing a human to
validate and approve them before use in customer interactions. While
hallucinations are minimal, this step ensures accurate and reliable FAQs
for Captain to use during LLM calls when responding to customers.
- Added a status field for the FAQ
- Allow the filter on the UI.
<img width="1072" alt="Screenshot 2025-01-15 at 6 39 26 PM"
src="https://github.com/user-attachments/assets/81dfc038-31e9-40e6-8a09-586ebc4e8384"
/>
Migration Guide: https://chwt.app/v4/migration
This PR imports all the work related to Captain into the EE codebase. Captain represents the AI-based features in Chatwoot and includes the following key components:
- Assistant: An assistant has a persona, the product it would be trained on. At the moment, the data at which it is trained is from websites. Future integrations on Notion documents, PDF etc. This PR enables connecting an assistant to an inbox. The assistant would run the conversation every time before transferring it to an agent.
- Copilot for Agents: When an agent is supporting a customer, we will be able to offer additional help to lookup some data or fetch information from integrations etc via copilot.
- Conversation FAQ generator: When a conversation is resolved, the Captain integration would identify questions which were not in the knowledge base.
- CRM memory: Learns from the conversations and identifies important information about the contact.
---------
Co-authored-by: Vishnu Narayanan <vishnu@chatwoot.com>
Co-authored-by: Sojan <sojan@pepalo.com>
Co-authored-by: iamsivin <iamsivin@gmail.com>
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Fixes https://github.com/chatwoot/chatwoot/issues/9935
Fixes https://github.com/chatwoot/chatwoot/issues/8213
The articles were grouped by category, with locale being a derived
attribute from the category. If a category was deleted, the article
wouldn't appear on the dashboard. However, due to a bug, it would show
up in the uncategorized section on the public portal, leaving agents
unable to edit or update the article.
To address this issue, I've added a locale attribute directly to the
article. This attribute is automatically set from the category or the
portal's default locale if not supplied. The API parameters now use this
attribute to filter articles. As a result, the dashboard will display
articles even if they're not associated with a category, improving the
overall workflow.
**Main updates:**
- Add locale attribute to the Article model. Add db migration to back
fill the data based on the above logic.
- Add a new scope search_by_locale and use it instead of
search_by_category_locale.
- Update the ERB template to include the locale filter.
- Move from `joins` to `left_outer_joins` to include the articles with
no categories.
---------
Co-authored-by: Sojan <sojan@pepalo.com>
- Adding a new index on (account_id,created_at,message_type) based on
our performance improvement exercise. This index significantly improves
the page load speeds of messaging reports.
Based on our recent performant optimisation exercises, We have identified a better indexing strategy for conversations and contacts. The previous index on last_activity_at for conversations significantly slowed down conversation filters. Similarly, the new index on Contacts will allow the page rendering to improve for accounts with many contacts.
fixes: https://linear.app/chatwoot/issue/CW-3300/db-improvements