This gates API-token access and outgoing account webhooks behind the
`api_and_webhooks` account feature introduced in #14972. On Chatwoot
Cloud, Hacker accounts lose token-authenticated account API access and
account webhook delivery, while paid accounts retain them through the
billing-plan feature reconcile. Community and self-hosted installations
continue to work without any upgrade-time interruption.
## What changed
- Added `Account#api_and_webhooks_enabled?` as the single backend kill
switch. Core returns enabled; the Enterprise override consults the
account flag on Chatwoot Cloud and remains enabled off-Cloud.
- Account-scoped v1 and v2 requests authenticated with a user or
agent-bot API token now return `403 Forbidden` when the feature is
disabled. Invalid tokens still return 401, and dashboard session
requests are unaffected.
- Profile responses return an empty access token when none of the user's
accounts has access. The stored token is preserved, and the profile UI
disables its token controls with paid-plan copy on Cloud.
- Account webhook delivery stops when the feature is disabled. Webhook
CRUD remains available to session-authenticated dashboard requests,
API-inbox webhooks continue to be delivered, and the Cloud dashboard
shows a webhook paywall instead of the webhook list.
- Removed the database backfill migration. Existing paid Cloud accounts
should be enabled with the one-off script below before enforcement is
deployed.
## Existing paid-account rollout
Run this as an ad-hoc Rails runner script on Chatwoot Cloud. It
intentionally targets only the Startups, Business, and Enterprise plans
and does not add `api_and_webhooks` to `manually_managed_features`, so
future billing reconciles remain authoritative.
```rb
paid_plan_names = %w[Startups Business Enterprise]
accounts = Account.where("custom_attributes ->> 'plan_name' IN (?)", paid_plan_names)
total = accounts.count
enabled = 0
skipped = 0
puts "Enabling api_and_webhooks for #{total} paid account(s)..."
accounts.find_each(batch_size: 500).with_index(1) do |account, processed|
if account.feature_enabled?('api_and_webhooks')
skipped += 1
else
account.enable_features!('api_and_webhooks')
enabled += 1
end
puts "Processed #{processed}/#{total}..." if (processed % 1000).zero?
end
puts "Done! Enabled: #{enabled}, Skipped: #{skipped}, Total: #{total}"
```
For example, save the snippet outside the repository as
`enable_api_and_webhooks.rb`, then run:
```sh
bundle exec rails runner /path/to/enable_api_and_webhooks.rb
```
## How to test
- On Cloud, use a Hacker account and confirm token-authenticated
requests to account-scoped v1 and v2 endpoints return 403, while the
same dashboard actions continue to work through session authentication.
- Confirm profile access-token controls are disabled with paid-plan copy
when all accounts are ineligible, and remain available when at least one
account has the feature.
- Confirm the Webhooks settings page shows the billing paywall for a
Cloud account without the feature; admins get the billing action and
agents get the existing ask-an-admin message.
- Confirm outgoing account webhooks stop for an ineligible Cloud account
while API-inbox webhooks still deliver.
- Confirm community and self-hosted installations retain API and webhook
behavior after upgrading, even when an existing account does not have
the stored feature bit.
### Screenshots
## Cloud
<img width="2590" height="642" alt="CleanShot 2026-07-15 at 15 13 14@2x"
src="https://github.com/user-attachments/assets/431a7bd8-1742-4e7a-b312-d3ad92015f9b"
/>
<img width="2152" height="994" alt="CleanShot 2026-07-15 at 15 14 37@2x"
src="https://github.com/user-attachments/assets/475dda48-d1c5-4be5-a3c3-7a96b9713724"
/>
---------
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
Remove the `user.permissions` field and resolve the permissions directly
from the accounts array in the user. This change ensures that the cache
or previous values from the last active account don't affect the
permissions.
In this PR:
- Remove user.permissions usage, replace it with getUserPermissions
method.
- Remove json.permissions from user.json.jbuilder
This API change sets the foundation for an upcoming frontend update, transitioning from a role-based model to a permission-based model. This new approach will determine eligibility for various actions and UI elements based on specific permissions rather than roles, enhancing flexibility and security in user access management.
- Add more feature flags for CRM, auto_resolution, and reports
- Add a SuperAdmin link in the sidebar if the user is a super-admin
- SuperAdmin could view all the features on an account irrespective of whether the feature is enabled.