# Documentation (/docs)
WASync puts WhatsApp numbers, QR or Business API, inside your CRM: conversations in the inbox and on the record, automatic flows, calls, and rules for who sees what. The same numbers are reachable from your own software through a REST API, a remote MCP server and an n8n node.
## Choose your path [#choose-your-path]
## Three things to know first [#three-things-to-know-first]
**Two kinds of numbers.** A **QR number** is the WhatsApp you already have, paired by scanning a code; no templates, no Meta limits, but WhatsApp's rules on bulk messaging apply. A **Business API number** is registered with Meta: templates, calls, higher volumes, and a 24-hour rule. The [connection types](/docs/concepts/connection-types) page compares them.
**The 24-hour window.** On a Business API number you may send free text only to a customer who wrote to you in the last 24 hours. Outside that window, only an approved **template** goes through; WASync locks the composer and offers the template picker instead of losing your message. [Templates on Business API numbers](/docs/product/wasync-chat#templates-on-business-api-numbers).
**Records follow rules you set.** Who becomes the responsible of a new chat, whether each number gets its own lead, what a flow creates or binds to, who may see which conversation: all of it is in **Chat rules** and documented under [CRM records](/docs/product/crm-records) and [Chat Flows](/docs/product/chat-flows).
## Keeping up [#keeping-up]
The [changelog](/docs/changelog) is the dated record of what shipped, with a line per change pointing at the product page that now documents it. Inside the app, **What's new** shows the same releases per user, in your language.
## For developers [#for-developers]
* [Quickstart](/docs/quickstart): account, key, first message in under five minutes.
* [Guides](/docs/guides): webhooks, OAuth2, n8n, MCP, WhatsApp templates, bringing a number from another provider.
* [API reference](/docs/api-reference): every endpoint, generated from the OpenAPI contract.
* [Security](/docs/security): API keys and the developer console.
Base URL `https://developers.wasync.app/api/v1`. Every page of this site is also available as Markdown (append `.md` to the URL) and listed in [llms.txt](/llms.txt) for AI agents.
# Plans, trial and invoices (/docs/administration/billing)
## What is licensed [#what-is-licensed]
Each WhatsApp **number** has its own licence, bought and renewed on the number's row in **Connections**. The app itself, the team, the flows and the settings are free; a number with no active licence stops sending and receiving.
| Plan | Covers | Price |
| ----------------------- | ---------------------------------------------------------------------- | ------------- |
| **WAPP** | A QR number: the WhatsApp you already have, paired by scanning a code. | $19 per month |
| **WABA** | A WhatsApp Business API number: templates, calls, higher volumes. | $29 per month |
| **API & agents** add-on | REST API, remote MCP server and n8n node on the number. | $12 per month |
Prices are in USD and exclude VAT, which Stripe adds according to your country and VAT status at checkout. Partners resell at 60 % of the list price; see [Partners](https://wasync.app/partners).
## The trial [#the-trial]
Every new number starts with a **7-day trial** with everything enabled; numbers brought by a partner get 15 days. One trial per phone number: a number that already had its trial, on any portal, goes straight to a paid licence. Three days before the end you receive an email and a Bitrix24 notification; when the trial ends the number is paused until a licence is activated, and nothing is deleted.
## Paying [#paying]
**Connections → the number → Activate** opens the Stripe checkout. Card and PayPal are accepted; the subscription renews monthly on the same card. A refused card is almost always the issuing bank's decision; try another card or write to [support@wasync.app](mailto:support@wasync.app) for a Revolut payment link and a manual activation.
Add-ons and extra numbers are added on the same page; the subscription is adjusted pro rata.
## Invoices and company details [#invoices-and-company-details]
Stripe emails an invoice for every payment. **Connections → the number → Manage subscription** opens the Stripe customer portal with every invoice, the card on file and the company details: fill in the legal name, address and VAT number **before** paying, because an invoice carries the details at the moment of payment. Companies outside Romania also receive a fiscal invoice from TDACRM Solutions SRL for each payment.
## Expiry and grace [#expiry-and-grace]
A subscription that fails to renew enters a short grace period during which the number keeps working and administrators are notified; after it, the number is paused. Reactivating a paused number restores everything, including conversations and flows.
## Related [#related]
* [Licences and trial](/docs/concepts/licences-and-trial) for the API side
* Help Center: [Do I get an invoice?](/docs/help-center/api-and-billing/invoices), [My card is refused](/docs/help-center/api-and-billing/card-refused-by-stripe)
# Data and security (/docs/administration/data-and-security)
## What is stored [#what-is-stored]
For each number, WASync keeps the conversations (messages, delivery status, the linked CRM record), the contacts WhatsApp knows (number, name, photo link), the files exchanged, the Chat Flow runs with the answers collected, call records, and an audit trail of administrative actions. Bitrix24 keeps its own copy of what WASync writes on timelines and in Open Channels.
## Retention [#retention]
| Data | Kept |
| ------------------------------------- | ----------- |
| Messages and media | 90 days |
| Sessions, events, email log, alerts | 180 days |
| Audit trail of administrative actions | Not deleted |
| Unused Bitrix24 user tokens | 60 days |
Media files are stored in the EU and served through short-lived signed links; the links in exports expire after 24 hours.
## Deleting [#deleting]
* **A connection**: the number, its conversations in WASync and the flows bound to it are removed; the CRM keeps everything written on it. [What do I lose when deleting a connection?](/docs/help-center/connections/what-do-i-lose-when-deleting-a-connection)
* **The app**: uninstalling from Bitrix24 pauses the portal; the data is kept for 90 days in case you come back, with a warning email on day 83, then purged, including messages, media and settings. Audit records of the purge itself are kept.
## Who can read what [#who-can-read-what]
Access follows Bitrix24: a person reads only the numbers and conversations given in [Team](/docs/administration/team-and-access), administrators read everything, and the APIs behind the app enforce the same limits. WASync staff access customer data only for support, on request, and every such access is logged.
## Agreements [#agreements]
The [Data Processing Agreement](https://wasync.app/dpa) is available to every customer; the [Terms](https://wasync.app/terms) and the [Privacy policy](https://wasync.app/privacy) cover the rest. WhatsApp traffic itself is subject to Meta's terms for the Business API and, on QR numbers, to WhatsApp's terms for the application.
## Related [#related]
* [Security: API keys](/docs/security/api-keys)
* [Developer console](/docs/security/developer-console)
# Administration (/docs/administration)
The pages for the person who installed WASync: money, people and data.
# Team and access (/docs/administration/team-and-access)
## Access to numbers [#access-to-numbers]
**Team** (sidebar) lists every Bitrix24 user with the numbers they may use. A person with access to a number can read and answer its conversations in WASync Chat and in the CRM tab, send files and templates, and is rung for its calls. **Edit access** picks the numbers; one of them is the **primary** number, used when the person starts a conversation from a CRM record without choosing a number. A person with no access sees no WhatsApp at all in Bitrix24.
The Open Channel's own queue in Bitrix24 is separate: a number bound to an Open Channel delivers to that queue as well, by Bitrix24's rules.
## Console access [#console-access]
For each person, **Console access** decides what they may do in the WASync app itself, area by area: read, or read and change. A sales agent typically needs numbers and nothing else; a team lead gets Chat Flows and Quick replies; connections, team, settings and reports stay with administrators.
## Visibility of conversations [#visibility-of-conversations]
Independent of access to a number, each person has a visibility level: **all chats** of the numbers they may use, their **department**, or **only the records they are responsible for**. It is set on their row in Team; the default for everyone else is in [Chat rules](/docs/product/settings#who-sees-what). The level applies in WASync Chat, in the "Assigned to" filter and in the export.
## Administrators [#administrators]
Bitrix24 administrators are administrators in WASync: they see every conversation, change every setting, manage licences and the team. Nothing has to be granted to them. Everybody else is limited to the numbers and areas given above, and the APIs behind the app refuse what the interface hides.
## Changing user or portal [#changing-user-or-portal]
WASync acts in Bitrix24 as the user who installed the app. If that person leaves, reinstall from the Marketplace as another administrator, or write to support; records created by WASync land on that user when no rule says otherwise ([Chat rules](/docs/product/settings#new-chats-from-unknown-numbers)).
## Related [#related]
* [Settings and Chat rules](/docs/product/settings)
* Help Center: [Can I restrict employees to their own chats?](/docs/help-center/wasync-chat/restrict-employees-to-their-own-chats)
# API Reference (/docs/api-reference)
{/* Generated by scripts/generate-api-reference.mjs — do not edit. */}
Base URL `https://developers.wasync.app/api/v1`. Every request carries
`Authorization: Bearer `; an OAuth access token goes in the same
header. The machine-readable contract these pages are built from is
[openapi.json](https://developers.wasync.app/openapi.json), served with open
CORS so you can generate a client straight from it.
## Connections [#connections]
## Account [#account]
## Messages [#messages]
## Webhook [#webhook]
# 19 June 2026 (/docs/changelog/2026-06-19)
## WhatsApp Platform API launch [#whatsapp-platform-api-launch]
**New feature.**
First public release. REST v1 at `https://cloudapi.wasync.app/api/v1`:
`GET /connections`, `GET /messages` (cursor-paginated) and `POST /messages`
(text, idempotent via `idempotencyKey`).
Auth is OAuth 2.0 Authorization Code + PKCE (S256 required,
`client_secret_post`) with discovery under `/.well-known/`.
A remote MCP server at `/api/mcp` exposes `list_whatsapp_connections`,
`send_whatsapp_message` and `read_whatsapp_messages`.
Webhooks deliver `message.received` with HMAC-SHA256 signatures
(`X-WASync-Signature`). App registration lives at
[https://developers.wasync.app](https://developers.wasync.app); the AI integration kit (`/docs`,
`/openapi.json`, `/llms.txt`) shipped the same day.
# 2 July 2026 (/docs/changelog/2026-07-02)
## 402 responses with a payment link when the API add-on is inactive [#402-responses-with-a-payment-link-when-the-api-add-on-is-inactive]
**Improvement.**
Sending through a connection whose Platform API add-on is not active now returns
`HTTP 402` with an actionable body instead of a bare 403:
`{ error: "license_inactive", code, message, payment_url }`.
The original core code (`addon_required` or `license_inactive`) is preserved in
`code`, and `payment_url` points where the connection owner can activate the
add-on. MCP tool results return the same information as plain text so an AI
agent can relay it to the human.
Every other error status is still relayed verbatim — branch on the `error` code,
never on message text. See
[Errors & idempotency](/docs/concepts/errors-and-idempotency).
# 13 July 2026 (/docs/changelog/2026-07-13)
## Webhooks reference page + docs payload fix [#webhooks-reference-page--docs-payload-fix]
**New feature · Improvement.**
A dedicated [Webhooks reference](/docs/guides/webhooks) now documents the full
delivery contract: event catalog, exact payload, signature verification with a
complete receiver example, retry policy (3 attempts, exponential backoff, 10 s
per-attempt timeout, no long redelivery queue — backfill via `GET /messages`),
duplicate and ordering semantics, and a troubleshooting checklist.
Docs fix: the webhook example previously showed `message.timestamp` as an ISO
string — deliveries actually carry epoch **milliseconds** (a number). The
payload itself is unchanged; only the documentation was wrong.
## Machine-readable docs surface: llms-full.txt + CORS-open spec [#machine-readable-docs-surface-llms-fulltxt--cors-open-spec]
**Improvement.**
The complete documentation is now published as a single markdown file at
[https://developers.wasync.app/llms-full.txt](https://developers.wasync.app/llms-full.txt) for LLM ingestion, alongside the
existing [https://developers.wasync.app/llms.txt](https://developers.wasync.app/llms.txt) index.
`/openapi.json`, `/llms.txt` and `/llms-full.txt` are now served with
`Access-Control-Allow-Origin: *`, so browser-based spec viewers, SDK generators
and AI agents can fetch them cross-origin. This changelog is also new.
# 25 July 2026 (/docs/changelog/2026-07-25)
## Read receipts — POST /messages/read gives your customers blue ticks [#read-receipts--post-messagesread-gives-your-customers-blue-ticks]
**New feature.**
If your operators read WhatsApp inside your own CRM, nobody ever opens the chat
in WhatsApp — the customer's messages stay on double grey ticks and the
conversation feels ignored. `POST /messages/read` sends the WhatsApp read
receipt for you.
Body: `{ connectionId, phone?, messageId? }` — at least one of `phone` /
`messageId` (the latter is WASync's cuid of an *incoming* message, not
`waMessageId`). It uses the existing `whatsapp.send` scope, because marking read
transmits a receipt to the customer's device — no re-consent needed.
Idempotent by nature: no `idempotencyKey`, no rate limit, safe to retry.
Response `{ ok: true, marked }`, where `marked` counts the stored inbound
messages newly flagged as read.
## messageId is now WASync's stable id — WhatsApp's id moves to waMessageId [#messageid-is-now-wasyncs-stable-id--whatsapps-id-moves-to-wamessageid]
**Breaking change · Improvement.**
`POST /messages` previously returned WhatsApp's own message id
(`true_…@c.us_3EB0…`) as `messageId`, while `GET /messages` and the
`message.received` / `message.status` webhooks used WASync's id — so status
events could never be matched back to a send.
They are now the SAME id everywhere: `messageId` (POST) = `id` (GET) =
`message.id` (webhooks), a WASync cuid. WhatsApp's own id is still returned,
alongside, as `waMessageId` (REST), `wa_id` (webhooks) and `wa_message_id`
(media send) — use it for support tickets, never as a join key (it can be
`null`). `GET /messages` rows now also carry `waMessageId`, so you can map both
ways.
**Action required** if you stored the value of `messageId` to match webhooks: it
now changes format — join on the new value, and read `waMessageId` if you
specifically needed the WhatsApp id.
One new edge case: if a send reaches WhatsApp but cannot be persisted, the 200
body is `{ messageId: null, waMessageId, status, persisted: false }` — the
message was delivered, so do not retry it.
# 8 August 2026 (/docs/changelog/2026-08-08)
## Connection lifecycle events + GET /account slot quota [#connection-lifecycle-events--get-account-slot-quota]
**New feature.**
Two webhook events were added for partners who run our connections inside their
own product: `connection.disconnected` (a number stopped working and its owner
must pair again) and `connection.connected` (it recovered). Both fire once per
real transition, on `qr` connections, and the QR is deliberately NOT in the
payload — it is a scan-to-login credential, so fetch it from your authenticated
`GET /connections/{id}`.
`GET /account` (scope `whatsapp.read`) answers "can I onboard another number
right now?" before you take the order:
`{ slots: { total, used, available, nextExpiry }, connections: { total, connected, needsReconnect } }`.
A slot is capacity, not a phone number — it attaches when a number actually
pairs and returns to your pool with whatever time is left on it when the
connection is deleted, so a paid slot moves from a departing customer to a new
one without paying twice. You map our connection `id` to your own customer
record; we mint the id, you map it.
Subscriptions created before 10 August 2026 must re-consent to receive the
`connection.*` events.
Also from this date, the connection `provider` field speaks the public
vocabulary: `qr` and `cloud_api`. See
[Connection types](/docs/concepts/connection-types).
# 17 August 2026 (/docs/changelog/2026-08-17)
## developers.wasync.app is the canonical host — cloudapi.wasync.app keeps working forever [#developerswasyncapp-is-the-canonical-host--cloudapiwasyncapp-keeps-working-forever]
**Improvement.**
The developer portal, the docs and the REST API are now documented under
`https://developers.wasync.app`, and the REST base URL is
`https://developers.wasync.app/api/v1`.
**Nothing you already built has to change.**
`https://cloudapi.wasync.app/api/v1` is a permanent alias serving exactly the
same API — same keys, same paths, same responses — and it remains valid
indefinitely. This is a documentation change, not a migration: there is no
cut-off date and no deprecation.
The OAuth endpoints, the `/.well-known/` discovery documents and the MCP server
URL are protocol identifiers your clients have already registered, so they are
**unchanged** and still read `cloudapi.wasync.app`. Keep using them exactly as
issued.
## Idempotency-Key on POST /connections — a retried create no longer costs you a second slot [#idempotency-key-on-post-connections--a-retried-create-no-longer-costs-you-a-second-slot]
**New feature.**
Creating a connection provisions a WhatsApp session and consumes a paid slot, so
a client that timed out and retried used to end up with two connections and two
slot charges for one customer. `POST /connections` now accepts an optional
`Idempotency-Key` header — the only endpoint that does; omit it and behaviour is
exactly as before.
Within a 24 h TTL: the same key with the same body returns the SAME connection
with `200` and the response header `Idempotency-Replayed: true`; the same key
with a different body is `400 idempotency_key_reuse`; a retry while the first
call is still in flight is `409 idempotency_in_progress` with `Retry-After: 1`;
a key over 255 characters is `400 idempotency_key_invalid`. Keys are namespaced
per workspace, and the body comparison is over a canonical hash, so JSON key
order is irrelevant.
**Mint one fresh UUID per customer-onboarding attempt** — never one per process,
per API key, per day, or a constant, or the second customer you onboard is
handed the first customer's connection. On a replay the `qr` is re-fetched
fresh, because pairing codes rotate roughly every 20 seconds and a stale one
would not scan.
## API keys are the default credential — plus IP allowlists and webhook self-service [#api-keys-are-the-default-credential--plus-ip-allowlists-and-webhook-self-service]
**New feature.**
`Authorization: Bearer wsk_live_…` now works on every endpoint. Create and
revoke keys at [https://developers.wasync.app/keys](https://developers.wasync.app/keys) — the key is shown once and
stored only as a hash, scopes are per key, and scopes plus the reachable
connection list are resolved live on every request.
If you are automating your own account this replaces the entire OAuth flow: no
redirect URI, no PKCE, no consent screen, no token refresh. OAuth 2.0 remains,
unchanged, for apps that OTHER WASync customers install and consent to. A key
can create a workspace's FIRST connection, so the old "make the first one in the
portal UI" bootstrap step is gone.
Optional hardening: pin a key to IPv4/IPv6 addresses or CIDR ranges — a call
from an address that is not on the list is refused with `403 ip_not_allowed`,
deliberately distinct from `401 invalid_key` (unknown or revoked key), because
the fix is to add an address, not to rotate a good key.
New endpoints `GET /webhook`, `PUT /webhook` and `POST /webhook/rotate` let you
point WASync at your endpoint and manage its signing secret without registering
an app: `PUT` issues the secret, `GET` never returns it (it reports `secretSet`
only), and rotation kills the old secret immediately. Nothing changed for
existing OAuth clients, and the webhook signature scheme is unchanged.
# 18 August 2026 (/docs/changelog/2026-08-18)
## Pairing codes — connect a number without scanning a QR [#pairing-codes--connect-a-number-without-scanning-a-qr]
**New feature.**
New endpoint `POST /connections/{id}/pairing-code` (scope `whatsapp.manage`).
Body `{ "phoneNumber": "40740267964" }` — E.164 without the leading `+`, digits
only — returns `{ "code": "7S59-1KZP" }`. Your customer types it into WhatsApp →
Settings → Linked devices → **Link with phone number**.
This is the path for the customer who is completing your onboarding on the same
phone that runs WhatsApp: there is no second screen to photograph, so the QR
simply cannot be used.
**A pairing code is not always available** — the engine can decline with
`502 pairing_code_unavailable`, so keep the QR flow on screen as a fallback.
Requesting another code on the same connection is allowed (a new code, same
session) and capped at 5 per connection per 15 minutes, then `429 rate_limited`
with `Retry-After`.
Nothing extra is consumed: the same paid slot and the same 7-day trial as QR
pairing, claimed when the number actually pairs. Monitoring is unchanged — poll
`GET /connections/{id}` and/or listen for `connection.connected`. `qr`
connections only; a `cloud_api` number answers
`409 not_supported_for_provider`.
Full guide: [Pairing code & QR](/docs/guides/pairing-and-qr).
# 8 September 2026 (/docs/changelog/2026-09-08)
## `422 recipient_not_on_whatsapp` on `POST /messages` [#422-recipient_not_on_whatsapp-on-post-messages]
**Improvement.** When WhatsApp reports that it has no account for the recipient,
the send now answers `422` with the code `recipient_not_on_whatsapp` and a message
that says what to check: the number must be in international format (country
code first, no leading zero) and the person must use WhatsApp. Until today this
case came back as a generic `502 send_failed`, which read like an outage on our
side. It is permanent for that number — fix the input rather than retrying.
`502 send_failed` is now reserved for failures that are not about the recipient
(session or provider), where a short back-off and a retry make sense. Both codes
are listed in [Errors & idempotency](/docs/concepts/errors-and-idempotency).
## Purchased slots apply themselves [#purchased-slots-apply-themselves]
**Improvement.** In a developer workspace, a new connection now takes a free
purchased slot immediately instead of starting a trial, and a connection still
on trial is upgraded as soon as a slot is free. On the Connections & Billing
page you can also move capacity by hand: "Assign a slot" on a trial or expired
connection, "Release slot" on a slot-backed one (the slot returns to your pool
with its remaining time), and a "free slots" counter on the Slots card.
# 14 September 2026 (/docs/changelog/2026-09-14)
## API keys from inside Bitrix24 [#api-keys-from-inside-bitrix24]
**New feature.** Settings → **API & Agents** now has an **API keys** card. An
admin names the integration and gets the full key shown once, with Copy, plus
the portal's existing keys — prefix, created, last used, revoked — and can
revoke any of them with a confirmation. Below the list: the API base URL
(`https://cloudapi.wasync.app/api/v1`), a curl example, a link to these docs
and a pointer to the n8n node. Creating a key needs at least one connection
with the API add-on active ($12 per number per month); without one, the button
is disabled with the reason and the server answers `403 addon_required`. Keys
made this way carry the standard scopes `whatsapp.read whatsapp.send`. The
developer console still exists for IP allowlists, webhooks, and several
portals under one account — the card links to it.
## Checkout self-heals a stale Stripe customer [#checkout-self-heals-a-stale-stripe-customer]
**Fix.** A customer id that no longer exists in Stripe live mode is now
replaced automatically instead of failing the checkout.
# 15 September 2026 (/docs/changelog/2026-09-15)
## Delete a number, close a workspace [#delete-a-number-close-a-workspace]
**New feature.** The developer console can now remove what it creates. Each
connection row on **Billing** has a **Delete** button, and a workspace with no
connections left can be closed from the same card.
Deleting a number closes its WhatsApp session, removes every message stored for
it, and returns its slot to the workspace pool if it was on a paid one. Closing a
workspace removes it together with its API keys and webhook configuration, so
anything still calling the API with those keys stops working. Both actions ask
for confirmation and neither can be undone.
Two refusals are deliberate. A workspace that still has numbers cannot be
closed — delete them first, so the phones are actually unlinked instead of
leaving orphaned sessions behind. A workspace with a live slot subscription
cannot be closed either; cancel the subscription first, or it keeps billing a
workspace that no longer exists.
The same actions are available over the API: `DELETE /v1/connections/{id}` with a
key carrying the `whatsapp.manage` scope.
What survives on purpose: the record that a number already had its free trial.
Closing a workspace and opening another does not hand the same phone a second
trial.
## Click-to-WhatsApp attribution retries the CRM write [#click-to-whatsapp-attribution-retries-the-crm-write]
**Fix.** Bitrix24 lists a freshly created deal seconds before it will answer a
write for that same id, replying `400 Not found` in between. Ad attribution
written in that window was lost, leaving the contact attributed and the deal
with empty UTM fields. Each write is now retried, and a write that still fails
raises an alert on our side instead of failing quietly.
# 17 September 2026 (/docs/changelog/2026-09-17)
## Call permission, end to end [#call-permission-end-to-end]
**New.** When a customer answers the WhatsApp "may we call you?" card, the
answer is now recorded on the contact and written to the CRM timeline:
allowed permanently, allowed until a date (temporary grants last seven days),
declined, or revoked. In the CRM widget and in WASync Chat the phone icon turns
green while the permission is active, and a chip next to the customer's name
reads "Calls allowed" or "Calls declined". Until now the only way to learn the
answer was to place a call and hit Meta's error.
The template picker has a new checkbox, *Also ask permission to call after
sending*: the permission card follows the template automatically. Official
WhatsApp Business API connections only — QR numbers have no call permission.
The request sentence itself now goes out in the operator's language, twenty
languages, instead of always English, and the call window has an optional field
for a custom sentence.
## Tapped template buttons reach chat flows [#tapped-template-buttons-reach-chat-flows]
**Fix.** A quick-reply button tapped on a template, or an interactive button or
list choice, used to arrive as an empty message: flows could not branch on it
and the inbox showed nothing. The button label is now the message text, and
flows branch on it with the usual keyword matching.
## Two new chat-flow nodes [#two-new-chat-flow-nodes]
**New.** *Ask permission to call* sends the permission card from inside a flow.
*Create Bitrix24 activity* adds a to-do on the lead or deal, assigned to the
record's responsible person, with a configurable deadline (default 60 minutes)
and a notification. A new variable, `{{RESPONSIBLE_NAME}}`, is available in
messages and templates.
Together these enable the re-engagement pattern after the 24-hour window: an
approved template with three buttons, one branch per button, a permission
request for the customers who want a call, and a to-do for the recruiter when
they accept.
## Buttons and the call-permission card in templates [#buttons-and-the-call-permission-card-in-templates]
**New.** The template builder adds buttons: up to three quick replies, one
link button and one call button, with a preview. A template can also carry
Meta's call-permission card as part of the message — tick *Include a WhatsApp
call-permission request* — which is the only way to ask a customer whose
24-hour window has closed. The picker marks such templates and hides the
follow-up checkbox for them.
When the follow-up checkbox is used on a closed window, the request is no
longer refused: it is parked and sent automatically at the customer's next
message, and the header reads *Asking…* until then. Meta allows one permission
request per customer per 24 hours and two per seven days.
## Known limit [#known-limit]
Call logging in Bitrix24's *Call details* requires the `telephony` permission,
which ships with app version 3, in Bitrix24 moderation since 17 September.
Existing portals will need to update the app from Market once it is approved.
# 18 September 2026 (/docs/changelog/2026-09-18)
## Late delivery failures reach the Open Channel [#late-delivery-failures-reach-the-open-channel]
**Fix.** On the official WhatsApp Business API, a message sent outside the
24-hour window is accepted by Meta and fails a few seconds later, in a
separate delivery status. Bitrix24 had already marked the message as sent,
and the connector API offers no way to change that, so the operator believed
the customer received it. The CRM widget showed the error; the Open Channel
showed nothing.
Every such late failure now posts a note into the same Open Channel dialog,
once per message, in the portal's language. For the 24-hour case the note
reads: *This message was not delivered: the 24-hour window with this customer
has closed. To reach them again, send an approved template.* Other Meta
error codes get the reason in plain words, with the code in parentheses.
The note respects the portal's Open Channel mirroring switch and is never
posted twice when Meta retries the webhook.
## Ad attribution always reaches the deal [#ad-attribution-always-reaches-the-deal]
**Fix.** Bitrix24 creates the contact when a conversation opens and the deal a
little later. When the deal arrived more than about 30 seconds after the ad
referral, the campaign data was written to the contact only and the deal
stayed empty. The lookup now keeps waiting for the deal for up to five minutes,
and an hourly pass copies the attribution from the contact onto any deal
created in the last 48 hours that came too late. Nothing is lost: the contact
always has it, and the deal inherits it within an hour at most.
# 19 September 2026 (/docs/changelog/2026-09-19)
## Passkeys, two-step sign-in and a security page for the developer console [#passkeys-two-step-sign-in-and-a-security-page-for-the-developer-console]
**New.** The developer console at
[developers.wasync.app](https://developers.wasync.app) now offers three ways to
sign in — password, a 6-digit email code, or a passkey (Face ID, Touch ID,
Windows Hello or a hardware key) — and a mandatory second step for accounts
that hold API keys: a passkey (which satisfies both steps at once), an
authenticator app, or one of ten single-use recovery codes.
New accounts set up the second step right after creating the account.
Existing accounts get a 14-day heads-up before it becomes mandatory; account
admins have no grace period. A new **Security** page lists your signed-in
devices (revoke any of them), your last 12 months of account activity, and
lets you manage your passkeys, authenticator app and recovery codes.
Sensitive actions — creating or revoking an API key, rotating a webhook
secret, deleting a connection, closing a workspace, or changing your two-step
setup — now ask you to reconfirm your second step if it has been more than a
few minutes since you last did. Repeated failed sign-in attempts bring up a
Cloudflare Turnstile challenge, and ten wrong passwords in 15 minutes apply a
temporary 15-minute lock to the account (password sign-in only — a passkey or
email code always still gets you in).
See [Developer console sign-in](/docs/security/developer-console) for the
full picture.
# 21 September 2026 (/docs/changelog/2026-09-21)
## Deleting a deal no longer orphans the conversation [#deleting-a-deal-no-longer-orphans-the-conversation]
**Fix.** Every WhatsApp conversation is bound to one Bitrix24 record — usually
the deal or lead it was last worked from. That binding is what the CRM tag on
the chat points at, what the assignee and stage controls act on, and where the
chat notes are written.
Deleting that deal in Bitrix24 left the binding pointing at a record that no
longer existed. The chat kept showing the old tag, the assignee and stage in
the chat header went blank — and, invisibly, every chat note from then on was
addressed to the deleted deal and reached nothing at all, instead of falling
back to the contact.
The binding now repairs itself. When the app reads the record it is bound to
and finds it missing, it confirms the record really was deleted rather than
merely unreadable at that moment, drops the stale binding, and re-matches the
conversation the same way an incoming conversation is matched: an open deal
first, then an open lead, then the contact. The message that discovered the
deletion is written to the CRM too, so no history is lost in between.
Nothing to switch on, and no effect on conversations whose records still
exist. A record you simply do not have permission to read is never mistaken
for a deleted one.
# 24 September 2026 (/docs/changelog/2026-09-24)
## Insert field, on every chat-flow message [#insert-field-on-every-chat-flow-message]
**New.** Every Message card in Chat Flows (and the escalate/handoff message)
has an *Insert field* button under the text. It opens the CRM field list —
Deal or Lead, Contact, Company — with search, and a click drops `{{CODE}}` at
the cursor. At send time the code is replaced by the record's value.
Placeholders were already substituted at send time (`{{NAME}}`,
`{{RESPONSIBLE_NAME}}`, any field of the lead or deal); what was missing was
a way to discover them. New in the same release: `{{CONTACT_*}}` and
`{{COMPANY_*}}` resolve in flows too, including inside a WhatsApp Business
template's parameters, and a question step's answer can be inserted as
`{{LABEL}}`. A flow that is not attached to a lead or deal offers its own
collected answers instead of CRM fields.
## Attach the file stored on the deal or lead [#attach-the-file-stored-on-the-deal-or-lead]
**New.** The attachment picker of a chat-flow message step (and of an
Automation) has a third source next to *upload* and *link*: **From CRM
field**. It lists the file-type fields of the flow's lead or deal; picking one
attaches the field, not a file. At send time WASync reads the file stored on
that record and sends it, so each customer receives their own contract,
invoice or CV. A multiple field sends all its files, five per message at most,
in the step's order.
If the field is empty on a record, or the file cannot be fetched, the message
text still goes out without the file and a short note is written to the
record's timeline. Nothing fails silently and nothing is sent half-resolved.
## Values written the way a person would [#values-written-the-way-a-person-would]
**Improvement.** Wherever a person reads a CRM value — flow messages, robot
messages, Automations text, AI prompts, timeline comments, notifications —
it is now formatted: list fields show the item's label instead of its id
(a customer had received "282, 284, 286"), dates read `dd.mm.yyyy` (with
`hh:mm` for date-time fields), money fields read "100 EUR", yes/no fields
read Yes/No in the message's language, file fields read "1 file" or
"3 files". Values written back into Bitrix24 by a flow (set-field steps,
router conditions) stay raw on purpose.
## Robot panel: custom fields show their name [#robot-panel-custom-fields-show-their-name]
**Fix.** In the robot panel's field picker, custom fields (`UF_*`) showed
their technical code instead of their name. Bitrix24 reports the code as the
field's title and keeps the name in a separate label; the picker now reads
the label. The inserted placeholder is unchanged, so saved automations keep
working.
# 25 September 2026 (/docs/changelog/2026-09-25)
## Who sees which chats [#who-sees-which-chats]
**New.** A "WASync Chat" page in the app's sidebar lets an administrator
decide what each employee sees in the WASync Chat inbox and in the WhatsApp
tab of the CRM: **all chats** of the numbers they may use (the default, and
today's behaviour), **their department** (the records of everyone who shares
a Bitrix24 department with them — a team leader's view), or **only their own
records** (the leads, deals and contacts they are responsible for). The scope
is set per person on the Staff page, with a portal-wide default; Bitrix24
administrators always see everything.
The rule is enforced on the server, not just hidden in the interface: the
conversation list, search, the conversation itself, every action on it and
every send are checked. If Bitrix24 cannot say who owns a record, a scoped
employee sees nothing rather than everything.
Nothing changes for existing portals until an administrator sets a rule.
## New chats from unknown numbers [#new-chats-from-unknown-numbers]
**New.** On the same page, a portal can decide what happens when a message
arrives from a number that is not yet in the CRM: nothing (the default), or
WASync creates the lead and assigns it **round-robin** to an employee from a
chosen list, or to one fixed person. The chat is then visible to that employee
and their department. Numbers already in the CRM are linked to their existing
record instead; connections bound to a Bitrix24 Open Line are left to
Bitrix24, which creates the record there.
## Slot subscriptions: no more reminders that do not apply [#slot-subscriptions-no-more-reminders-that-do-not-apply]
**Fix.** Workspaces on a slot subscription renew automatically, yet their
connections were receiving "your licence expires" reminders, and a renewal
extended the slots without extending the connections holding them. Both are
fixed: reminders skip every connection covered by a live slot, and a renewal
carries the attached connections to the new period end.
# 29 September 2026 (/docs/changelog/2026-09-29)
## One thread per contact, whichever number they wrote to [#one-thread-per-contact-whichever-number-they-wrote-to]
**Improved.** When a customer has written to two or more of a workspace's
WhatsApp numbers, WASync Chat keeps a single conversation with the whole
history of that person. It now says which number each message belongs to: a
small "via +number" badge on messages that came through a number other than
the one selected for replying. The composer always shows the number a reply
will go out from and, with two or more numbers, becomes a picker — it defaults
to the number the customer wrote to last, and marks a WhatsApp Business
number as "templates only" while it is outside the 24-hour window. Every
send path follows the chosen number: text, files, templates, voice notes,
notes, takeover and the stage or assignee changes written to the CRM.
## New users saw their first two hours of messages as read [#new-users-saw-their-first-two-hours-of-messages-as-read]
**Fix.** An employee opening WASync Chat for the first time had every
incoming message of the following two hours counted as already read, in any
conversation they had not opened themselves; on workspaces with team-shared
read status, the team badge inherited it. The cause was a database session
time-zone shift on the moment the inbox was first opened. It is fixed for all
workspaces with nothing to configure. The rule is unchanged: whatever existed
before a person's first visit is read, and unread accrues from that visit
onward.
The same correction applies to the **chat export** — its date range was two
hours off at each end — and to the **Bot** tab's activity window.
# 30 September 2026 (/docs/changelog/2026-09-30)
## Media in EU object storage, served through signed links [#media-in-eu-object-storage-served-through-signed-links]
**Changed.** Images, voice notes, videos and documents exchanged over WhatsApp
are now stored in an EU-jurisdiction object store (Cloudflare R2) and handed
out only through **short-lived signed links** (15 minutes for the CRM widget
and WASync Chat, 30 minutes for a send in progress, 24 hours for a chat
export). The same 90-day retention applies, and deletion removes the object
store copy too. Nothing changes for what you see in Bitrix24, Pipedrive or
WASync Chat; links you copied earlier keep working until they expire.
## Deleted and edited WhatsApp messages on QR connections [#deleted-and-edited-whatsapp-messages-on-qr-connections]
**Fix.** When a customer deleted a message for everyone or edited it, the
change reached us with a short message id we did not recognise, so the
conversation in WASync kept the original. Both now apply within seconds:
a deleted message shows as deleted and an edited one shows the new text
with an "edited" label.
## Health checks that reach the database [#health-checks-that-reach-the-database]
**Improved.** The `/api/health` endpoint now runs a real database query and
reports the deployed build; a deploy only takes traffic once both agree.
Background jobs run on a single leader, which is what lets a second
application host come next.
## Voice notes through the WhatsApp Business API [#voice-notes-through-the-whatsapp-business-api]
**Fix.** A voice note recorded in the CRM widget or WASync Chat and sent
through a WhatsApp Business API number reached the customer as a plain audio
attachment, without the waveform bubble. It now arrives as a real voice note,
the same way it already did on QR-connected numbers.
## A number that is already connected cannot be connected twice [#a-number-that-is-already-connected-cannot-be-connected-twice]
**Changed.** Scanning the QR code with a phone whose number is already
connected on the same workspace used to create a second connection that took
over the first one, and both imported the conversation history — which showed
up as duplicated notes in the CRM. The second scan is now refused with a
clear message, in every language of the app, and the existing connection
keeps working. If the existing connection shows as disconnected, open it and
click Reconnect instead of creating a new one.
# 6 October 2026 (/docs/changelog/2026-10-06)
## Required fields before a stage change [#required-fields-before-a-stage-change]
**New.** Bitrix24 enforces its "required on this stage" fields only in its own
form, never when a stage is changed through the API, so closing a lead from the
chat could leave fields such as the reason for closing empty. An administrator
now defines, in WASync Chat rules → "Before moving to a stage, ask for these
fields", which fields must be filled for each pipeline and stage (leads and
every deal pipeline). When an operator changes the stage from WASync Chat, a
panel asks for those fields, pre-filled from the record; the stage changes only
once they are filled, in a single CRM update, and Cancel leaves it as it was.
Chat Flows are not affected, and the CRM widget has no stage picker, so
Bitrix24's own card applies its rule there.
## Templates keep their header image [#templates-keep-their-header-image]
**Improved.** WhatsApp Business API templates with an image, video or document
header now keep the file uploaded when they were created. Every send — CRM
widget, WASync Chat, Chat Flows, Automations and the template robot — uses it
by default: the operator sees "Template image" preselected with a preview and
can still change it before sending. For templates approved earlier or created
in Meta's own interface, "Set default image" in the template list sets it once.
Meta keeps the sample only for approval and asks for the file again at every
send, which is why this was needed.
## Chat visibility after a lead or deal is closed [#chat-visibility-after-a-lead-or-deal-is-closed]
**New.** A new administrator option in WASync Chat rules, "Closed leads and
deals", removes a conversation from its former responsible employee N days
after the lead or deal is closed (0 = immediately). It can optionally ignore
the contact's responsible, so only open leads and deals decide who sees a chat.
The chat reappears for whoever receives the customer's next lead or deal.
Administrators and people who see all chats are not affected.
Under "New chats from unknown numbers" there is also a new option, "Also create
a lead when the number is already a contact but has no open lead or deal": the
lead is linked to the existing contact and assigned by the same rule (fixed
person or round-robin). The "Create lead" button in WASync Chat now appears on
conversations linked only to a contact as well. Both options are off by
default.
## Chat Flows editor: first step of the redesign [#chat-flows-editor-first-step-of-the-redesign]
**Changed.** The Start step is now unique and cannot be deleted. It describes
in plain sentences when the flow starts — for example "Starts when a customer
writes first on +…, with any message" or "Once per customer. Stops when a
colleague replies" — with a "Change when it starts" button. Steps are edited in
a side panel while the canvas stays visible, instead of a modal.
The Branch step takes conditions as Field · Condition · Value, with a
searchable field picker grouped by customer answers, deal or lead, contact,
company and ad fields, and list values (stage, source, user, yes/no) chosen by
name. Every step that used to ask for an ID now uses pickers with names, and
the legacy "Action" step is no longer in the palette. The palette is grouped
and searchable, and the top bar has an editable name, a live "N problems" pill
that jumps to the step, Undo/Redo and a "Flow settings" panel. The whole editor
is available in all 20 languages. Draft and published versions are not part of
this step.
## "Customer writes first" no longer starts on a reply to your team [#customer-writes-first-no-longer-starts-on-a-reply-to-your-team]
**Fix.** If someone on the team wrote to a customer in the previous 72 hours —
from the CRM widget, WASync Chat, the Open Line or the business phone — the
customer's answer is now treated as a reply, and the inbound flow does not
start. Messages sent by flows, automations or robots do not count, so a flow
still starts when the customer truly writes first. This is on by default for
every existing flow; the trigger's "Don't start when we wrote first" option
turns it off or changes the window (1–168 hours).
## Leads created by WASync come with a contact and the form data [#leads-created-by-wasync-come-with-a-contact-and-the-form-data]
**Improved.** Every lead WASync creates — automatically at the first message,
when the operator writes first, or from the "Create lead" button — now gets a
linked contact: an existing one found by phone or email, otherwise a new one.
When the first message is a Meta lead-form message from a Click-to-WhatsApp
ad, its data is mapped: full name to first and last name and the lead title,
email to email, a different phone to a secondary phone, and every other
question and answer to a comment on the lead's timeline. On existing leads only
empty fields are filled; nothing is overwritten.
## Every contact of a lead or deal links to that record [#every-contact-of-a-lead-or-deal-links-to-that-record]
**Improved.** When a lead or deal has several contacts, the WhatsApp
conversation of any of them is now linked to that lead or deal, not only the
primary contact's. An open deal wins over an open lead, and a closed lead never
wins over a contact. This applies to new conversations and to the daily
re-check of existing links.
## Ad attribution reaches every open deal [#ad-attribution-reaches-every-open-deal]
**Fix.** When a customer's first message arrives without Meta's ad data and the
referral only comes with a later message, the campaign and ad fields are now
written to the contact and to every open deal without attribution opened in
the previous 24 hours, not only the first one. An older deal already attributed
to a previous ad no longer blocks the new one. An existing attribution is never
overwritten.
## Pipedrive: subscribing from the WASync panel [#pipedrive-subscribing-from-the-wasync-panel]
**Fix.** Pipedrive customers can subscribe again from the WASync panel. Pay
opens Stripe Checkout in a new tab — WhatsApp QR $19 or WhatsApp Business API
$29 per number per month, for 1, 3, 6 or 12 months, the same prices as on
Bitrix24 — and the panel updates itself when the payment completes. Account &
Plans shows each number's plan and billing state, with "Manage billing" for the
card, invoices and cancellation at the end of the period. Paying does not
reconnect a number that was disconnected when its trial ended; scan the QR code
again.
# 7 October 2026 (/docs/changelog/2026-10-07)
## Create or link a lead from WASync Chat [#create-or-link-a-lead-from-wasync-chat]
**Improved.** "Create lead" in WASync Chat first shows what the CRM already has
for that person under "Already in the CRM": existing leads (open and closed,
closed ones tagged "Closed") found by phone number and by the linked contact,
plus the contact's open deals, each with a "Link" button. "Create new lead"
sits below the list. On conversations linked only to a contact the button reads
"Create or link lead", and "Link to record" is available there too. Operators
see only the records their Bitrix24 role allows. Nothing is created or linked
automatically.
## Chat Flows: "Assign to" can rotate within a group [#chat-flows-assign-to-can-rotate-within-a-group]
**New.** The "Assign to a colleague" step has two modes: "One person", as
before (existing flows are unchanged), or "Rotate within a group". In rotation
mode the administrator ticks up to 50 employees in the step's side panel, and
each new conversation that reaches the step goes to the next person in the
list. Every step keeps its own rotation, and saving the flow again does not
restart it. Employees deactivated in Bitrix24 are skipped; if nobody in the
group is active, the record keeps its current responsible and a timeline note
explains why. A customer who passes the same step twice in one conversation
stays with the same person, and a test run shows who is next without using up
a real turn.
## Long messages on the WhatsApp Business API [#long-messages-on-the-whatsapp-business-api]
**Fix.** WhatsApp's official API accepts at most 4,096 characters in one text
message, so longer texts written by an operator were not delivered at all. They
are now sent as several WhatsApp messages in order, cut at the end of a
paragraph (or else a line, a sentence or a word), with the operator's name only
on the first one and delivery ticks on each. This works from the Open Line, the
CRM widget, WASync Chat, Chat Flows and Automations; in Bitrix24 the operator
still sees the single original message. The limit is 10 messages (about 40,000
characters) — beyond that the operator is told the message is too long and
nothing is sent. Templates and file captions keep their own limits. The
developer API does not split: a text over 4,096 characters is answered with
the error `text_too_long`.
## Calls you place: "Ringing…" until the customer answers [#calls-you-place-ringing-until-the-customer-answers]
**Fix.** When an operator calls a customer from the CRM on a WhatsApp Business
API number, the call window shows "Ringing…" with the customer's name and
number while the phone rings, and switches to "In call" only when the customer
picks up. The timer starts then, so the duration is talk time. The call saved
in Bitrix24 follows the same rule, and a call that was not picked up is saved
as an unanswered outgoing call with no duration. The operator is told why a
call was not answered: "No answer", "Call declined" or "Line busy" (the last
two only when WhatsApp reports them). Incoming calls are unchanged.
## Incoming calls: the team is rung when the responsible is offline [#incoming-calls-the-team-is-rung-when-the-responsible-is-offline]
**Fix.** When a known customer called and their responsible employee was
offline in Bitrix24, the call was saved as missed straight away. It is now
offered to the other online operators of the number's Open Line, all at once,
and if none is online, to the online employees with access to the number in
Connections → Staff. Only when nobody is online is the call saved as missed, on
the responsible employee, as before. An online responsible employee is still
rung alone, and only people already allowed to handle the number are ever rung.
## The customer's WhatsApp photo and name in Bitrix24 [#the-customers-whatsapp-photo-and-name-in-bitrix24]
**Improved.** On QR-connected numbers, WASync now asks for the customer's
WhatsApp profile photo as their message arrives, so the Open Channel chat is
created with the photo from the first message. The message is never held for
it: if the photo is not available within about a second and a half, it is
used from the next message on. New QR conversations also arrive in the Open
Channel under the customer's WhatsApp name instead of their phone number.
**New.** Settings → "CRM contact name and photo" → "Copy the WhatsApp name and
profile photo to the CRM contact when they are empty" is off by default. When
an administrator turns it on, WASync fills the name and photo on the linked
Bitrix24 contact only when they are missing, never over anything the team
entered, once per contact, with an audit log entry. On WhatsApp Business API
numbers only the name is available, because Meta does not provide customer
photos. A lead or deal without a contact is not affected, and a name the
customer changes later in WhatsApp is not re-synced.
# 8 October 2026 (/docs/changelog/2026-10-08)
## Answer WhatsApp calls in Bitrix24's call card [#answer-whatsapp-calls-in-bitrix24s-call-card]
**New.** A WhatsApp call now rings in Bitrix24's own call card as an ordinary
incoming call: the customer's name and number as the title, "WhatsApp" and the
line under it, and Bitrix24's Answer and Ignore buttons. Answer takes the call
right there — the card switches to connected, Bitrix24's timer runs, and Mute
and End work from the card. Ignore declines the call. If another operator
answers first, the other cards show "Taken by" with that person's name and
close. When the call ends the card shows why for a few seconds.
The call lives in the browser tab where it was answered; the card says so, and
the browser asks before the tab is closed or reloaded. If the browser refuses
the microphone, the WASync panel opens and offers the call window as before.
The separate call window still exists for that case, when the card does not
appear within 3 seconds, and for calling a customer back from the CRM widget.
Calling back from the card's own Call button is not available yet; use the
widget's Call button. Card texts are in the operator's language.
## The conversation inside the call card [#the-conversation-inside-the-call-card]
**New.** The call card's tab for a WhatsApp call is now named "WASync" (it was
"WhatsApp"). It shows a status line (incoming, connected with a timer, ended)
and, under it, the WhatsApp conversation with the caller on the number they
called: read the history and write while the phone rings or during the call.
Messages sent there go exactly where messages from the CRM widget go, and new
messages from the customer appear by themselves. An operator without access to
the called number sees only the call status. The conversation stays in the tab
after the call until the card is closed.
## Who is rung for an incoming call [#who-is-rung-for-an-incoming-call]
**Changed.** Everyone who handles a number can now be rung for its calls: the
operators of its Open Line or the employees with access to it in Connections →
Staff — either is enough. Until now a responsible manager with Staff access but
not in the Open Line queue could miss a call while online.
When a known customer calls, their responsible employee is still rung alone
first if they handle the number and are online. New: if nobody answers within
8 seconds — or straight away if the responsible is missing, offline or does not
handle the number — everyone online who handles the number is rung at once, up
to 5 people, while the responsible's card keeps ringing. The first to answer
takes the call. Bot users are never rung, and if nobody who handles the number
is online the call is saved as missed, as before. The 8 seconds are fixed.
## Each WhatsApp number creates its own lead [#each-whatsapp-number-creates-its-own-lead]
**New.** Under "New chats from unknown numbers" (when that rule is on), a new
option, off by default, makes an open lead or deal count for a conversation
only if it was created or linked from the same WhatsApp number. If a customer
writes to number X while their open deal came from another number or another
tool, WASync creates a new lead for X — assigned by the rule, attached to the
customer's existing CRM contact, carrying the Click-to-WhatsApp ad when there
is one — and leaves the old record untouched. Later messages on X go to that
same lead. With the option on, the CRM timeline, the record shown on the
conversation row and the stage filter follow the record of the number the last
message came through. Records created before 8 October 2026 have no number and
count as coming from another number.
## The employee filter follows what each person may see [#the-employee-filter-follows-what-each-person-may-see]
**Changed.** The "All employees" filter above the WASync Chat list now offers
only the colleagues whose conversations the person is allowed to see. Someone
set to "Only my records" no longer gets the filter, and someone set to "My
department" sees only colleagues from their department. Administrators and
people who see all chats get the same list as before. Nothing to configure: it
follows the visibility set in WASync Chat rules.
# 9 October 2026 (/docs/changelog/2026-10-09)
## A chat flow per Meta ad [#a-chat-flow-per-meta-ad]
**New.** The Start step of an inbound flow gains "From a specific ad": list the
Meta ad ids the flow should answer (for a campaign, list all of its ad ids; an
empty list means any ad). A number can now have several inbound flows, and the
one that starts is chosen by how specific it is: the matching ad first, then
keywords, then "any message". A flow bound to the number beats a
workspace-wide one, and within the same level the older flow wins. A message
from an unlisted ad, or from no ad, falls back to the keyword or any-message
flow. A human reply stops every inbound flow set to stop on it. The editor does
not yet warn when the same ad id is listed in two active flows, and the
simulator cannot yet pretend a message came from an ad.
## Insert a step on a connection line [#insert-a-step-on-a-connection-line]
**New.** In the Chat Flows editor, hovering a line between two steps shows a
"+" next to the "×". It opens the same step picker as the "+" on a step and
inserts the new step in between, keeping the branch or answer option the line
carried. The new step lands halfway along the line with its panel open.
## Flows no longer advance on a re-delivered message [#flows-no-longer-advance-on-a-re-delivered-message]
**Fix.** WhatsApp can deliver the same incoming message twice, for example
after a session re-sync or a retry. The copy was treated as a new answer from
the customer, so a flow could move on by itself. Copies are now ignored by
flows, lead creation and automations; the conversation already showed the
message once.
## Choose who is rung first for incoming calls [#choose-who-is-rung-first-for-incoming-calls]
**New.** Settings → "Incoming calls" (administrators) sets who is rung first
when a known customer calls: "The contact's responsible person" (the default,
as before), "The responsible person of the most recent open deal or lead"
(falling back to the contact's responsible when there is none), or "Both at
once". The rest is unchanged: only people online in Bitrix24 who handle the
number are rung, and after 8 seconds without an answer everyone online who
handles the number is rung too.
# 10 October 2026 (/docs/changelog/2026-10-10)
## Quick replies with "/" [#quick-replies-with-]
**New.** Quick replies are saved answers with a short command name, either for
the whole team or personal. They work in every chat: WASync Chat and the
WhatsApp tab in the CRM.
Type `/` at the start of the message box or after a space, and a picker opens
with every reply **already filled in for the open customer**. Keep typing to
filter (`/cuo`), choose with ↑ and ↓, and press Enter or Tab to insert — a
reply is never sent by itself, so you can edit it first. Esc closes the picker.
The ⚡ button next to the box does the same for mouse and phone users, and a
pencil in the picker edits a reply in place.
**Variables** are filled in on the server when the reply is inserted:
* `{{greeting}}` — Good morning, Good afternoon or Good evening in the
customer's language and at the customer's local time, both taken from the
country of their phone number (UTC when the country is unknown).
* `{{contact.first_name}}`, `{{contact.name}}` — the customer.
* `{{me.first_name}}`, `{{me.name}}` — the person sending.
* `{{record.title}}`, `{{record.stage}}`, `{{record.responsible}}` — the lead
or deal linked to the conversation.
* `{{crm.FIELD}}` — any CRM field of that lead or deal, for example
`{{crm.OPPORTUNITY}}`.
A reply can carry **versions in other languages**, and the picker chooses the
version that matches the country of the customer's phone number.
**Save from the conversation.** "⋯ → Save as quick reply" on any message you
sent turns it into a quick reply, with the customer's name, the greeting and
the record title replaced by variables automatically.
**Improve as you go.** Insert a reply, change it and send it, and WASync asks
"Update «/x» with this version?", so the saved text keeps up with how you
actually write.
**The Quick replies page** (⚡ in the app menu, for administrators and anyone
with write access to Settings) lists Team and Mine replies, with add, edit and
delete, language versions, how often and when each was last used, and "promote
to team" for a personal reply. Everything is available in all 20 languages.
Quick replies are not the canned responses of Bitrix24 Open Lines, which live
in the Contact Center and do not fill in CRM data. AI suggestions for replies
are not part of this release.
## Learning quick replies inside the product [#learning-quick-replies-inside-the-product]
**New.** Getting started needs no tutorial:
* **Hover card on ⚡** — "Type / in the box or click here. Enter inserts, then
edit before sending", with an example. The empty message box reads "Write a
message… (/ for quick replies)".
* **Empty states that teach** — an empty picker shows the two ways to get a
first reply (⋯ → Save as quick reply, or "Create one now"). Typing `/xyz`
with no match offers "Create «/xyz»" and inserts the new reply right after
it is saved. A key legend sits in the picker footer (hidden on touch
screens).
* **Quick replies page** — a two-line introduction and a three-step "How it
works" (Create → Use → Improve) with "?" explanations.
* **Starter kit** — while the list is empty, "Add these 4" offers four
suggested replies with variables: a greeting, a thank-you, a follow-up and a
request for details.
* **Live preview** — the reply form shows the text with sample values as you
type.
* **Placeholder chips** — when a reply contains hand-typed placeholders such as
"\[nombre]", "\[asesor]" or "\[saludo]", a chip offers the matching variable in
one click.
* **One-time tip** — after the third hand-typed message in a session, a tip
above the box suggests saving it ("Save this one?" / "Got it"); once
dismissed, it does not come back for that person.
* **Checklist** — the Getting started checklist on Connections gains "Create
your first quick reply".
## "Each number creates its own lead": no duplicate for existing records [#each-number-creates-its-own-lead-no-duplicate-for-existing-records]
**Fix.** With the option on, a customer whose open lead had been created by
Bitrix24's Open Channel, or before the option was switched on, got a second
lead on their next message, assigned to the fixed person. Now, when a contact
has only ever written to one of the workspace's numbers and their open lead or
deal was created after their first message there, that record counts and
nothing new is created. A record older than the first message, such as a deal
from another channel, still gets its own new lead, as designed.
## The "WhatsApp disconnected" alert now says why [#the-whatsapp-disconnected-alert-now-says-why]
**Improved.** When WhatsApp removes a linked device right after the number has
messaged many new contacts in a short time, the "WhatsApp disconnected" e-mail
and Bitrix24 notice now include the reason: how many new contacts were
messaged, that WhatsApp usually removes a linked device for this (especially
for a new number or when the recipients had not written first), and what to do
next — reply to people who write to you, add only a few new contacts a day, and
send bulk or promotional messages from a WhatsApp Business API number,
otherwise WhatsApp can block the number. Available in the eight languages of
the alert.
## A QR number moved to the Cloud API no longer alerts as "disconnected" [#a-qr-number-moved-to-the-cloud-api-no-longer-alerts-as-disconnected]
**Fixed.** When a number that was connected by QR code is later connected
through the WhatsApp Business API on the same workspace, the old QR connection
is retired automatically: no more "WhatsApp disconnected" alerts for it and no
endless reconnection attempts. Scanning the number by QR again revives it.
# 11 October 2026 (/docs/changelog/2026-10-11)
## No more doubled timeline comments [#no-more-doubled-timeline-comments]
**Fixed.** A reply sent from the Open Channel chat was written to the CRM
timeline twice: once when it was sent, and once more when WhatsApp echoed the
same message back. A message WhatsApp delivered twice could do the same. Both
copies are now ignored; a message typed on the phone or in WhatsApp Web is
still logged once, as before.
## One comment per message, on the conversation's record [#one-comment-per-message-on-the-conversations-record]
**New option.** Until now every WhatsApp message was logged on every lead,
deal, contact and company that carries the customer's number, which on a
busy workspace can mean three or four copies of the same comment.
Settings → **Log WhatsApp messages in the CRM timeline** gains a second
checkbox, **Write the comment only on the conversation's record**. With it on,
WASync writes one comment per message, on the record the conversation is
linked to: the open deal or lead, otherwise the contact. With "Each number
creates its own lead" on, that is the record of the number the message went
through. The default is unchanged.
## Sent messages are credited to the operator [#sent-messages-are-credited-to-the-operator]
**Changed.** Bitrix24 credits a timeline comment to the user whose
authorisation wrote it, and ignores any author we pass, so every comment used
to appear under the person who installed WASync, and "last activity" on a
record always showed that person.
For messages **sent** by an operator, from the Open Channel chat, WASync Chat
or the WhatsApp tab in the CRM, the comment is now written with that
operator's own authorisation, so Bitrix24 shows them as the author. This works
for everyone who has opened WASync at least once; otherwise, and for every
received message, robot send and automation, the comment is written by the
application's user as before. If you want that user to be a dedicated service
account, create it as a portal administrator and open WASync once with it.
## Move a conversation to another record [#move-a-conversation-to-another-record]
**New.** In WASync Chat, a conversation that is already linked to a lead or a
deal gets a **Change record** button next to the responsible person. It opens
the same search as "Link to record"; pick the lead, deal or contact, confirm,
and the conversation moves. Only WASync's link changes: the old record keeps
its history and nothing in Bitrix24 is edited. New messages are logged on the
new record. With "Each number creates its own lead" on, the link of that
number is replaced too, and the target must be a lead or a deal.
# 12 October 2026 (/docs/changelog/2026-10-12)
## "Any message" flows wait for a new conversation [#any-message-flows-wait-for-a-new-conversation]
**Fixed.** When several inbound flows run on one number (one per Meta ad plus
a general one), the general flow, set to *Any message — the first message of
a new contact*, could start the moment another flow finished: a customer who
came from an ad, answered the ad flow's questions and was handed to a person
received the general flow's greeting on his next "Ok".
Now the general flow starts only when no flow on that conversation ended in the
last 72 hours (the same window as *Don't start if we wrote first*, adjustable
per flow). A flow that was completed, handed to a person or cancelled counts;
one that was closed for inactivity does not. Flows started by an ad referral or
a keyword are unaffected: those are explicit intents and still start.
# 13 October 2026 (/docs/changelog/2026-10-13)
## MCP: send a file from an AI assistant [#mcp-send-a-file-from-an-ai-assistant]
**New.** The [MCP server](/docs/guides/mcp) has a sixth tool,
`send_whatsapp_file`. An assistant can send a document, image, audio or video
(up to 5 MB, with an optional caption) from one of the authorized numbers, the
same way `send_whatsapp_message` sends text.
Give the file as a direct `https` link in `url`, or as base64 in `data` with its
`mimetype`. A link is preferred: WASync downloads it, and links that point at
private networks, at WASync itself or at a web page rather than a file are
refused. Like the text tool, it needs the send permission and the assistant is
told to confirm the recipient and the file first, because a delivered file
cannot be recalled.
Nothing changes for existing integrations: `send_whatsapp_message` and the
other four tools are untouched, and the REST `POST /messages` media send keeps
its larger limit.
# 14 October 2026 (/docs/changelog/2026-10-14)
## Chat Flows: HTTP request step [#chat-flows-http-request-step]
**New.** A flow can ask an external system over HTTPS and use the answer:
method, URL and body with `{{VARIABLES}}`, headers (secret ones stored
encrypted), and a mapping from JSON paths to flow variables. Two outgoing edges:
success and error. The request is performed by a dedicated Cloudflare Worker,
never by WASync's servers, under a fixed policy (https only, public hosts, 10 s,
256 KB). See [HTTP request step in Chat Flows](/docs/guides/chat-flows-http-request).
No change to the REST API or the MCP tools.
## Guide: bring a number from another provider [#guide-bring-a-number-from-another-provider]
**New page.** [Bring a number from another provider](/docs/guides/bring-your-own-number)
walks through the in-app wizard for moving a WhatsApp Business API number you
already run elsewhere onto WASync: what comes with the number and what stays
behind, the checks the wizard runs before the move, exactly what to choose in
Meta's own window, and what to do right after (templates, the new two-step PIN,
when to cancel the old provider). No API change.
# 15 October 2026 (/docs/changelog/2026-10-15)
## Smart Processes (SPA) [#smart-processes-spa]
**New.** WASync now works on Bitrix24 Smart Process items as it does on leads and
deals. Rolled out in four steps between 14 October 23:30 and 15 October (Bucharest).
* **Robots on SPA automation rules.** *Send WhatsApp message*, *Send WhatsApp
template*, *Start a Chat Flow* and the AI robot run from a process's automation
rules; the recipient is the item's client (primary contact, other contacts,
company). Before this release the robots were listed there but failed with
"no phone".
* **WASync tab in the item card**, added automatically for existing processes, for
processes created later, and on *Reinstall placements*. A process without the
*Client* field gets an explanation instead of an error.
* **Conversations linked to items** in WASync Chat (type selector, search as the
operator), item responsible honoured by "Assigned to" and "only my records",
timeline comments on the item, closed items (final stages) treated like won or
lost deals.
* **Chat Flows on a process**: fields read and filled (custom fields included),
*Set stage → Move item*, activities, assignment; `{{record.stage}}` renders the
stage name.
* **Ad attribution** fills the item's native UTM fields when a click-to-WhatsApp
conversation is linked to it.
Guide: [Smart Processes (SPA) in WASync](/docs/guides/smart-processes). No change
to the REST API or the MCP tools; linked items appear as record type
`dynamic_` in WASync's data.
## Re-contact window after a closed lead [#re-contact-window-after-a-closed-lead]
**New option** under *Chat rules → New chats from unknown numbers*: **Re-contact
window after a closed lead (hours)**, 0 (off) to 720. When a customer writes again
within that many hours after their lead was marked **lost**, the conversation goes
back to that lead instead of a new lead being created. A second switch, **Reopen
the lost lead when the client writes back**, moves the lead back to an open
stage so it shows up again in the agent's list: the first open status of your
lead pipeline (usually *New*) or a stage you pick in **Stage the lead returns
to**. Without it the lead stays closed and the messages land in its timeline.
The window applies to leads created from new chats (fixed person or round-robin),
to the "already a contact but no open lead" option, and to Chat Flows that create
leads. Leads that were **won** (converted) are not affected: the conversation
already follows the deal made from them. Off by default on every portal.
Guide: [Leads from WhatsApp chats](/docs/guides/leads-from-whatsapp-chats).
# 16 October 2026 (/docs/changelog/2026-10-16)
## Stage picker in WASync Chat [#stage-picker-in-wasync-chat]
**New option** under *Chat rules → Stage picker in WASync Chat*, for Bitrix24
administrators: choose who may change the CRM stage of a conversation from the
WASync Chat header.
* **All operators** (default, unchanged behaviour).
* **Admins only**: other operators see the current stage as a read-only label.
* **Hidden (read-only for everyone)**: nobody changes the stage from WASync Chat;
the current stage stays visible.
The restriction is enforced on the server, not only in the interface, and Bitrix24
CRM permissions still apply on top of it. Required-fields rules for stage changes
are unaffected. No change to the REST API or the MCP tools.
Guide: [Leads from WhatsApp chats](/docs/guides/leads-from-whatsapp-chats).
## Bring a number without a WABA connection [#bring-a-number-without-a-waba-connection]
**Improved.** The **Bring a number** wizard no longer needs an existing WABA
connection. Open it from the link inside **Connect WhatsApp Business API** or
from the link on the Connections page. Without a WABA connection, the five
prerequisite checks become a checklist you confirm yourself; once a number is
connected, later moves get the automatic checks.
Guide: [Bring a number from another provider](/docs/guides/bring-your-own-number).
# 18 October 2026 (/docs/changelog/2026-10-18)
## What's new, inside the app [#whats-new-inside-the-app]
**New.** The sidebar of the WASync app in Bitrix24 has a **What's new** entry.
It opens the list of product releases, newest first, each with a version such
as `2026.10.18`, the date, and a few lines on what changed, with a *Learn more*
link to the matching page here when a change needs more than a sentence.
A small dot on the entry means there are releases you have not opened yet; it
disappears when you open the list, separately for each person. Entries that
only an administrator can act on (a Chat rules setting, for example) are shown
to administrators only. The list is translated into every language the app
offers.
Version numbers are dates: `2026.10.18` is the release of 18 October 2026, the
same date as this page. A second release on the same day would be
`2026.10.18.2`. Nothing on your side needs an update; the app is always the
current version.
## Choose the source of the record a flow creates [#choose-the-source-of-the-record-a-flow-creates]
**New.** In the Start card's *When it starts* section, lead and deal flows now
have a **Source** selector listing your CRM sources. The chosen source is
written on the contact, lead or deal the flow creates, so a flow can, for
example, leave the source on a placeholder such as "not selected" for your team
to fill in later, or stamp a campaign source of its own.
The default, *Automatic*, keeps today's behaviour: the record takes the source
of the WhatsApp Open Channel it came through. Nothing changes on existing flows
until you pick a source. A record the flow reuses instead of creating keeps its
own source.
## Only customers who never wrote to you before [#only-customers-who-never-wrote-to-you-before]
**New.** The *Customer writes first* trigger has a new option, **Only customers
who never wrote to you before**. With it on, the flow skips any phone number
that has ever exchanged a message with one of your WhatsApp numbers in WASync,
on this number or another, in either direction. An existing customer who writes
again gets no greeting and no new record; the message simply reaches your team.
Off by default on every existing flow, so nothing changes until you switch it
on in the trigger panel (Start card → *Change when it starts*). Note that the
option used to be implied by the trigger's description, *The first message from
a new contact*, while the flow actually started for anyone when no other rule
held it back; the description now says *Any message that starts a
conversation*.
## No second lead for a customer you are already working [#no-second-lead-for-a-customer-you-are-already-working]
**Fixed.** A lead flow that creates its record when it starts used to add a new
lead even when the customer's contact already had an open lead or deal. The flow
now binds to that open record instead (an open lead as a lead, an open deal as a
deal) and creates a lead only when there is none. This is the same rule the
"new chats from unknown numbers" lead follows, and the mirror of what deal
flows already did with an open deal in their pipeline.
## Records created by a flow follow your "new chats" rule [#records-created-by-a-flow-follow-your-new-chats-rule]
**Fixed.** A contact, lead or deal created by a flow when it started was owned
by the person who installed WASync, because Bitrix24 assigns a record to the
app's user when no responsible is given. With an Open Channel that routes to
the CRM responsible, that person then received every conversation of that
customer. Flow-created records now take the responsible from the same *New
chats from unknown numbers* rule in Chat rules (a fixed person or round-robin);
with the rule off, nothing changes.
## Find a step, and lines that light up [#find-a-step-and-lines-that-light-up]
**New, in the flow editor.** A **Find a step** box in the top bar searches
every step by name, message text, question options and keywords, branch names,
assignee and step type. Enter jumps to the next match and Shift+Enter to the
previous one; the card is selected, centred and flashes for a moment. Ctrl+F
(⌘F on a Mac) while on the canvas focuses the box.
When a step is selected, its incoming and outgoing lines turn green and come to
the front while the other lines fade, so a long connection can be followed on a
large canvas.
# 19 October 2026 (/docs/changelog/2026-10-19)
## WhatsApp from CRM Marketing and automation rules [#whatsapp-from-crm-marketing-and-automation-rules]
**New.** WASync registers itself as a Bitrix24 message provider, **WASync
WhatsApp**. Choose it in a CRM Marketing campaign under *Send using*, in the **Send
message** automation rule, or in the message button of a lead, deal, contact or
company (Bitrix24 labels that button *SMS*). The customer receives a WhatsApp
message from your WASync number, and it lands on the record's timeline. How it chooses the number and what happens on a Business
API number outside the 24-hour window:
[WhatsApp from CRM Marketing and automation rules](/docs/product/crm-records#whatsapp-from-crm-marketing-and-automation-rules).
Existing portals get the provider when the app is next updated from the Market,
or on request.
## Campaign and ad set on conversations from ads [#campaign-and-ad-set-on-conversations-from-ads]
**New.** Give WASync a Meta Ads token (System User, `ads_read`) in Settings and
every conversation from a Click-to-WhatsApp ad carries the campaign id in
`UTM Campaign`, the ad set id in `UTM Term` and the ad id in `UTM Content`,
with their names on the timeline note. Without a token nothing changes.
[Campaign and ad set on conversations from ads](/docs/guides/meta-ads-campaign-attribution).
## Flows and "Each number creates its own lead" [#flows-and-each-number-creates-its-own-lead]
**Fixed.** With the option on, a flow that starts for a known customer reused
any open lead or deal of the contact, including one from another channel. It
now reuses only the record that belongs to the number the customer wrote to,
otherwise it creates the number's own lead.
[Which record a flow creates or binds to](/docs/product/chat-flows#which-record-a-flow-creates-or-binds-to).
## Reliability [#reliability]
* **Fixed.** On portals with many advisors online at once, the WASync Chat list
asked Bitrix24 for the responsible person of every conversation on every
refresh and hit Bitrix24's request limit at the start of the day, which also
refused sign-ins and new leads for a few minutes. The list now reads from its
cache.
* **Fixed.** Automation rules (*Send WhatsApp Message*, *Send WhatsApp
Template*) stopped working on portals where the portal's first user had been
deactivated. They now run under the user who installed WASync.
* **Fixed.** An incoming WhatsApp message that arrived in the few seconds of a
WASync deployment could be lost. The message is now kept and saved as soon
as the deployment settles.
# 20 October 2026 (/docs/changelog/2026-10-20)
## A refused send outside the 24-hour window says why [#a-refused-send-outside-the-24-hour-window-says-why]
**Fixed.** On a WhatsApp Business API number, typing to a contact who had never
written (or whose only "incoming" item was a missed call) left the composer
open; the send was refused by the 24-hour rule and the message simply
disappeared. Now the composer locks for such contacts with the explanation and
the **Pick a template** button, in WASync Chat and in the CRM tab alike, and if
a send is still refused the reason stays on screen until the customer replies.
[Templates on Business API numbers](/docs/product/wasync-chat#templates-on-business-api-numbers).
## A closing message when a run stops for inactivity [#a-closing-message-when-a-run-stops-for-inactivity]
**New.** **If no reply** has a fourth field, **When the run closes, send this
message**, both in Flow settings and on each question. Write something like
"We didn't hear back, so this conversation was closed. Whenever you want to
continue, just send us a new message here." and the customer receives it the
moment the run closes. Leave it empty to close silently, as before. The preview
simulator plays it after the close.
[Inactivity reminders and closing](/docs/product/chat-flows#inactivity-reminders-and-closing).
## The reminder is the bot's message, not your team's [#the-reminder-is-the-bots-message-not-your-teams]
**Fixed.** The inactivity reminder was stored like a message typed by a person.
For a customer who answered only after the run had closed, that made their
reply look like an answer to your team, and **Flows do not start on a reply to
your team** kept the flow from starting again. Reminders and closing messages
are now recorded as the flow's own messages: they never count as a colleague
taking over, and a late reply starts a new run as the documentation always
said.
## No second lead when an open lead already holds the number [#no-second-lead-when-an-open-lead-already-holds-the-number]
**Fixed.** A **Customer writes first** lead flow found the customer's CRM
contact and that contact's open lead or deal, but an open lead that carries the
number without any CRM contact on it, typically a lead imported from another
tool, stayed invisible, so the flow created a second lead next to it. The flow
now also binds to such a lead.
[Which record a flow creates or binds to](/docs/product/chat-flows#which-record-a-flow-creates-or-binds-to).
## Edits and deletions in a group stay in the group chat [#edits-and-deletions-in-a-group-stay-in-the-group-chat]
**Fixed.** When a member edited or deleted a message inside a WhatsApp group
synced to a Bitrix24 group chat, the "message edited" / "message deleted" note
was sent to the Open Line as if the group were a person, which opened a
one-to-one chat and a lead whose phone number was the group id. The note now
goes to the bridged group chat, and a group id is refused as a phone number
when sending from a CRM record. Leads created this way can be deleted; they
carry a phone of 18 digits starting with `1203`.
## Videos and documents sent from Bitrix24 no longer fail at 15 seconds [#videos-and-documents-sent-from-bitrix24-no-longer-fail-at-15-seconds]
**Fixed.** On a WhatsApp QR number, a file sent from an Open Channel or from
the WASync tab is downloaded and uploaded to WhatsApp in one step, and a large
video can take 20 to 30 seconds. Our side gave up after 15 seconds and marked
the message as failed in Bitrix24 and in the thread, while the file still
reached the customer, so operators sometimes sent it a second time. Media sends
now wait up to 90 seconds; short text messages keep their quick timeout.
# 21 October 2026 (/docs/changelog/2026-10-21)
## One run per customer, even when the first messages come in a burst [#one-run-per-customer-even-when-the-first-messages-come-in-a-burst]
**Fixed.** When a customer sent two or three messages within a few seconds
before the bot answered ("hi", "good evening", "where are you?"), each message
arrived as its own request and each could start the flow. The second run
replaced the first, but the first had already begun its opening sequence and
kept sending it, so the customer saw every opening message twice, sometimes
three times. Now the first message of a burst is the only trigger, and a run
that has been replaced or cancelled stops at its next step instead of finishing
its sequence.
[When a flow starts](/docs/product/chat-flows#when-a-flow-starts).
# 22 October 2026 (/docs/changelog/2026-10-22)
## Lead per number: a new contact gets its own lead, not another tool's old one [#lead-per-number-new-contact-gets-its-own-lead]
**Fixed.** With **Each number creates its own lead** switched on, a flow run
for a contact that did not exist yet could bind to an older open lead that
merely held the phone number, typically a lead created by another WhatsApp
tool running in parallel. That lead was not this number's record, so when the
customer answered the agent, the "new conversations" rule created a second
lead and assigned it again. Now, under that option, a first-time contact gets
the number's own lead at the start of the flow, and the next reply lands on
it. Portals without the option are unchanged.
[Which record a flow creates or binds to](/docs/product/chat-flows#which-record-a-flow-creates-or-binds-to).
# 23 October 2026 (/docs/changelog/2026-10-23)
## Pick which number to message from a CRM record [#pick-which-number-to-message-from-a-crm-record]
**New.** The WASync tab of a lead, deal, contact or company used to chat with
the first phone of the record only. It now lists every number the record can
reach, including the phones of each contact of a deal, and shows a picker when
there is more than one. It opens on the number you used last on that record.
[Records with several phone numbers](/docs/product/crm-records#records-with-several-phone-numbers).
## Start a conversation with a number that has no chat yet [#start-a-conversation-with-a-number-that-has-no-chat-yet]
**New.** WASync Chat only listed existing conversations, so a number nobody
had written to yet could not be reached from there. Search the full number;
when nothing matches, the list offers to start the conversation, with your
sending number of choice and a template on Business API numbers. An employee
limited to their own records can start one with a number that is on a record
assigned to them.
[Starting a conversation with a number that has no chat yet](/docs/product/wasync-chat#starting-a-conversation-with-a-new-number).
# 27 October 2026 (/docs/changelog/2026-10-27)
## Options of a question as buttons [#options-of-a-question-as-buttons]
**New.** A question step can show its options to the customer: as buttons (up
to 3) or a list (up to 10) on WhatsApp Business API numbers, and as a numbered
list on QR numbers, where the customer can answer with the number. Until now
the customer only saw the question text.
[Showing the options as buttons](/docs/product/chat-flows#showing-the-options-as-buttons).
## Keywords separated with commas [#keywords-separated-with-commas]
**Fixed.** In the keywords of an option, a typed comma disappeared at once, so
several keywords could not be entered. Commas and semicolons now both separate
keywords, and keywords already saved with semicolons (`continuar;1;si`) are
read as separate keywords.
## Send a message later [#send-a-message-later]
**New.** Next to **Send** in WASync Chat and the WASync tab of a CRM record, a
clock schedules the message for a date and time up to 30 days ahead; it can be
cancelled until it goes out. On WhatsApp Business API numbers it goes out only
if the customer wrote in the 24 hours before.
[Sending a message later](/docs/product/wasync-chat#sending-a-message-later).
## Voice notes transcribed to text [#voice-notes-transcribed-to-text]
**New.** An administrator can turn on transcription of WhatsApp voice notes in
Settings. The text appears under the player in WASync Chat and the CRM tab, and
in the export. It runs on the workspace's own OpenAI, Groq or ElevenLabs account.
[Voice-note transcription](/docs/product/wasync-chat#voice-note-transcription).
## WhatsApp forms in Chat Flows [#whatsapp-forms-in-chat-flows]
**New.** A Chat Flows step sends a form the customer fills in inside WhatsApp,
with up to 8 fields; each answer can land in a CRM field. WhatsApp Business API
numbers only.
[WhatsApp forms](/docs/product/chat-flows#whatsapp-forms).
## Carousel templates [#carousel-templates]
**New.** Marketing templates with 2 to 10 swipeable cards, each with an image or
video, a short text and buttons, created in the WASync template builder and sent
from the chat, flows and robots.
[Carousel templates](/docs/product/wasync-chat#carousel-templates).
## Link click tracking [#link-click-tracking]
**New.** With link tracking on, links sent from WASync become short links; the
message and the CRM timeline show when the customer opened them.
[Link click tracking](/docs/product/wasync-chat#link-click-tracking).
## Re-contact window covers lost deals [#re-contact-window-lost-deals]
**Fix.** With one lead per number, a reply to a deal marked lost inside the
re-contact window goes back to that deal instead of creating a new lead.
[Re-contact window](/docs/guides/leads-from-whatsapp-chats#re-contact-window-after-a-closed-lead).
## Allow the flow again restarts the flow at once [#allow-flow-again-restarts]
**Fix.** **Allow the flow again** in WASync Chat now also clears the wait after
a finished flow, so the next message starts an *Any message* flow right away.
[Chat Flows](/docs/product/chat-flows).
# 28 October 2026 (/docs/changelog/2026-10-28)
## Ad attribution on leads created from the chat [#ad-attribution-on-leads-created-from-the-chat]
**Fixed.** When a customer wrote from a click-to-WhatsApp ad and no lead or
deal existed yet (for example on a number without an Open Line), a lead created
later with **Create lead** in WASync Chat stayed without UTM fields. The lead
or deal you create or link from the chat now receives the ad's UTM fields,
campaign and timeline note, when the ad message is from the last 7 days.
[Ad attribution](/docs/product/crm-records#ad-attribution).
# 29 October 2026 (/docs/changelog/2026-10-29)
## Templates no longer get a phone number as the name [#templates-no-longer-get-a-phone-number-as-the-name]
**Fixed.** The template window fills `{{1}}` with the contact's first name. For a
contact with no name, that "name" was its phone number, and it went into `{{1}}`
even when `{{1}}` was a date. The window now fills `{{1}}` only with a real name and
only when the template describes `{{1}}` as a name; otherwise it stays empty for
you to type.
[Templates on Business API numbers](/docs/product/wasync-chat#templates-on-business-api-numbers).
## Reports for people who are not administrators [#reports-for-people-who-are-not-administrators]
**New.** In **Staff → Access**, the new **Reports** area gives a non-administrator
the Reports page and its export, and nothing else from the console.
[Reports for non-administrators](/docs/product/connections#reports-for-non-administrators).
# 31 October 2026 (/docs/changelog/2026-10-31)
## Customer videos and large files always reach the Open Channel [#customer-videos-and-large-files-always-reach-the-open-channel]
**Fixed.** A large video or file a customer sent could be refused by Bitrix24 when it
tried to fetch it, and the operator never saw the message. Files are now handed
over from a link that is ready at once; a file sent without a caption gets a short
one in the portal's language (for example “🎬 Video” or “📎 Document · offer.pdf”);
and if Bitrix24 still refuses the file, the message is sent again with the caption
and a link to the file.
[Bitrix24 Open Channels](/docs/product/settings#bitrix24-open-channels).
## A message made only of empty CRM fields no longer stops the flow [#a-message-made-only-of-empty-crm-fields-no-longer-stops-the-flow]
**Fixed.** A Chat Flows message made only of a CRM field, such as a promo text kept
in a deal field, stopped the whole conversation when that field was empty on the
record, and every later step was lost. The step is now skipped and the flow
continues, and the editor warns you when a message is made only of fields.
[Messages built from CRM fields](/docs/product/chat-flows#messages-built-from-crm-fields).
## Fill in a field can write only when the field is empty [#fill-in-a-field-can-write-only-when-the-field-is-empty]
**New.** The Chat Flows step **Fill in a field** has a new switch, **Only if the
field is empty**, off by default so existing flows behave as before. When it is on
and the field already has a value, nothing is written and the flow continues, so a
later flow can no longer overwrite a lead's origin or UTM values.
[Fill in a field](/docs/product/chat-flows#fill-in-a-field).
## A flow can save a lead's origin before the lead exists [#a-flow-can-save-a-leads-origin-before-the-lead-exists]
**New.** A **Fill in a field** step has a second switch, **If there is no CRM record
yet, save as pending origin**. On a conversation without a lead, the value (for
example a UTM source or the lead source) waits on the contact, WASync Chat shows it
under the header, and it is written into the lead when someone creates it from the
chat. Linking an existing record never changes its origin.
[Save the origin when there is no lead yet](/docs/product/chat-flows#pending-origin).
## Call-permission templates only on numbers with calls on [#call-permission-templates-only-on-numbers-with-calls-on]
**Fixed.** WhatsApp approves a template with a call-permission request even for a
number without WhatsApp calls, then refuses every send of it. The template builder
now offers the call-permission request only when calls are on for the number, the
template picker marks such templates **Needs calling** and greys them out on a
number without calls, and a send from the chat, an automation rule or a Chat Flow
is refused before it reaches WhatsApp, with the reason shown.
[Turning calls on for a number](/docs/product/calls#turning-calls-on-for-a-number).
## When a contact changes their WhatsApp number [#when-a-contact-changes-their-whatsapp-number]
**New.** When a contact moves to a new WhatsApp number on a Business API
number, the conversation gets a note, the new number is added to the CRM
record (the old one stays) with a timeline comment, and the old conversation
shows a banner that opens the new one. The CRM update can be turned off in the
Chat rules.
[When a contact changes their number](/docs/product/wasync-chat#when-a-contact-changes-their-number).
## Open Channel chats named from CRM fields [#open-channel-chats-named-from-crm-fields]
**New.** A chat title template in Settings, such as
`WA: {{company.UF_CRM_CODE}} - {{contact.name}}`, names every Open Channel chat
when an operator first answers and again when its CRM record changes; the
**Set WhatsApp chat title** automation step sets it at any stage. A chat someone
renamed by hand is kept.
[Chat title from CRM fields](/docs/product/settings#chat-title-from-crm-fields).
## Chat files open with a fresh link and can be downloaded [#chat-files-open-with-a-fresh-link-and-can-be-downloaded]
**Fixed.** In a chat left open for a while, clicking an older photo or file could
show an "expired" page instead of the file. Photos, videos and files now open with
a link made at the moment you click, photos open full size inside the app, and
each file has a **Download** button that saves it with its original name.
[Opening and downloading files](/docs/product/wasync-chat#opening-and-downloading-files).
## See when a contact uses disappearing messages [#see-when-a-contact-uses-disappearing-messages]
**New.** On QR connections, the conversation header in WASync Chat and in the
WASync tab of a CRM record shows a label such as **Disappearing: 24 h**,
**7 days** or **90 days** when the contact has disappearing messages on, so you
know a quote may vanish from their phone. Your history in WASync and Bitrix24 is
kept.
[Disappearing messages](/docs/product/wasync-chat#disappearing-messages).
## My conversations only through the number they are on [#my-conversations-only-through-the-number-they-are-on]
**New.** With **Each number creates its own lead**, a new switch in the Chat
rules makes an employee who sees only their own (or their department's)
conversations see a conversation only through the lead or deal of the number
it is on. A colleague's lead on another number no longer opens it, and sending
from a number whose record belongs to a colleague is refused. Off by default;
with it off, the conversation header explains when you see a conversation
because of your record on another number.
[Who sees which conversations](/docs/product/wasync-chat#who-sees-which-conversations).
## Warning when Meta routes a number to your old provider [#warning-when-meta-routes-a-number-to-your-old-provider]
**New.** A number brought from another provider can look connected while Meta's
Conversation routing still sends its conversations to the old provider: no
messages arrive and every send fails with error 131070. WASync now checks this
after the move and several times a day, shows a red warning on the number in
**Connections** and in the Templates window with the exact steps in Meta
Business Suite, and a failed message shows what to do instead of Meta's code.
[Conversation routing at Meta](/docs/product/connections#conversation-routing-at-meta).
## Customers who write from a WhatsApp username [#customers-who-write-from-a-whatsapp-username]
**New.** Customers who write from a WhatsApp username with a hidden number now
reach WASync Chat and the Open Channel as **@username** on WhatsApp Business API
numbers; replies, templates and the Open Channel work without a phone number. Their
messages used to be dropped. When the same customer later writes from their phone
number, both conversations get a note pointing to each other.
[Contacts without a phone number](/docs/product/wasync-chat#contacts-without-a-phone-number).
## Sequential stages in WASync Chat [#sequential-stages-in-wasync-chat]
**New.** A new chat rule, **Sequential stages**, off by default: from WASync Chat,
an operator can move a lead or deal only to the next stage of its pipeline, with
one step back and the won or lost stages allowed by default. A jump is refused
with "Move to *next stage* first". Moves made directly in Bitrix24 are not
affected.
[Sequential stages](/docs/product/wasync-chat#sequential-stages).
**Changed.** The closing option is now two: **Allow "Lost" from any stage** (on
by default) and **Allow "Won" from any stage** (off by default), so a lost
record closes from any stage while "Won" still follows the pipeline.
# 2 November 2026 (/docs/changelog/2026-11-02)
## More control over chat titles from CRM fields [#more-control-over-chat-titles-from-crm-fields]
**New.** The chat title template in Settings can now be limited to the Open
Channels you tick, and it has two new fields, `{{line.name}}` (the channel's name)
and `{{line.phone}}` (the WhatsApp number). With **Skip the rename when a field is
empty** on, a chat keeps its current title until every field in the template has a
value, instead of leaving the empty ones out. Each rename WASync makes adds the
note “WASync set the chat title: «…»” to the conversation's CRM record (on by
default, can be switched off in the same card). The **Set WhatsApp chat title**
automation step also works on companies, renaming the chats of the company's
contacts.
[Chat title from CRM fields](/docs/product/settings#chat-title-from-crm-fields).
## New AI step in Chat Flows [#new-ai-step-in-chat-flows]
**New.** Chat Flows have an **AI reply** step: the flow answers the customer with
your own AI key (Chat Flows → AI assistant), from the context you choose — the last
messages of the conversation, the CRM fields you pick and its own earlier
answers. The AI takes no actions; messages that look like prompt injection are
caught before the call, links to other sites are removed from the answer, and
when anything goes wrong the conversation goes to a person by default. Pro
(paid) numbers only.
[AI step](/docs/product/chat-flows#ai-step).
## AI step: choose from a list [#ai-step-choose-from-a-list]
**New.** The AI step has a second mode, **Choose from a list**: the AI picks one
of the options you list (2–12) and the flow continues on that option's line.
Nothing the AI writes is sent; an answer that is not one of your options goes to
**Anything else** or to your fallback. The step can ask the customer a question
first and classify the reply.
[Choose from a list](/docs/product/chat-flows#ai-choose-from-a-list).
## Knowledge for the AI step [#knowledge-for-the-ai-step]
**New.** Add texts, PDFs and web pages once in **Chat Flows → AI assistant**, then pick in each AI step which of them it may use. Before every answer
the AI gets the passages closest to the customer's message; with **Answer only
from the knowledge** on, a question the knowledge does not cover goes to your
fallback instead of getting an invented answer.
[Knowledge base](/docs/product/chat-flows#knowledge-base).
## Automation-started flows check the country code [#automation-started-flows-check-the-country-code]
**Improved.** A chat flow started by a Bitrix24 automation rule no longer starts
on a phone without a country code (for example a 10-digit national number). The
lead or deal gets a timeline comment that explains how to fix it. A message to a
number that is not on WhatsApp now says “This number is not on WhatsApp” under
the bubble.
[When a flow starts](/docs/product/chat-flows#when-a-flow-starts).
## Set up and test the AI in one place [#set-up-and-test-the-ai-in-one-place]
**New.** Chat Flows has an **AI assistant** tab with your AI key and model, the
knowledge and a **Try a question** box that shows the answer and the passages it
used. The AI step now lists what is missing (key, licence) with a fix on the
spot, lets you paste knowledge without leaving the editor and can test a question
with the changes you have not saved yet. The cards moved out of Settings, which
keeps a shortcut.
[The AI assistant tab](/docs/product/chat-flows#ai-assistant-tab).
## PDFs and videos open inside the app [#pdfs-and-videos-open-inside-the-app]
**Improved.** A PDF or a video in a conversation now opens in a window over the
chat, with **Open** and **Download** next to it, instead of a new browser tab.
Some browsers add an extra code to addresses opened in a new tab, and the file
storage then refused the link. A PDF over 25 MB, or on a browser that cannot show
PDFs in a page, offers Open and Download only.
[Opening and downloading files](/docs/product/wasync-chat#opening-and-downloading-files).
# 3 November 2026 (/docs/changelog/2026-11-03)
## Large batches from automation rules no longer fail [#large-batches-from-automation-rules-no-longer-fail]
**Fixed.** When an automation rule ran the **Send WhatsApp message**, **Send
WhatsApp template (WABA)** or **Start chat flow** robot on hundreds of records
at once, Bitrix24 limited how fast WASync could read the records and many runs
failed with “Bitrix24 did not answer while we looked up the phone number”.
WASync now queues those runs and sends them at a steady pace, about one per
second for your portal, in order. Bitrix24 shows the robot as *queued* and the
message follows within minutes.
[Large batches](/docs/product/crm-records#large-batches).
## Replies to robot messages stay on their record [#replies-to-robot-messages-stay-on-their-record]
**Fixed.** With one lead per number turned on, a WhatsApp message sent by the
**Send WhatsApp message** or **Send WhatsApp template (WABA)** robot did not
bind the conversation to the lead or deal it ran on, so the customer's reply
opened a new lead. The conversation is now bound to that record, exactly like a
message sent from the record's widget.
[Robot messages and the record](/docs/product/crm-records#robot-messages-and-the-record).
# 4 November 2026 (/docs/changelog/2026-11-04)
## Sending from an open record moves the chat off a closed one [#sending-from-an-open-record-moves-the-chat-off-a-closed-one]
**Fixed.** With one lead per number turned on, a conversation whose record on
that number was already won or lost stayed on it, even when an advisor sent a
message from the customer's open deal. The reply then opened a new lead for the
unknown-numbers rule. Now a message sent from an open lead, deal or Smart
Process item moves the conversation to that record, and a reply to a closed
record first looks for the contact's open deal or lead before creating one.
Off by default: write to support to turn it on for your portal.
[When the number's record is closed](/docs/product/crm-records#when-the-numbers-record-is-closed).
## Mexican numbers typed with +52 stay in one conversation [#mexican-numbers-typed-with-52-stay-in-one-conversation]
**Fixed.** WhatsApp files a Mexican mobile as `521` followed by the 10-digit
number, while people usually type `+52` and the 10 digits. A message sent to a
number typed the second way reached the customer but opened a second, empty
conversation, and the customer's reply arrived in the first one. Both
spellings now open the same conversation; duplicates created before the fix
will be merged on our side.
[Default country](/docs/product/settings#default-country).
## Lead flows can create the lead without a new contact [#lead-flows-can-create-the-lead-without-a-new-contact]
**New.** A lead flow that creates the lead when the customer writes first can
now skip creating a CRM contact. Tick **Create only the lead (no new contact)**
on the Start card: the lead is created on its own, and linked to a contact only
when one with the customer's phone already exists.
[Create only the lead, without a new contact](/docs/product/chat-flows#lead-only-without-a-new-contact).
## One CRM timeline comment per day per record [#one-crm-timeline-comment-per-day-per-record]
**New.** A busy conversation no longer fills a deal's timeline with one comment
per WhatsApp message. Turn on **One comment per day per record** under **CRM
Timeline Log** in Settings: each record then gets one comment per day, and every
message is added to it as a line with the time, the direction and the
operator's name.
[One comment per day per record](/docs/product/crm-records#one-comment-per-day-per-record).
# Changelog (/docs/changelog)
This is the dated record: when something arrived. How each feature works today
is documented under [Product](/docs/product) for the Bitrix24 app and under
[Guides](/docs/guides) and the [API reference](/docs/api-reference) for the
API, and the entries below link there.
Breaking changes to the API are always announced here before they ship. New
event types are announced here too, which is why unknown `event` values in a
webhook payload should be ignored rather than treated as errors.
# Connection types (/docs/concepts/connection-types)
Every connection reports a `provider`, and it is one of two values:
| `provider` | What it is | How it is onboarded |
| ----------- | ---------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| `qr` | An ordinary WhatsApp number (sold as **WAPP**), paired by linking a device. | `POST /connections`, then scan a QR or type a pairing code. Entirely self-serve through the API — no Meta Business account. |
| `cloud_api` | A WhatsApp Business number (sold as **WABA**) registered with Meta, on the official Cloud API. | Meta embedded signup, not this API. |
Both types send and receive through the same endpoints, with the same request
bodies and the same two message ids. If you assumed QR-from-your-own-app was
impossible: it is not.
## Where they actually differ [#where-they-actually-differ]
**Webhooks.** Events fire for `qr` connections only. `cloud_api` connections
emit no webhooks today — poll `GET /messages` and `GET /connections/{id}` for
those.
**Pairing.** `POST /connections/{id}/pairing-code` is a `qr` concept. A
`cloud_api` number answers `409 not_supported_for_provider`; that is a permanent
refusal, so do not retry it.
**Send latency.** A `qr` send normally takes 1–7 s (up to \~20 s for a long text)
and can take \~2.5 minutes on the self-heal path. A `cloud_api` send is about 1 s.
Size your HTTP timeout for the slow one: **at least 180 s**.
**Marking read.** `POST /messages/read` marks the whole chat on a `qr`
connection. A `cloud_api` connection can only mark one specific message, so a
`phone`-only request resolves your most recent inbound message from that number
automatically.
**Volume.** A newly paired `qr` number has 72-hour warm-up caps on hourly volume;
exceeding one returns `429 warmup_limited`. See
[Licences & trial](/docs/concepts/licences-and-trial).
**Session health.** A `qr` connection is bound to a phone that has to stay
reachable, so it can drop and be asked to re-pair — that is what
`connection.disconnected` / `connection.connected` and the `needs_reconnect` flag
are for. A `cloud_api` connection never scans anything and does not have that
failure mode.
`provider` maps to `null` rather than passing through an unrecognised value. If
a new connection kind is ever added it will be named here deliberately, so
branching on `qr` / `cloud_api` today is safe — but treat `null` as "a kind this
client does not know about" rather than crashing on it.
# Errors & idempotency (/docs/concepts/errors-and-idempotency)
## Branch on the code, not the status [#branch-on-the-code-not-the-status]
Errors come back as `{ "error": "" }`. The status alone is not enough to
decide what to do — two `403`s can need opposite fixes.
| Status | Code | What it means, and what to do |
| ------ | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| 401 | `invalid_key` | Unknown or revoked key. Create a new one; retrying will never help. |
| 403 | `ip_not_allowed` | The key has an IP allowlist and this address is not on it. **The key is fine** — add the address at `developers.wasync.app/keys`. Do not rotate. |
| 403 | `insufficient_scope` | The credential lacks the scope this endpoint needs. |
| 403 | `forbidden_portal_kind` | `POST /connections` on a Bitrix24 portal. Connections there are created by the portal admin. |
| 400 | `invalid_phone_number` | `phoneNumber` must be digits only, no leading `+`. |
| 400 | `invalid_webhook` | The URL must be HTTPS on a publicly reachable host. |
| 402 | — | The connection's licence has lapsed. See [Licences & trial](/docs/concepts/licences-and-trial). |
| 409 | `already_connected` | The session is live; there is nothing to pair. |
| 409 | `not_supported_for_provider` | A `qr`-only operation on a `cloud_api` number. Permanent — do not retry. |
| 422 | `recipient_not_on_whatsapp` | WhatsApp could not find an account for the recipient. Check the number is in international format (country code first, no leading zero) and that the person uses WhatsApp. Permanent for that number — do not retry unchanged. |
| 502 | `send_failed` | WhatsApp could not deliver for a reason that is not about the recipient (session or provider). Retry after a short delay; if it persists, check the connection's status. |
| 429 | `warmup_limited` | Hourly warm-up cap on a new `qr` number. Back off in minutes. |
| 429 | `rate_limited` | Abuse limiter. Honour `Retry-After` when present; keep a default back-off regardless. |
| 502 | `pairing_code_unavailable` | An ordinary outcome, not an outage — fall back to the QR. |
`Retry-After` is not guaranteed on every 409/429, so never make your back-off
depend on it.
## Idempotency on `POST /connections` [#idempotency-on-post-connections]
Creating a connection provisions a WhatsApp session and consumes a paid slot. A
client that times out and retries would otherwise create a *second* connection —
and you would silently pay for two slots for one customer. The optional
`Idempotency-Key` header closes that hole. It is supported on
`POST /connections` **only**; leave it off and behaviour is exactly as before.
A key is any opaque string up to 255 characters, namespaced to your workspace
(two partners using the same literal string never collide), and it lives **24
hours** from the first request that used it.
**New key**
— the connection is provisioned as normal →
`201 Created`
.
**Same key, same body, within the TTL**
— the same connection is returned, nothing is provisioned again:
`200 OK`
plus the response header
`Idempotency-Replayed: true`
. The
`qr`
in that response is freshly fetched, not the code stored at first creation: pairing codes rotate roughly every 20 seconds, so a replayed stale QR would simply fail to scan.
**Treat 200 as success, not as an error.**
**Same key, different body, within the TTL**
—
`400 { "error": "idempotency_key_reuse" }`
. The comparison is a hash of the canonical body, so JSON key order does not matter.
**Same key, first request still in flight**
—
`409 { "error": "idempotency_in_progress" }`
with
`Retry-After: 1`
. Honour it and retry with the
*same*
key.
A key longer than 255 characters is rejected with
`400 { "error": "idempotency_key_invalid" }` — never truncated. A blank or
whitespace-only header counts as absent. The response body shape is unchanged in
all cases.
A fresh UUID (`crypto.randomUUID()`) minted right before the call and reused
only by that call's retries. Do **not** use one key per process, per API key,
per day, or a constant. A key that coarse means the second customer you onboard
is handed the *first* customer's connection back instead of his own.
## Idempotency on sends [#idempotency-on-sends]
`POST /messages` takes an `idempotencyKey` in the **body** (not a header). Always
send one — a UUID per logical send.
* On any error **or timeout**, retry with the *same* key. A new key means a
second real WhatsApp message on someone's phone.
* On `409 in_progress`, poll with the same key: honour `Retry-After` when
present, otherwise back off about 5 s.
* A slow send is not a failed send. Set your HTTP timeout to at least 180 s.
# Concepts (/docs/concepts)
The model behind the API: workspaces, connection kinds, licences, scopes and failure handling.
# Licences & trial (/docs/concepts/licences-and-trial)
Each WhatsApp **number** needs an active licence to send and receive through the
API. There is no free tier; there is a **7-day free trial** on every new number.
## Prices [#prices]
One price, in USD, per number, per month — the same whether the number is a
`qr` connection or a `cloud_api` connection, and whatever you send through it.
| | Price |
| ------------------------------------------------------------------- | ------- |
| A WhatsApp number in a standalone workspace | **$12** |
| API access to a number that lives on a Bitrix24 portal (API add-on) | **$12** |
No seats, no message caps, no per-request fees on our side. Meta's own
conversation charges for `cloud_api` numbers are billed by Meta to your
WhatsApp Business Account, not by us. Activation and invoices live at
[https://developers.wasync.app/billing](https://developers.wasync.app/billing).
## Slots [#slots]
A **slot** is capacity, not a phone number, and not something you bind to a
customer:
* It attaches when a number actually pairs — creating a connection record does
not consume one until then.
* Deleting a connection returns its slot to the pool carrying whatever time is
left on it. The next number you connect picks it up automatically.
* That is what lets you move a paid slot from a departing customer to a new one
without paying twice or asking anybody to intervene.
Check `GET /account` before you promise capacity: `slots.available` is what
`POST /connections` can still consume with an active licence, and
`slots.nextExpiry` is the date you have to renew before.
## Deleting a number, closing a workspace [#deleting-a-number-closing-a-workspace]
Both are yours to do, from the **Billing** screen of the developer console or
over the API.
* **Delete a number** — `DELETE /v1/connections/{id}`, or the **Delete** button
on the connection row. Its WhatsApp session is closed, every message stored
for it is removed, and a paid slot returns to the pool as described above.
* **Close a workspace** — the **Close workspace** button on a workspace with no
connections left. It removes the workspace together with its API keys and its
webhook configuration, so anything still calling the API with those keys stops
working.
A workspace that still has numbers cannot be closed: delete them first, so the
phones are unlinked instead of leaving sessions behind. A workspace with a live
slot subscription cannot be closed either — cancel the subscription first.
Neither action can be undone. What does survive is the record that a number
already used its free trial: closing a workspace and opening a new one does not
give the same phone a second trial.
## The trial [#the-trial]
A new number starts on a 7-day trial the moment it pairs — whether it paired by
scanning a QR or by typing a pairing code. Pairing by code consumes nothing
extra: same slot, same trial.
When the licence lapses, the connection stops being reachable: it disappears
from `GET /connections`, events stop being delivered, and sends answer `402`.
## Warm-up caps on new `qr` numbers [#warm-up-caps-on-new-qr-numbers]
A freshly paired `qr` number carries **72 hours of warm-up caps** on hourly send
volume. Exceeding one returns `429 warmup_limited` — an hourly cap, so back off
in minutes and do not hot-loop.
That is a separate limiter from the abuse limiter, which returns
`429 rate_limited`. Honour `Retry-After` when it is present, but always keep a
default back-off of your own: the header is not guaranteed on every 409/429.
# Scopes (/docs/concepts/scopes)
Scopes are per credential — per API key, or per OAuth grant. There are four.
| Scope | Grants |
| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `whatsapp.read` | `GET /connections`, `GET /connections/{id}`, `GET /account`, `GET /messages` |
| `whatsapp.send` | `POST /messages`, `POST /messages/read` |
| `whatsapp.events` | `GET /webhook`, `PUT /webhook`, `POST /webhook/rotate`, and receiving deliveries at all |
| `whatsapp.manage` | `POST /connections`, `POST /connections/{id}/pairing-code`, `POST /connections/{id}/restart`, `POST /connections/{id}/logout`, `DELETE /connections/{id}` |
## Marking read is a send, not a read [#marking-read-is-a-send-not-a-read]
`POST /messages/read` needs `whatsapp.send`. It looks like a read operation, but
it **transmits** a receipt from your number to the customer's device — it is
outbound. The upside is that any client which can already send can also mark
read: no new scope, no re-consent.
## Resolution is live [#resolution-is-live]
Scopes and the reachable connection list are resolved on **every** request.
Nothing is cached in the token and nothing has to be refreshed. Two consequences:
* Revoking a key, or narrowing its scopes, takes effect on the very next call.
* A connection you just created is visible on the next call. There is no
propagation delay and nothing to re-issue.
## Insufficient scope [#insufficient-scope]
A credential that lacks the scope an endpoint needs gets
`403 insufficient_scope`. Branch on the **code**, not the status — `403` is also
what an IP-allowlist refusal returns (`ip_not_allowed`) and the two need
opposite fixes: one means edit the key's scopes, the other means add an address.
See [Errors & idempotency](/docs/concepts/errors-and-idempotency).
## Ask for less [#ask-for-less]
The scope you do not grant is the one that cannot be abused if the key leaks. A
read-only reporting job wants `whatsapp.read` and nothing else; a notification
sender wants `whatsapp.send`; only a provisioning flow needs
`whatsapp.manage`, which can delete connections.
# Workspaces (/docs/concepts/workspaces)
A **workspace** owns WhatsApp connections. An API key is issued against exactly
one workspace, and everything the key can see or do is scoped to it — there is
no way to ask about another one.
## One key, one workspace, many connections [#one-key-one-workspace-many-connections]
For a multi-tenant application this is the shape you want:
* **One API key**, not one per tenant. Do not mint a key per customer.
* **One `POST /connections` per tenant**, including the very first one, each
with its own fresh `Idempotency-Key`.
* **Route inbound events by `connection_id`** — a stable cuid that appears on
every REST response and every webhook payload. Map it to your own customer
record; we mint the id, you map it.
* New connections are usable immediately. The key's connection list is resolved
live on each request, so there is nothing to refresh after a create.
## Two kinds of workspace [#two-kinds-of-workspace]
The difference shows up in exactly two places, and they are worth knowing before
you write code against the wrong one:
**Creating connections.** `POST /connections` is standalone-only. On a Bitrix24
portal it answers `403 forbidden_portal_kind` — the portal admin creates
connections in the WASync interface instead. Every other endpoint behaves
identically on both.
**What makes a connection reachable.** In a standalone workspace it is the
connection's own licence (trial or paid). On a Bitrix24 portal the portal's
subscription pays for the number in the CRM, and reaching that same number
*through the API* additionally needs the **API add-on**, at $12 per number per
month. Without it the connection is simply not in `GET /connections`.
## Bootstrapping [#bootstrapping]
With an API key there is no bootstrap step: the key is issued against your
workspace directly, so `POST /connections` creates the first connection as
readily as the tenth.
An OAuth grant is different by construction — it is only ever issued *over
connections that already exist*, so an OAuth-only integration cannot create a
workspace's first connection. That is the reason every quickstart here starts
with a key.
# Bring a number from another provider (/docs/guides/bring-your-own-number)
Already using the WhatsApp Business API somewhere else, for example Gupshup,
360dialog, Twilio or Wati? You can move that number to WASync (sold as **WABA**)
and keep your reputation with Meta. Your old provider keeps working right up to
the final step, so there is no gap in service until you switch over.
The wizard is called **Bring a number**. Where to find it, under
**Connections** in the WASync app:
* The menu of an existing WABA connection.
* The link **Already using the WhatsApp Business API with another provider?
Bring that number instead** inside **Connect WhatsApp Business API**.
* The link **Bring a number from another provider** next to the buttons at the
top of the Connections page.
You do not need a WABA connection to start: the last two entries work on a
portal that has none yet.
## What comes with you, what stays behind [#what-comes-with-you-what-stays-behind]
| Comes with you | Stays behind |
| ------------------------------------------------------------------ | ------------------------------------------ |
| Your display name | Chat history |
| Quality rating | Analytics and insights |
| Official Business Account status | Rejected, pending or low-quality templates |
| Messaging limits | |
| Approved, high-quality message templates (Meta copies them across) | |
Because the display name comes across with the number, there is nothing to
re-enter and no new name review.
## Before you start [#before-you-start]
* Switch off **two-step verification** for the number at your current provider.
Meta refuses the move while it is on, and this is by far the most common
reason a migration fails. In Business Manager: WhatsApp Manager, Phone
numbers, the settings (gear) of the number's row, Two-step verification, Turn
off. Meta emails a confirmation link that must be clicked before it takes
effect.
* **No Two-step verification tab?** Meta is retiring the six-digit PIN for
eligible Cloud API numbers, number by number. When the tab is missing from a
number you own with full control, the change has already reached that number:
there is no PIN to switch off, and you can proceed with the move and tick the
box in the wizard. Meta's note is in their
[account model evolution](https://developers.facebook.com/documentation/business-messaging/whatsapp/account-model-evolution)
page.
* Your business must be verified with Meta, and the WhatsApp Business Account
the number moves into must be in good standing.
* You need to be able to receive a 6-digit code on the number, by SMS or by
voice call.
## Steps [#steps]
1. **Intro.** Read what comes with you and what stays behind, then continue.
2. **Number.** Pick the country and enter the phone number exactly as it runs at
your current provider, without the country code and without a leading 0.
You type the same number again in Meta's window at the last step. Here it is
only used to run the checks.
3. **Checks.** WASync reads your Meta business and WhatsApp Business Account
(read-only, nothing is changed) and reports five checks:
* Your business is verified with Meta.
* The destination WhatsApp Business Account is in good standing.
* Your account has room for another number. Meta does not publish the
maximum, so WASync shows how many numbers the account has and you confirm
the rest yourself.
* The number is not already on this account.
* Two-step verification is switched off at your current provider. Only you
can confirm this, so you tick a box.
You can continue only when no check fails and the box is ticked. Fix any
failing check, then run the checks again.
If the portal has no WhatsApp Business API connection yet, WASync has no
account to read through, so it cannot run these checks. You get a checklist
of five boxes instead: business verified with Meta, you are an admin of the
Business portfolio that owns the number, the number is yours and not rented
from the provider, two-step verification is off (and Meta's confirmation
email opened), and no display-name change is pending. Tick all five to
continue. Once a number is connected, later moves get the automatic checks.
4. **Meta's window.** Click **Open Meta sign-up**. The move happens in Meta's own
window, which WASync cannot fill in for you. Choose:
1. Your existing Meta Business portfolio, the one that owns the number today.
Do not create a new one.
2. **Create a new WhatsApp Business Account.** Meta always builds a fresh
account for a number arriving from another provider. Your old account
cannot be reused, and that is expected.
3. Enter your existing number, exactly as checked. Meta warns that it is
already registered with another provider. Continue past it.
4. Verify with the code Meta sends, by SMS or voice call, and enter the
6-digit code.
When setup finishes, close the window if it stays open. The move finalizes
in WASync automatically.
5. **Done.** The number now runs on WASync.
## After the move [#after-the-move]
* Meta created a new WhatsApp Business Account for the number under WASync and
registered it for sending. Your old provider no longer sends or receives on it.
* Templates can take up to **24 hours** to show a quality rating again, and may
read as unrated until then. Templates that were rejected, pending or
low-quality did not come across. Create them again under **Templates**.
* WASync re-registers the number with a two-step verification PIN, because you
had to switch it off to move. Save the PIN. You need it if you ever move the
number again. It is always under **Connections**, **PIN**.
* Your old provider's dashboard shows the number as migrated and its channel is
dead. Send and receive a real message in WASync first, and cancel the old
subscription only once messaging works.
## Conversation routing at Meta [#conversation-routing-at-meta]
Meta has a setting, **Conversation routing**, that decides which partner app
receives a number's conversations. When it is on and your previous provider is
still the primary partner, the number looks connected in WASync but customer
messages keep going to the old provider, and every message you send from WASync
fails with error **131070** ("another app is controlling this thread"). Moving
or re-registering the number does not change this. Only you can, at Meta.
WASync checks this right after the move and again several times a day. When
Meta still routes the number elsewhere, **Connections** shows a red warning on
the number with these steps:
1. Open **Meta Business Suite**, **Settings**, **WhatsApp accounts**, and select
the number.
2. Open **Conversation routing**.
3. Set **WASync** as **Primary** for every entry point: **Customer service**,
**Click-to-WhatsApp ads**, **Utility**, **Marketing** and **Calls**.
4. Set **WASync** as the **Escalation** partner too.
5. Save. New messages from then on reach WASync.
If you no longer use the previous provider at all, you can instead remove it
under **Partners** or **Messaging accounts** in Business Suite. Then every
conversation comes to WASync.
The warning disappears on its own at the next check once WASync is the primary
partner. If messages still do not arrive after that, write to support with the
number.
## Troubleshooting [#troubleshooting]
Meta locks a number for 72 hours after 10 failed attempts. Continue only when
every check passes. If Meta refuses in its own window, read its message and fix
the cause before trying again.
| What you see | What to do |
| -------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Business verification is pending or not verified | Complete verification in Business Manager, Business settings, Security centre, or wait for Meta to finish the review. The wizard does not start the move until this check passes. |
| The account is not in good standing | Resolve the restriction on that WhatsApp Business Account first. Moving a healthy number into it does not lift the restriction. |
| The number is already attached to this account | There is nothing to migrate. Use the connection it belongs to. |
| Room for another number cannot be confirmed | If Meta rejects the move because the account is full, delete a number you no longer use in WhatsApp Manager, Phone numbers, or migrate into a different account. |
| WASync could not reach Meta | Retry in a minute. If it keeps failing, reconnect the WhatsApp Business Account and try again. |
| Meta refuses the move | The usual cause is two-step verification still on at the old provider, or the confirmation email not yet clicked. |
| After the move, messages still go to the old provider, or sends fail with error 131070 | Meta's Conversation routing still makes the old provider the primary partner. See [Conversation routing at Meta](#conversation-routing-at-meta). |
## Billing [#billing]
WASync's licence for the number is unchanged by the move. Meta's own message
charges are billed by Meta per WhatsApp Business Account, and the move creates a
new account for the number: open WhatsApp Manager, Billing & payments, for the
new account and make sure it has a payment method before you send
business-initiated messages. See
[Licences & trial](/docs/concepts/licences-and-trial).
# HTTP request step in Chat Flows (/docs/guides/chat-flows-http-request)
A Chat Flow can ask an external system a question over HTTPS and use the answer
in the conversation: look up an order, check a balance, fetch a delivery date.
The step is called **HTTP request** (palette group *Integrate*) in the Chat Flows
editor of the WASync app in Bitrix24.
## What the step does [#what-the-step-does]
1. Builds the request from the step's settings: method (GET or POST), URL, headers,
and for POST a body. `{{VARIABLES}}` from earlier steps and from the lead or deal
are substituted: in the URL they are URL-encoded, in a JSON body they are
JSON-escaped.
2. Performs the request and waits up to 10 seconds for the answer.
3. Maps the JSON answer onto flow variables with the **response mapping**: a JSON
path (`data.order.status`, `items[0].id`) on the left, a variable name
(`ESTADO`) on the right. The next steps use these like any answer:
`{{ESTADO}}` in a message, a condition in a Branch, a value in Fill in a field.
Every call also sets three variables:
| Variable | Value |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `HTTP_STATUS` | The HTTP status code the system answered with (`200`, `404`, …), empty if nothing answered. |
| `HTTP_OK` | `true` for a 2xx answer, otherwise `false`. |
| `HTTP_ERROR` | Empty on success; otherwise a short code: `http_404`, `timeout`, `blocked_url`, `upstream_unreachable`, `budget_exceeded`, `breaker_open`. |
## Two outgoing edges [#two-outgoing-edges]
The node has a normal edge (success) and a red **error** edge. The error edge is
taken when the call times out, the URL is refused, the system answers 4xx or 5xx,
or the network fails. If the error edge is not connected, the flow continues on
the normal edge with `HTTP_OK` = `false`, so a Branch on `HTTP_OK` can still react.
## Where the request is made from [#where-the-request-is-made-from]
The request is **not** made from WASync's servers. It is performed by a dedicated
Cloudflare Worker (`egress.wasync.app`) that has no access to WASync's internal
systems. Two consequences:
* The call reaches your system from Cloudflare's IP ranges, not from a fixed WASync
address. If your API allows only listed IPs, use an API key or a signature
instead; there is no WASync IP to allow-list.
* A slow or failing API can never delay or duplicate WhatsApp messages: the call
runs outside the message pipeline, and the flow waits on the step until the
answer or the timeout.
## What the step may call [#what-the-step-may-call]
| Rule | Value |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Scheme and port | `https` on port 443 only |
| Host | A public domain name. IP addresses, `localhost`, `.local`, `.internal`, single-label names and WASync's own domains are refused. |
| Methods | GET, POST |
| Headers | Up to 16. Transport and proxy headers (`Host`, `Transfer-Encoding`, `Proxy-*`, `Cookie`, `X-Forwarded-*`, …) are refused; `Authorization`, `X-Api-Key`, `Content-Type`, `Accept` and the like are fine. |
| Request body | Up to 64 KB |
| Response | Read up to 256 KB; longer bodies are cut, and `truncated` is reported in Test. |
| Timeout | 10 seconds |
| Redirects | At most 2, each checked against the same rules |
| Budget | 600 calls per workspace per hour. A host that fails 5 times in a row is paused for 5 minutes (the error edge is taken meanwhile). |
| Licence | The number's licence must be active; the step does not run on a trial. |
The user agent is always `WASync-Flows/1.0 (+https://wasync.app)`.
## Secrets [#secrets]
Mark a header as **secret** (an API key, a bearer token) and WASync stores it
encrypted. It is never shown again in the editor, never exported with the flow,
never written to logs or to the audit trail. To change it, type a new value; to
keep it, leave the field empty when you save.
## Test before you save [#test-before-you-save]
**Test request** in the step's panel performs the real call with sample values for
the variables and shows the status, the time taken, the mapped variables and the
body. **Use as sample response** stores that body on the step: the simulator uses
it instead of calling the system, so the whole flow can be previewed offline.
## Example: order status [#example-order-status]
* **Question**: "¿Cuál es tu número de pedido?" (saved as `PEDIDO`)
* **HTTP request**: `GET https://erp.example.com/api/orders/{{PEDIDO}}`, header
`X-Api-Key` (secret), mapping `data.status` → `ESTADO`, `data.eta` → `ENTREGA`
* **Branch** on `HTTP_OK`: `true` → **Message** `Tu pedido está {{ESTADO}}, llega el {{ENTREGA}}.`
· `false` → **Message** `No pude consultar tu pedido ahora, un asesor te escribe en breve.`
→ **Hand to a person**
## Not in this version [#not-in-this-version]
PUT, PATCH and DELETE; OAuth towards the external system; automatic retries;
file downloads; waiting for a callback from the system. For those, keep the
sibling recipe: the flow writes a CRM field, a Bitrix24 automation rule notifies
your system, your system writes the result back through the Bitrix24 REST API,
and the **WASync: Send WhatsApp Message** rule sends it.
Every call is recorded in the workspace audit trail (host and path, status,
duration, which variables were set; never the body or the headers).
# Guides (/docs/guides)
End-to-end recipes: n8n, MCP, webhooks, pairing, and OAuth2 for third-party apps.
# Leads from WhatsApp chats (/docs/guides/leads-from-whatsapp-chats)
Everything on this page lives in one place: open the WASync app in Bitrix24 and
choose **WASync Chat** in the left menu. The page is visible to people who can
read Settings; saving needs write access to Settings.
The rules below apply to numbers connected through WASync, both the ones paired
by QR and the official WhatsApp Business API ones. They never touch leads or
deals your team creates by hand.
## New chats from unknown numbers [#new-chats-from-unknown-numbers]
A number that is not in your CRM writes to you for the first time. Pick what
WASync does:
| Option | What happens |
| ---------------- | ----------------------------------------------------------------------------- |
| **Off** | The chat is visible to people who see all chats. No CRM record is created. |
| **Round-robin** | WASync creates a lead and assigns it to the next person in the list you tick. |
| **Fixed person** | WASync creates a lead and assigns it to that person. |
The lead carries the customer's name and phone, the CRM source of the
WhatsApp line, and, when the message came from a click-to-WhatsApp ad, the ad's
attribution (UTM fields and the ad name). The conversation is linked to the lead,
so the lead's responsible sees the chat and the lead's stage shows on the
conversation.
Three switches refine the rule:
* **Also on connections bound to an Open Line.** By default a number that is
connected to a Bitrix24 Open Line is skipped, because Bitrix24 creates its own
lead there. It does so only when an operator takes the chat, sometimes hours
later. Turn this on and the lead exists from the first message.
* **Also when an operator writes first.** A conversation started from WASync
Chat to a number that is not in your CRM gets a lead right away, assigned to
the operator who wrote.
* **Also create a lead when the number is already a contact but has no open lead
or deal.** Without it, a known contact is linked to their contact card only.
With it, WASync creates a lead attached to the existing contact (no duplicate
contact) and assigns it by the rule above.
## Numbers already in your CRM [#numbers-already-in-your-crm]
When the number exists in Bitrix24, WASync looks for the customer's open record
and links the conversation to it, in this order: an open deal, then an open lead,
then the contact. A lead that was converted follows its deal.
**Each number creates its own lead** changes what "open record" means for teams
that run several WhatsApp numbers or another WhatsApp tool next to WASync. With
it on, an open lead or deal counts only if it was created or linked from the
same WhatsApp number the customer wrote to. A customer who reaches a new number
from an ad gets a lead for that number, attached to their existing contact; the
old record is not touched, and the customer's next messages on that number go to
that same lead.
## Re-contact window after a closed lead [#re-contact-window-after-a-closed-lead]
A customer's lead is marked **lost**. Minutes or hours later they write again:
"thanks", "one more question", or they tap the same ad. Without a window, the
rules above see a contact with no open record and create a new lead at once.
Set **Re-contact window after a closed lead (hours)** to the number of hours
during which a message from that customer goes back to the lost lead instead:
* `0` (the default on every account) keeps today's behaviour: a new lead.
* Any value up to `720` (30 days) is accepted. Most teams pick between 24 and 72.
Inside the window:
1. No new lead is created. The conversation stays linked to the lost lead and
the messages land in its timeline.
2. With **Reopen the lost lead when the client writes back** on, the lead also
moves to an open stage, so it shows up again in the agent's list. The stage
is **Stage the lead returns to**: the first open status of your lead pipeline
(usually *New*) or any open stage you pick. If the chosen stage no longer
exists or is a closed one, WASync falls back to the first open status.
3. After the window, the next message is handled by the rules above again, which
usually means a new lead.
**Lost deals, with one lead per number.** When **Each number creates its own lead**
is on, the window also covers a lost deal the conversation on that number is
linked to. Example: an agent sends a template from a deal and marks the deal
lost a minute later. The customer's reply inside the window goes back to that
deal, not to a new lead for the default responsible. A lost deal is never
reopened, whatever the reopen option says: move it to a stage yourself if the
conversation brings it back to life.
What the window does not change:
* **Won leads.** A converted lead has a deal; the conversation already follows
that deal, so the window never applies to it.
* **Chat Flows** that create a lead when they start use the same window: a
customer re-entering from an ad inside the window lands on the lost lead, not
on a second one.
* **Records closed before you saved the setting.** The window reads the lead's
close time, so it applies from the moment you save, including leads that were
closed shortly before, but it does not merge duplicates created earlier.
The field is enabled only while **Also create a lead when the number is already
a contact…** or **Each number creates its own lead** is on; with both off, a
known contact never gets a new lead, so there is nothing for the window to
prevent.
### A typical setup for an ad-driven sales team [#a-typical-setup-for-an-ad-driven-sales-team]
* **Fixed person** or **Round-robin** for new numbers.
* **Also on connections bound to an Open Line** on, so leads exist from the
first message.
* **Also create a lead when the number is already a contact…** on, so returning
customers get a fresh lead for the new inquiry.
* **Re-contact window** 72 hours, **Reopen the lost lead** on, stage *New*.
With that, a lost lead stays closed unless the customer comes back within three
days; when they do, the agent sees the same lead reopened with the whole
conversation on it.
## Closed leads and deals [#closed-leads-and-deals]
The separate **Closed leads and deals** card decides who still sees a
conversation after its record is closed: the former responsible keeps it for the
number of days you set (0 = it disappears immediately), and the chat reappears
for whoever receives the customer's next lead or deal. Admins and people who see
all chats are not affected.
## Stage picker in WASync Chat [#stage-picker-in-wasync-chat]
The **Stage picker in WASync Chat** card decides who may change the CRM stage of
a conversation from the WASync Chat header. Open the WASync app in Bitrix24 and
choose **WASync Chat** in the left menu. Only a Bitrix24 administrator can change it.
* **All operators** (default): everyone who can open the chat sees the stage
dropdown and can move the record.
* **Admins only**: administrators keep the dropdown; everyone else sees the
current stage as a read-only label.
* **Hidden (read-only for everyone)**: nobody can change the stage from WASync
Chat. The current stage is still shown, in its Bitrix24 colour.
This setting only narrows access. Bitrix24 CRM permissions still apply on top: an
operator who cannot edit a record in Bitrix24 cannot move its stage from
WASync Chat either. The "required fields before a stage change" rules keep
working for the people who can still change the stage.
## Related [#related]
* [Smart Processes (SPA) in WASync](/docs/guides/smart-processes): the same
rules link conversations to Smart Process items.
* [Changelog, 15 October 2026](/docs/changelog/2026-10-15): when the re-contact
window shipped.
* [Changelog, 16 October 2026](/docs/changelog/2026-10-16): when the stage picker
setting shipped.
# MCP (/docs/guides/mcp)
WASync runs a remote **MCP** server over Streamable HTTP. Add it to an MCP
client and the agent gets WhatsApp tools with no code on your side.
```text title="MCP server URL"
https://cloudapi.wasync.app/api/mcp
```
That host is deliberate. The REST base URL and every human-facing link use
`developers.wasync.app`, but the MCP server URL, the OAuth endpoints and the
`/.well-known/…` documents are protocol identifiers clients have already
registered — they stay on `cloudapi.wasync.app` and must match byte-for-byte.
Do not "normalise" them.
## Connect a client [#connect-a-client]
For clients that read a config file (Claude Desktop, Cursor, …):
```json title="mcp config"
{
"mcpServers": {
"wasync": {
"url": "https://cloudapi.wasync.app/api/mcp"
}
}
}
```
Authentication is **OAuth 2.0 with PKCE**, handled by the client: the first call
opens a browser, you approve, and the client stores the tokens. There is no key
to paste.
A client without native remote-MCP support can bridge over stdio:
```bash
npx mcp-remote https://cloudapi.wasync.app/api/mcp
```
## Find it in the registry [#find-it-in-the-registry]
WASync is listed in the official MCP Registry as:
```text
app.wasync/whatsapp
```
Clients and directories that read the registry can find the server by name
instead of pasting the URL.
## The tools [#the-tools]
| Tool | What it does | Needs |
| ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- |
| `list_whatsapp_connections` | Lists the connections the grant may use, with status and licence state. Every other tool takes a connection id from here. | read |
| `get_whatsapp_connection` | The current state of one connection: online or not, licence status and expiry. Read-only. | read |
| `read_whatsapp_messages` | Stored messages, newest first, across every shared connection or one of them; paged with `nextCursor`. Nothing is sent and no read receipt is shown. | read |
| `send_whatsapp_message` | Sends a text message from one connection to one recipient. The tool's description tells the model to confirm recipient and wording first: a WhatsApp message cannot be recalled. | send |
| `send_whatsapp_file` | Sends a file (document, image, audio or video, up to 5 MB) with an optional caption. Give a direct `https` link in `url` (preferred) or base64 in `data`. Same confirm-first rule: it cannot be recalled. | send |
| `mark_whatsapp_messages_read` | Marks one customer's inbound messages as read (blue ticks), by phone number or by a message id. | send |
They map onto `GET /connections`, `GET /connections/{id}`, `GET /messages`,
`POST /messages` (text and media) and `POST /messages/read`, and they obey the
same [scopes](/docs/concepts/scopes) — an agent can only do what the grant
allows.
### Sending a file [#sending-a-file]
`send_whatsapp_file` takes exactly one of `url` or `data`:
```json title="send_whatsapp_file arguments"
{
"connectionId": "conn_123",
"to": "40700000000",
"url": "https://files.example.com/offers/offer-2026.pdf",
"filename": "offer-2026.pdf",
"caption": "Here is the offer we discussed."
}
```
* **`url`** must be a direct `https://` link to a file that anyone on the
internet can open without logging in. WASync downloads it (up to 5 MB, 20
seconds) and takes the `mimetype` from the file server's answer unless you
pass one. Links that point at private networks, at WASync itself, or at a web
page instead of a file are refused.
* **`data`** is the file as plain base64 (no `data:` prefix), at most 5 MB
decoded, and then `mimetype` is required. Prefer `url`: moving file bytes
through a model's conversation is slow and costly.
* `filename` is what the recipient sees (no slashes); `caption` is optional, up
to 1024 characters.
Failures come back as tool errors with a stable code at the start of the
message: `invalid_url`, `url_not_allowed`, `download_failed`, `file_too_large`,
`invalid_media`, or `send_failed: ` when WASync refused the send.
## MCP or the REST API? [#mcp-or-the-rest-api]
Use MCP when a **human-supervised agent** should be able to reach WhatsApp:
answering from a chat client, drafting replies, looking things up. Use the
[REST API](/docs/api-reference) when your own software owns the behaviour and
needs webhooks, idempotency keys, files larger than 5 MB or provisioning — none
of which MCP exposes.
An OAuth grant is only ever issued over connections that **already exist**, so
MCP cannot create a workspace's first connection. Create it with an API key
first: [Quickstart](/docs/quickstart/first-call).
# Campaign and ad set on conversations from ads (/docs/guides/meta-ads-campaign-attribution)
When a customer writes to you from a Click-to-WhatsApp ad, WhatsApp tells
WASync which **ad** it was, and nothing more. WASync writes that on the lead or
deal: `UTM_SOURCE = facebook`, `UTM_MEDIUM = ctwa`, the ad id in `UTM Campaign`
and the click id in `UTM Content`, plus the `UF_CRM_CTWA_*` fields.
To report by **campaign** and **ad set** you need the two ids Meta does not
send with the message. WASync can look them up in your ad account if you give
it a token of your own Business Manager. With the token in place the UTM
fields follow Meta's own convention:
| Field | Value |
| ------------ | ----------- |
| UTM Campaign | campaign id |
| UTM Term | ad set id |
| UTM Content | ad id |
The click id stays in `UF_CRM_CTWA_CLID`, and the timeline note on the record
shows the names: *Campaign: «Préstamos octubre» (1202…)*, *Ad set: «Profes»
(1202…)*, *Ad: «FACSIS IA» 1202…*.
## 1. Create a System User token with ads\_read [#1-create-a-system-user-token-with-ads_read]
Five steps, once, about ten minutes. Everything happens in Meta's own
interfaces; WASync only receives the token at the end.
### 1.1 An app with the Marketing API product [#1-1-an-app-with-the-marketing-api-product]
Meta only issues a token through an app of your own portfolio, and the token
dialog lists only the permissions that app can grant. If your portfolio
already has an app with the **Marketing API** product, use it. If not, create
one once at [developers.facebook.com/apps](https://developers.facebook.com/apps/):
**Create app**. Meta's wizard first asks for a *use case*: pick **Other**
(the last card at the bottom, labelled "this option is going away soon"), which
opens the previous experience: type **Business** → pick your business
portfolio → once the app exists, **Add product** → **Marketing API** →
*Set up*. In the new experience, the use case under *Ads and monetisation*
that creates and manages ads with the Marketing API leads to the same place.
Do not pick "Create an app without a use case": it has no products. No code,
no review: the app stays in development mode and that is enough for a system
user token.
### 1.2 A system user [#1-2-a-system-user]
In **Meta Business Suite → Business settings → Users → System users → Add**.
Name it in lowercase, for example *wasync attribution* (Meta refuses names
with several capital letters); the **Employee** role is enough.
### 1.3 Give it the ad account [#1-3-give-it-the-ad-account]
Open the system user → **Assign assets → Ad accounts** → tick the ad account
that runs your Click-to-WhatsApp ads → **View performance** (read is enough)
→ Save.
### 1.4 Give it the app [#1-4-give-it-the-app]
Still on the system user → **Assign assets → Apps** → tick the app from step
1.1 → **Develop app** → Save. This is the step most people miss: without it,
the token dialog shows only the WhatsApp permissions and **ads\_read** is not
in the list.
### 1.5 Generate the token [#1-5-generate-the-token]
System user → **Generate token** → choose the app from step 1.1 → expiry
**Never** → tick **ads\_read** only → **Generate token** → copy it. Meta shows
it once; if you close the dialog, generate a new one.
## 2. Paste it in WASync [#2-paste-it-in-wasync]
Open the WASync app in Bitrix24 → **Settings** → the card **Campaign and ad set
on conversations from ads**. Paste the token and click **Save token**. WASync
stores it encrypted and never shows it again.
To check it, paste the numeric id of one of your ads (from Ads Manager, the
*Ad ID* column) and click **Test**: the card shows the campaign, the ad set and
the ad that WASync would write.
Save tokenTestRemove token
## If something does not work [#if-something-does-not-work]
* **ads\_read is not in the token dialog.** The system user has no role on the
app (step 1.4), or the app has no Marketing API product (step 1.1). Fix one
of the two and open *Generate token* again.
* **The app is not offered in the token dialog.** The app belongs to another
business portfolio. Create the app under the portfolio that owns the ad
account, or assign it to the system user from that portfolio.
* **Test says the token is invalid or expired.** The token was generated with
an expiry, or from an app that was later removed. Generate a new one with
expiry *Never* and save it again.
* **Test says the ad was not found.** The ad belongs to an ad account the
system user does not have (step 1.3), or the id is a campaign or ad set id.
Use the *Ad ID* column of Ads Manager.
* **Leads still show only the ad id.** The token applies to new conversations
only; records attributed before the token keep what they have.
## What changes, and what does not [#what-changes-and-what-does-not]
* Only new conversations from ads get the three ids; records attributed before
the token keep what they have.
* A record that already has a `UTM Source` from another channel is never
overwritten; the `UF_CRM_CTWA_*` fields are always written.
* Each ad is looked up once and remembered for a day, so a campaign with
thousands of conversations costs one request to Meta.
* If Meta refuses the lookup (expired token, an ad from another ad account),
the conversation is attributed as before, with the ad id only, and nothing
else breaks.
* Remove the token at any time with **Remove token**; WASync goes back to
writing the ad id only.
Related: [CRM records and timeline](/docs/product/crm-records#ad-attribution).
# n8n (/docs/guides/n8n)
WASync ships a community node for [n8n](https://n8n.io), published on npm as
[`n8n-nodes-wasync`](https://www.npmjs.com/package/n8n-nodes-wasync). It wraps
the same REST API these docs describe, so anything the node does you can also do
with curl — and anything it does not do yet, you can.
## Before you start: an account and a connected number [#before-you-start-an-account-and-a-connected-number]
The node talks to your **WASync account**. If you do not have one yet, create it
first — it takes a minute and costs nothing:
### Create a free developer account [#create-a-free-developer-account]
Go to [developers.wasync.app/register](https://developers.wasync.app/register)
— name, email, password. Every new account comes with its own **workspace**: the
place your WhatsApp numbers and API keys live.
### Get a WhatsApp number into that workspace [#get-a-whatsapp-number-into-that-workspace]
Two situations:
* **You already use WASync inside Bitrix24** — sign in with the same email you
use in Bitrix24. Your portal appears as a workspace and its connected numbers
are ready to use. Sending through the API needs the **API add-on** on that
number ($12 per number per month; without it the node's send step answers
`addon_required`).
* **You are new to WASync** — connect a number to your own workspace with one
API call that returns a QR code (or a pairing code you type into WhatsApp).
The exact steps are in [Connect a WhatsApp number](/docs/quickstart/first-call).
Every number starts with a **7-day free trial**; plans are WAPP $19 or
WABA $29 per number per month, USD.
### Create an API key [#create-an-api-key]
Two ways to do this:
* **Already using WASync inside Bitrix24?** Go to **Settings → API & Agents →
API keys**, name the integration and click **Create key**. It needs a
connection with the API add-on active, and it comes with the scopes this
workflow needs (`whatsapp.read whatsapp.send`) — skip the scope picklist
below.
* **Otherwise**, sign in and open
[developers.wasync.app/keys](https://developers.wasync.app/keys). Pick the
workspace, give the key a name, tick the scopes below, create it.
Either way, copy the key immediately — it is shown once. This is the value the
n8n credential asks for.
The node's **Connection → List** operation shows every number the key can reach.
If the list is empty, the workspace has no connected number yet — go back to step 2.
## 1. Install the community node [#1-install-the-community-node]
`n8n-nodes-wasync` is a **verified** community node — it carries the verified
badge wherever n8n shows one.
Two ways to install it, depending on where you run n8n:
* **n8n Cloud or self-hosted — search the node panel.** Open the nodes panel,
search for **"WASync"**, and add it. Verified nodes install straight from
there, no extra setup.
* **Self-hosted only — Community Nodes settings.** Go to
**Settings → Community nodes → Install**, enter the package name and confirm:
```text
n8n-nodes-wasync
```
This path works on any self-hosted instance, verified or not.
After installing, the **WASync** and **WASync Trigger** nodes appear in the
node panel.
Ready-made starting points: the [free workflow
templates](https://wasync.app/whatsapp-n8n-kit) cover the most common flows —
import one and adjust the fields instead of building from a blank canvas.
## 2. Create the credential [#2-create-the-credential]
Add a credential of type **WASync API**. It takes a single field: your API key,
which is sent as `Authorization: Bearer …`.
Paste the key you created above (see *Before you start*) — it is shown once. Give it only the scopes the workflow needs:
* listing connections and reading messages → `whatsapp.read`
* sending and marking read → `whatsapp.send`
* the trigger → `whatsapp.events`
See [Scopes](/docs/concepts/scopes).
## 3. Your first workflow [#3-your-first-workflow]
The simplest useful workflow is two nodes: a manual trigger and a send.
**Find the connection id.** Add a **WASync** node, choose resource
**Connection** → operation **List**, and run it. Copy the `id` of the number you
want to send from.
**Send a message.** Add a second **WASync** node, resource **Message** →
operation **Send**. Fill in:
| Field | Value |
| -------------- | ------------------------------------------------- |
| `connectionId` | the id you just copied |
| `to` | international digits, no `+` — e.g. `40712345678` |
| `text` | the message body |
**Execute.** The node returns the message id you can join on later — see
[the two ids](/docs/quickstart/first-message).
## Operations the node supports [#operations-the-node-supports]
| Resource | Operation | Parameters |
| ---------- | ---------------- | ---------------------------- |
| Connection | **List** | — |
| Message | **Send** | `connectionId`, `to`, `text` |
| Message | **Get Many** | `connectionId`, `limit` |
| Message | **Mark as Read** | — |
Text sending only. Sending a WhatsApp **template** and checking whether a number
is on WhatsApp are not available through the API today, so the node does not
offer them — do not build a workflow that assumes they exist.
## 4. The trigger [#4-the-trigger]
**WASync Trigger** starts a workflow when something happens on your account. It
supports four events:
* `message.received`
* `message.status`
* `connection.connected`
* `connection.disconnected`
The payloads are exactly the ones in the [Webhooks
guide](/docs/guides/webhooks) — same fields, same ids, same
`timestamp`-in-milliseconds.
The API has a **single** webhook URL per account (`PUT /webhook`,
`POST /webhook/rotate`, and no delete). Activating a WASync Trigger points that
one slot at n8n.
So: if your own backend was already receiving webhooks, **it stops** the moment
the trigger takes over. And two WASync Triggers cannot both hold the slot — the
second one wins. If you need events in more than one place, receive them once
and fan out yourself: let n8n hold the slot and forward from a workflow, or let
your backend hold it and call an n8n Webhook node.
Test and production trigger URLs are different URLs, so switching between them
also moves the slot.
Because deliveries are dropped after three failed attempts, keep a reconciliation
path even in n8n: a scheduled workflow calling **Message → Get Many** every
30–60 seconds catches anything the trigger missed while the instance was
restarting.
## When the node is not enough [#when-the-node-is-not-enough]
The node covers the common path. For media sends, pairing codes, connection
provisioning, `Idempotency-Key` handling or anything else in the
[API reference](/docs/api-reference), use n8n's **HTTP Request** node with the
same credential: base URL `https://developers.wasync.app/api/v1`, header
`Authorization: Bearer `.
# OAuth2 for third-party apps (/docs/guides/oauth2)
An [API key](/docs/quickstart/create-account-and-key) does everything in these
docs with none of the machinery. OAuth is the right tool for exactly one job:
your app is installed by *other* WASync customers, and those customers have to
consent to connections they own.
## Register the app [#register-the-app]
Register at [https://developers.wasync.app/apps](https://developers.wasync.app/apps). You get a `client_id` and a
`client_secret` (shown once), and you set one or more `redirect_uri` (matched
exactly at token exchange), an optional `webhook_url`, and the scopes you need.
## The flow [#the-flow]
**Authorization Code with PKCE — `S256` is required.** Send the user to
`/oauth/authorize` with `response_type=code`, your `client_id`, `redirect_uri`,
`scope`, a `state` and a `code_challenge`.
| Endpoint | URL |
| ---------------------------- | -------------------------------------------------------------------- |
| Authorize | `https://cloudapi.wasync.app/oauth/authorize` |
| Token (`client_secret_post`) | `https://cloudapi.wasync.app/oauth/token` |
| Discovery | `https://cloudapi.wasync.app/.well-known/oauth-authorization-server` |
These URLs — and the [MCP server URL](/docs/guides/mcp) — read
`cloudapi.wasync.app` on purpose. They are protocol identifiers your client
library and our discovery documents have already registered, so they must match
byte-for-byte. Only the REST base URL and the human-facing pages use the
canonical `developers.wasync.app`.
## Consent depends on who owns the connections [#consent-depends-on-who-owns-the-connections]
**Bitrix24.** WASync shows a short user code, and someone with Write access to
the portal's **API & Agents** area enters it under **Settings → API & Agents**,
picking connections and scopes. Every Bitrix24 administrator has that access; so
does anyone an administrator has granted it to in the access matrix on the Staff
page.
**Standalone.** The developer approves at
[https://developers.wasync.app/authorize](https://developers.wasync.app/authorize) — auto-approved when they own exactly
one workspace with at least one connection.
## Exchange the code [#exchange-the-code]
```bash title="Token exchange"
curl -X POST https://cloudapi.wasync.app/oauth/token \
-d grant_type=authorization_code \
-d code=$AUTH_CODE \
-d redirect_uri=https://your.app/callback \
-d client_id=$CLIENT_ID \
-d client_secret=$CLIENT_SECRET \
-d code_verifier=$CODE_VERIFIER
```
`access_token` lives **15 minutes**. `refresh_token` lives **30 days and rotates
on use** — persist the new one atomically and serialise refreshes across
workers, or two workers racing will invalidate each other's token.
The access token goes in the same header as an API key:
`Authorization: Bearer …`. Both credential types reach every endpoint.
## One structural limit [#one-structural-limit]
A grant is only ever issued over connections that **already exist**, so an
OAuth-only integration cannot create a workspace's first connection. An API key
can — which is why the [quickstart](/docs/quickstart) starts with one.
## Webhooks for OAuth apps [#webhooks-for-oauth-apps]
An OAuth app sets `webhook_url` on the app itself rather than calling
`PUT /webhook`, and the grant must have been approved **with** `whatsapp.events`
or nothing is delivered. Everything else — the signature scheme, the retry
policy, the payloads — is identical to the [Webhooks
guide](/docs/guides/webhooks).
Subscriptions created before **24 July 2026** receive only `message.received`;
those created before **10 August 2026** do not receive the connection events.
Re-authorize to pick up the newer event types, or write to support and ask for
them to be added to your existing subscription.
# Pairing code & QR (/docs/guides/pairing-and-qr)
Pairing applies to `qr` connections. A `cloud_api` number never scans anything
and answers `409 not_supported_for_provider`.
## The QR path [#the-qr-path]
`POST /connections` returns an initial QR as a data-URI PNG.
WhatsApp rotates the pairing code roughly every **20 seconds**. The `qr` in the
create response is stale within seconds of being displayed, and this fails
**silently**: the phone never pairs and nothing on screen explains why.
Poll `GET /connections/{id}` every 3–5 s and re-render the `qr` from *every*
response until `status` is `"connected"`. Do not cache it, and do not hide the
refresh behind a button the user has to press.
The same rule applies to an idempotent replay: when `POST /connections` returns
`200` with `Idempotency-Replayed: true`, the `qr` in that response has been
re-fetched fresh rather than replayed from storage — precisely because a stored
code would no longer scan.
## The pairing-code path [#the-pairing-code-path]
A QR needs two devices: a screen showing it and a phone photographing it. A
large share of real onboardings happen on **one** device — the customer finishes
your flow on the same phone that runs WhatsApp, and cannot photograph its own
screen. For them the QR path is not awkward, it is impossible.
```bash title="POST /connections/{id}/pairing-code"
curl -X POST https://developers.wasync.app/api/v1/connections/conn_8f3a21/pairing-code \
-H "Authorization: Bearer $WASYNC_API_KEY" \
-H "Content-Type: application/json" \
-d '{"phoneNumber":"40740267964"}'
```
```json title="200 response"
{
"code": "7S59-1KZP"
}
```
The customer opens WhatsApp → **Settings → Linked devices → Link with phone
number** and types the code.
`phoneNumber` is E.164 **without** the leading `+` — digits only. Anything else
is rejected with `400 { "error": "invalid_phone_number" }` rather than cleaned
up for you: silently rewriting the number you sent is how a customer ends up
pairing an account nobody asked for. Uses `whatsapp.manage`, same as creating
the connection.
The engine can decline to issue one. That is an ordinary outcome, not an outage,
and it answers `502 { "error": "pairing_code_unavailable" }` instead of a generic
500 precisely so you can tell the two apart and send the user back to the QR. An
integration that ships only the pairing-code path will, sooner or later, show a
customer a screen with no way forward. **Render both, side by side.**
## Asking for another code [#asking-for-another-code]
You can request another code on the same connection: it returns a *new* code and
does not rebuild the session, so a "send me another code" button is safe.
It is capped at **5 per connection per 15 minutes**; past that you get
`429 { "error": "rate_limited" }` with a `Retry-After` header to honour. The cap
is not bureaucracy — repeatedly requesting codes for one number is exactly what
WhatsApp's anti-abuse systems act on, and the number at risk is your customer's.
## Nothing extra is consumed [#nothing-extra-is-consumed]
Pairing by code uses the same paid slot and starts the same **7-day free trial**
as scanning a QR: the licence is claimed when the number actually pairs,
whichever way it paired.
Watching for success is unchanged too. There is no "code accepted" event, so
poll `GET /connections/{id}` until `status` is `"connected"` and/or listen for
the `connection.connected` webhook.
Two refusals are worth coding for:
* `409 already_connected` — the session is live, there is nothing to pair.
* `409 not_supported_for_provider` — a `cloud_api` number. Pairing codes are a
`qr` concept and never apply, so do not retry.
## Re-pairing later [#re-pairing-later]
A `qr` session can break on its own. `connection.disconnected` tells you, and
`needs_reconnect` is the field to drive your UI from. The QR is deliberately not
in that payload — it is a scan-to-login credential — so fetch it from
`GET /connections/{id}` and show it to the number's owner exactly as during first
setup. See [Webhooks](/docs/guides/webhooks).
# Smart Processes (SPA) in WASync (/docs/guides/smart-processes)
Bitrix24 **Smart Processes** (SPA, "smart process automation") are custom CRM
entities next to leads and deals: contracts, service requests, bookings, claims.
WASync treats an SPA item like a lead or a deal wherever that makes sense:
* the **WASync tab** in the item card shows the WhatsApp conversation of the item's client;
* a conversation in **WASync Chat** can be linked to an item, and the item's
responsible person counts for the "Assigned to" filter and the "only my records" scope;
* messages are written to the item's **timeline** (comments), as on leads and deals;
* WASync **robots** (send message, send template, start a Chat Flow, AI) run from the
process's **automation rules**, and a Chat Flow can read and fill the item's fields.
## What the item needs [#what-the-item-needs]
An SPA item has no phone number of its own. WASync reaches the person through the
**client** bound to the item: the contact (or company) in the item's *Client* field.
That field exists only when the process was created with **Client** enabled
(*CRM → Smart Processes → the process → Settings → Client*).
* Process without *Client*: the WASync tab explains that there is nobody to write to
and links to the item card. Turn *Client* on in the process settings, then bind a
contact to the item.
* Item with a contact that has no phone: the tab offers to add the number, as on a deal.
* Several contacts on one item: WASync uses the primary contact first, then the others
in the item's order, then the company's phone.
## The WASync tab in the item card [#the-wasync-tab-in-the-item-card]
Open any item of the process. The **WASync** tab works like the one on deals: the
conversation with the client, sending text, files, voice notes and (on the official
API plan) templates. The header shows the item's title, stage and responsible person.
The tab is added automatically:
* at installation, for every process that exists at that moment;
* when a process is created or changed later (WASync listens to Bitrix24's
process events), and once a day as a safety net;
* immediately, if an administrator opens **WASync → Settings → Reinstall placements**.
If a brand-new process does not show the tab yet, reload the page a minute later or
use *Reinstall placements*.
## Linking a conversation to an item [#linking-a-conversation-to-an-item]
In **WASync Chat**, open the conversation → *Link to record*. When the portal has
Smart Processes, a type selector appears above the search: pick the process, type at
least two letters of the item's title, choose the item. The inbox row then shows the
process name as the record chip, the header shows the item's responsible person and
stage, and *Change record* lets you move the conversation to another item.
Bitrix24 permissions apply: the search runs as the operator, so only items that
person may see are offered.
## Timeline [#timeline]
With the default timeline setting, every message is written as a comment on the
records that carry the client's phone — leads, deals, contacts, companies — and on
the linked item. With *Timeline target → conversation record*, messages are written
once, on the record the conversation is linked to, which may be an SPA item.
## Robots on automation rules [#robots-on-automation-rules]
Open the process → **Automation rules**. The WASync robots are listed under the
WASync group, exactly as on leads and deals:
* **Send WhatsApp message** / **Send WhatsApp template (WABA)**: the recipient is the
item's client (primary contact, other contacts, company, in that order). `{{Fields}}`
of the item, its contact and its company are available in the text.
* **Start a Chat Flow**: starts a flow whose record type is this process (see below).
* **AI robot**: as on deals.
After installing or updating WASync, **reload the automation page once**: Bitrix24
caches robot definitions until the page is reloaded.
## Chat Flows on a process [#chat-flows-on-a-process]
In the Chat Flows editor, the *Record* selector lists every process that has
automation enabled. A flow built for a process:
* starts **only from an automation rule** of that process (the robot *Start a Chat
Flow*); the "first message" and "keyword" triggers are not offered, because a
message from a new number cannot create an item on its own;
* can read and fill the item's fields (*Fill in a field*, *Insert field*), including
custom fields, and the fields of the item's contact and company;
* can move the item with **Set stage → Move item**: choose the pipeline (when the
process has several) and the stage;
* can assign the item, create an activity on it, and hand the conversation over, as
on a deal.
`{{record.stage}}` renders the stage's name, `{{record.title}}` the item's title.
## Ad attribution (click-to-WhatsApp) [#ad-attribution-click-to-whatsapp]
When a conversation that started from a click-to-WhatsApp ad is linked to an item,
WASync fills the item's native UTM fields (source, medium, campaign, content, term)
if they are still empty, and leaves one timeline comment with the ad. Custom
`UF_CRM_CTWA_*` fields are not created on Smart Processes: Bitrix24 does not let an
application add user fields there.
## Limits in this version [#limits-in-this-version]
* Automations v2 (event-driven sends) and the *Send conversion to Meta* robot stay
on leads and deals.
* A flow cannot create an SPA item from a new conversation; link the conversation
to an item or start the flow from the process's automation.
* *From CRM field* attachments in Chat Flows read lead and deal file fields only.
* Calls started from the item card are not yet wired to the item.
## REST and MCP [#rest-and-mcp]
Nothing changes in the Platform API: items are Bitrix24's own `crm.item.*` objects.
In WASync's data, a linked item appears as record type `dynamic_` (for
example `dynamic_137`) wherever leads appear as `lead` and deals as `deal`.
# WhatsApp templates (WABA) (/docs/guides/waba-templates)
A **template** is a message that Meta has approved in advance. It is the only kind
of message a WhatsApp Business API (**WABA**) number may send to a customer who
has not written to you in the last 24 hours. This page covers writing one in
WASync, what happens at Meta, and every place you can send it from.
## What a template is, and when you need one [#what-a-template-is-and-when-you-need-one]
WhatsApp gives a business a **24-hour customer service window**. It opens when the
customer writes to you and stays open for 24 hours after their last message.
* **Inside the window** you can send any free-form text, file or voice note.
* **Outside the window** (the customer never wrote, or wrote more than 24 hours
ago) only an approved template goes out. When the customer replies, the window
opens again for 24 hours.
In **WASync Chat**, a closed window shows the banner *Conversation paused — send a
template to re-engage* with a **Pick a template** button, and a chip in the chat
header shows how much of the window is left.
Every template has one of three categories, which Meta uses for review and for
billing:
| Category | Use it for |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------ |
| **Utility** | An update about something the customer already started: appointment confirmation, order status, invoice, delivery, payment reminder. |
| **Marketing** | Offers, promotions, news, getting back in touch with a past customer. |
| **Authentication** | One-time codes, with wording fixed by Meta. WASync cannot create these yet. |
Template messages are **billed by Meta per template message, by category**
(marketing, utility, authentication). Utility templates sent inside an open
24-hour customer service window are free. The charge goes to the payment method on
your Meta account, not through WASync. Creating or submitting a template costs
nothing.
## Requirements [#requirements]
* A **WABA number** connected to WASync, on the WABA plan. See
[Connection types](/docs/concepts/connection-types) for how it differs from a
QR-paired number.
* To manage templates: an administrator, or a staff member with write access to
**WhatsApp numbers & templates** (Staff access matrix). Reading the list needs
read access.
* To send them: access to the number in **Connections → Staff**, like any message.
Templates exist only on the official WhatsApp Business API. On a QR-paired number
the template button is not offered, and a robot or automation that tries to send
one fails with: *This WhatsApp connection cannot send templates. Templates need a
WhatsApp Business (Cloud API) number.*
## Create a template [#create-a-template]
Open the WASync app in Bitrix24, go to **Connections**, open the **…** menu of the
WABA number and choose **Message templates**. The list shows each template with
its language, category, status and, for rejected ones, Meta's reason. Click
**+ New template**.
### What is the message for? [#what-is-the-message-for]
Pick **Inform a customer** (Utility), **Promote an offer** (Marketing) or
**Send a code** (marked *Coming soon*). The choice sets the category for you.
Be honest here: a promotional text submitted as Utility is rejected or moved to
Marketing by Meta.
You can also start from an example (*Appointment reminder*, *Order is ready*,
*Offer with an image*, *Let's pick up the conversation*) and change everything in
the next step. Choose the **Message language**. A template has a single language;
for another language you create another template.
### Write the message [#write-the-message]
Write the text the way the customer receives it; the preview on the right is what
they will see (up to 1,024 characters).
* **Personalize.** Click **+ Personalize** to add a variable: a common one
(*Customer name*, *Date*, *Time*, *Order number*, *Expiry date*, *Product or
service*, *Amount*), a **Bitrix24 field**, or your own label. Behind the scenes
each one becomes `{{1}}`, `{{2}}`, and so on. Do not type braces by hand.
* **Examples for approval.** Meta wants a realistic sample value for every
variable (for example "Ana", "31 October"). Use believable values, never real
customer data. They are not sent to anyone.
* **Header (optional).** A title (up to 60 characters, no variables), or an
**Image** (JPEG or PNG, up to 5 MB), **Video** (MP4, up to 16 MB) or **PDF**
(up to 16 MB). The file you upload is the **sample** Meta reviews. WASync keeps
it as the template's default file, so operators are not asked for it again.
* **More options.** A footer (up to 60 characters), up to 3 quick-reply buttons,
one link button (a fixed URL, no variables), one call button, and **Include a
WhatsApp call-permission request**. Button labels are limited to 25 characters.
The call-permission request is available only when WhatsApp calls are turned
on for the number ([Turning calls on for a number](/docs/product/calls#turning-calls-on-for-a-number)):
WhatsApp approves such a template anyway, then refuses every send from a
number without calls.
WhatsApp rejects a message that starts or ends with a variable, so add a word
before the first one and after the last one. WASync checks this and the other
rules before you can continue.
### Send for approval [#send-for-approval]
Give the template a **Template name** that your team will recognise (only your
team sees it). WASync generates the technical name Meta needs: lowercase letters,
digits and `_`, unique on this number and language. The checklist shows what was
verified. Click **Send to WhatsApp for approval**. Nothing is sent to customers.
There is no draft: the list mirrors what Meta has, so a template exists in WASync
only once it is submitted.
### After you submit [#after-you-submit]
The template appears in the list as **Pending**. Meta reviews it: typically a few
minutes, sometimes a few hours, and occasionally up to a day. WASync receives
Meta's verdict automatically and updates the status. **Resync from Meta** pulls
the live state if you want to check at once.
| Status | Meaning |
| ---------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
| **Pending** | Meta is reviewing it. It cannot be sent yet. |
| **Approved** | Ready. This is the only status that can be sent. |
| **Rejected** | Meta refused it. The reason shows on the card. Fix the text and create a new template. |
| **Paused** | Meta paused it. Sends fail until it is active again. |
| **Disabled**, **In appeal**, **Pending deletion**, **Deleted**, **Limit exceeded** | Meta's own states, shown as received. |
**✕** on a card deletes the template, and also deletes it at Meta.
### The default file of a media template [#the-default-file-of-a-media-template]
A template with an image, video or PDF header needs that file at every send.
Meta keeps its copy only for review, so WASync keeps the sample you uploaded as
the template's **default file**. For a template that was approved before this, or
created in Meta, use **Set default image** (or *video*, *document*) on its card;
**Change** and **Remove** are there too. Without a default, whoever sends picks
the file each time.
## Templates created in Meta [#templates-created-in-meta]
Templates you built in WhatsApp Manager are not in WASync until you click
**Resync from Meta** in the template list. Resync imports them with their buttons
and header, refreshes every status, and marks a template as **Deleted** when it no
longer exists at Meta. It is safe to run any time.
## Send a template [#send-a-template]
All three ways below send only **Approved** templates, only from a WABA number,
and refuse a contact who has asked to stop receiving messages. If a customer
replies with a stop request, WASync marks them as opted out; an administrator can
clear the opt-out when the person asks to be contacted again.
### From the chat [#from-the-chat]
In the **WASync tab** of a lead, deal or Smart Process item, and in **WASync
Chat**, click the template icon next to the message box (*Send a Meta-approved
template*). When the 24-hour window is closed, the *Pick a template* button in
the banner opens the same list.
1. Search by name, language or text, and pick a template.
2. Fill in every variable. The first one is pre-filled with the contact's first
name when it is known; edit it as needed. The preview shows the finished
message.
3. If the template has a media header, choose the file: the template's default
file (preselected when it has one) or upload another. **Send** stays disabled
until a file is chosen.
4. Optionally tick **Also ask permission for a WhatsApp call after sending**
(hidden when the template already asks for call permission).
5. Click **Send**. The message appears in the conversation and in the record's
timeline, with the finished text.
### From Bitrix24 automation rules [#from-bitrix24-automation-rules]
Open the lead, deal or Smart Process stage → **Automation rules → Add
automation** and pick **Send WhatsApp Template (WABA)** in the WASync group. It
runs for every record that reaches that stage, one record at a time.
* **WABA Connection**: the number that sends.
* **Template**: only approved templates of that number are listed.
* **Variables**: one row per `{{n}}`. Click **⋯** to open **Insert Field** and
choose CRM fields, or type text. A row can combine several fields and fixed
text. Fields are read from the record the rule runs on.
* **Header image / video / document**: for a media template, choose **File or
link** (upload a file, or paste a link or a field that holds one) or **Template's
example** (the default file kept by WASync).
The recipient is the record's client phone. A deal without a contact yet is
re-checked in the background before WASync gives up.
When something stops a send, the reason is written to the record's timeline
instead of failing silently: a variable that resolved to empty, a template that
is no longer approved, a missing header file, an opted-out contact, or a license
problem. Empty variables stop the send because Meta rejects empty parameters.
After installing or updating WASync, reload the automation page once: Bitrix24
caches robot definitions until the page is reloaded.
### From Chat Flows [#from-chat-flows]
In the flow editor, a **Message** step has a section called **WhatsApp Business
template (window closed)**. Choose the number, an approved template, fill each
variable (a CRM field like `{{NAME}}` or fixed text) and, for a media template,
the header file.
The template is used **only** when the number is a WABA number and the 24-hour
window is closed, for example the first message to a customer who never wrote. If
the window is open, the step sends the normal text. If the window is closed and
the step has no template, it fails with *On a WhatsApp Business number the first
message must use an approved template.* Files attached to the step are not sent
with a template. An empty variable is replaced with a dash instead of stopping the
step. If Meta answers with a temporary error, the step retries once before it
fails.
## What is not included: bulk campaigns [#what-is-not-included-bulk-campaigns]
WASync has no bulk or broadcast campaign module: you cannot upload a list and send
a template to everyone. What it does is send **one template per CRM record when an
automation rule runs**. To message a segment, put those leads or deals in a stage
(or move them there) and let the **Send WhatsApp Template (WABA)** rule run on that
stage.
### Stay within Meta's limits [#stay-within-metas-limits]
* Each number has a **messaging limit** that depends on its quality tier (the
Connections page shows the tier Meta assigned, for example 1,000 customers per
24 hours). Sends above it fail.
* Message only people who expect to hear from you. Each block or report lowers
the **quality rating**; a lower rating lowers the limit, and a template with
poor feedback can be paused.
* Say who you are in the first line and tell people how to stop. Respect a stop:
WASync blocks templates to opted-out contacts.
* When Meta restricts or limits the number, the Connections page and the Templates
window show a banner (*Meta has blocked sending on this number* or *Meta has
limited sending on this number*) with what to do and a link to Meta Account
Quality.
## Troubleshooting [#troubleshooting]
| What you see | What to do |
| ----------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Status **Rejected**, with a reason on the card | Read Meta's reason. Common causes are a promotional text in a Utility template, a variable at the start or end of the text, or missing examples. Create a corrected template under a new name. |
| Status **Paused** | Meta paused the template, usually because of poor customer feedback. Improve the text, or create a new template. Do not keep sending a paused one. |
| *Meta has blocked / limited sending on this number* banner | Open Meta Account Quality with the button in the banner and follow its steps: payment method, business verification or an appeal. Sends and new templates stay blocked until Meta lifts it. |
| *Access token expired or invalid* in the Templates window | On the Connections page, run **Connect with Facebook** on that number to refresh the token. |
| Template not in the list when sending | Only **Approved** templates appear. Check the status, then **Resync from Meta**. |
| Variable error when creating (*isn't a valid variable*, *needs a CRM field and an example value*) | Add variables with **+ Personalize**, not by typing braces, and give each one an example. Numbering must run 1, 2, 3 with no gaps. |
| Robot did not send, timeline says *empty variable(s)* | A field mapped to a variable was empty on that record. Fill the field on the record, or change the variable to another field or to fixed text. |
| *This template has a … header*, or the send is disabled | A media template needs its file. Choose a file at send time, in the rule or step, or set the template's default file. |
| *This WhatsApp connection cannot send templates* | The number is QR-paired. Use a WABA number. |
| *This template asks for call permission, but WhatsApp calling is not enabled on this number*, or a template marked **Needs calling** cannot be picked | Turn on calls for the number in **Connections** → **WhatsApp calls**, or send another template. |
| *Templates to this contact are blocked: this contact asked to stop receiving messages* | The contact opted out. You can still reply to messages they send you. An administrator can clear the opt-out only if the person asked to be contacted again. |
## Related [#related]
* [Connection types](/docs/concepts/connection-types): QR-paired numbers and WABA numbers.
* [Bring a number from another provider](/docs/guides/bring-your-own-number): move
an existing WABA number to WASync.
* [Smart Processes (SPA) in WASync](/docs/guides/smart-processes): the template robot
runs on Smart Process automation rules too.
# Webhooks (/docs/guides/webhooks)
Point WASync at your endpoint and you get a signing secret back. Uses
`whatsapp.events`. No app registration and no consent step is involved.
An account has exactly **one** webhook URL. `PUT /webhook` sets it — calling it
again with a different URL *moves* the endpoint rather than adding a second one,
and there is no delete. This matters as soon as more than one thing wants
events: an [n8n trigger](/docs/guides/n8n) and your own backend cannot both own
the slot. Fan out on your side.
## Set the endpoint [#set-the-endpoint]
```bash title="PUT /webhook"
curl -X PUT https://developers.wasync.app/api/v1/webhook \
-H "Authorization: Bearer $WASYNC_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com/wasync/webhook"}'
```
```json title="200 response"
{
"url": "https://example.com/wasync/webhook",
"events": [
"message.received",
"message.status",
"connection.disconnected",
"connection.connected"
],
"secret": "whsec_3f9a…"
}
```
**Store the secret.** It is issued here because this is the moment you need it
to write your verification code, and `GET /webhook` will not return it again —
that endpoint reports `{ url, events, secretSet }`, deliberately without the
secret, because a read path gets logged and pasted into tickets. Lost it? Call
`POST /webhook/rotate` for a new one. The URL must be HTTPS on a publicly
reachable host; `http`, localhost and private ranges are rejected with
`400 invalid_webhook`.
Rotation has **no overlap window**: the old secret dies the instant the new one
is issued. Deploy the new secret promptly — the retry policy below covers a
rollout measured in seconds, not hours.
## Event catalog [#event-catalog]
| Event | Fires when | Direction |
| ------------------------- | ------------------------------------------------------------------- | --------------------------------------------------------- |
| `message.received` | A WhatsApp message arrives on a granted connection (text or media). | Inbound only — messages you send do not fire this. |
| `message.status` | The delivery state of one of your outgoing messages changes. | Outbound only. |
| `connection.disconnected` | A connection stopped working and needs its owner to pair again. | Once per outage, not repeatedly while it stays broken. |
| `connection.connected` | A connection that had broken is working again. | Once, and only for a connection you were told had broken. |
Ignore unknown `event` values rather than treating them as errors — new types
are announced on the [changelog](/docs/changelog) before they ship.
Events fire for **`qr` connections only**. `cloud_api` connections emit no
webhooks today; poll `GET /messages` and `GET /connections/{id}` for those.
## Payload [#payload]
```json title="POST your webhook URL"
{
"event": "message.received",
"connection_id": "conn_8f3a21",
"message": {
"id": "cmqj3k2ab0001xyz",
"wa_id": "false_40700000000@c.us_3EB0A1B2C3",
"from": "40700000000",
"text": "Hello!",
"media_url": null,
"media_type": null,
"timestamp": 1766138640000
}
}
```
* `message.id` — WASync's stable id (the same value `GET /messages` returns as
`id`). **Dedupe and join on it** — delivery is at-least-once.
* `message.wa_id` — WhatsApp's own id, `null` when unknown. Support and
debugging only, never a dedupe or join key.
* `from` — international digits only, no `+`.
* `text` is `null` for media-only messages; `media_url` / `media_type` are
`null` for text messages or when the file is not publicly fetchable.
* `timestamp` — epoch **milliseconds** as a number, not an ISO string.
A `message.status` delivery updates one of your outgoing messages:
```json title="POST your webhook URL"
{
"event": "message.status",
"connection_id": "conn_8f3a21",
"message": {
"id": "cmqj3k2ab0001xyz",
"wa_id": "true_40700000000@c.us_3EB0A1B2C3",
"status": "read",
"timestamp": 1766138641000
}
}
```
## Verify the signature [#verify-the-signature]
Every delivery carries `X-WASync-Timestamp` (epoch ms) and
`X-WASync-Signature: sha256=`, which is
`HMAC-SHA256(timestamp + "." + rawBody, secret)`. Compute it over the **raw**
body — before any JSON parsing — and compare in constant time. Reject deliveries
whose timestamp is more than \~5 minutes old, which is what blocks replays.
```js title="verify.js"
import crypto from "node:crypto";
// rawBody MUST be the exact bytes you received (verify BEFORE JSON.parse).
export function verifyWASync(headers, rawBody, secret) {
const ts = headers["x-wasync-timestamp"];
const sig = headers["x-wasync-signature"]; // "sha256="
const expected =
"sha256=" +
crypto.createHmac("sha256", secret)
.update(`${ts}.${rawBody}`)
.digest("hex");
return Boolean(sig) &&
crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
}
```
```js title="receiver (express)"
import express from "express";
import { verifyWASync } from "./verify.js";
const app = express();
// Capture the RAW body — signature verification needs the exact bytes.
app.post("/webhooks/wasync", express.raw({ type: "application/json" }), (req, res) => {
if (!verifyWASync(req.headers, req.body.toString("utf8"), process.env.WASYNC_WEBHOOK_SECRET)) {
return res.status(401).end();
}
// Reject stale deliveries (replay window) — 5 minutes is a sane tolerance.
if (Math.abs(Date.now() - Number(req.headers["x-wasync-timestamp"])) > 5 * 60_000) {
return res.status(401).end();
}
res.status(200).end(); // ACK fast — under 10s — then process async
const { message } = JSON.parse(req.body.toString("utf8"));
// ... your logic (dedupe on message.id — retries can deliver duplicates)
});
```
## Delivery & retry policy [#delivery--retry-policy]
| Property | Value |
| ---------------------- | --------------------------------------------------------------------------- |
| Success criterion | Any `2xx`. Everything else, including redirects, is a failure. |
| Attempts | 3 per event — immediate, then after 500 ms, then after 1 s. |
| Per-attempt timeout | 10 seconds. ACK fast and process async. |
| After the last failure | The event is **dropped**. There is no long redelivery queue. |
| Duplicates | Possible. Dedupe on `message.id`. |
| Ordering | Not guaranteed. Order by `timestamp` if it matters. |
| Signature on retries | Identical body and signature are resent — verify each attempt the same way. |
## Status ladder [#status-ladder]
`message.status` values form a one-way ladder: `sent` (1) → `delivered` (2) →
`read` (3), with `failed` as a terminal outcome that does not follow `read`.
**Apply updates monotonically.** Only apply a new status if its rank is higher
than the one you have stored. A message can arrive with `read` before
`delivered` (a late delivery), and duplicate events are possible. Never move a
message backwards in your UI.
## Reconciliation — poll as a safety net [#reconciliation--poll-as-a-safety-net]
Deliveries are attempted three times and then dropped, which makes your webhook
handler the **fast path, not the guarantee**. Run a background loop that polls
`GET /messages?connectionId=…` every **30–60 seconds** and upserts anything the
handler has not seen, using the cursor for incremental fetches. The same loop
backfills status updates that arrived while your endpoint was down.
Webhooks = real-time UI updates. Polling = correctness. Run both.
## Connection lifecycle [#connection-lifecycle]
```json title="POST your webhook URL"
{
"event": "connection.disconnected",
"connection_id": "conn_8f2a…",
"connection": {
"id": "conn_8f2a…",
"phone_number": "393331234567",
"label": "Studio Rossi",
"status": "disconnected",
"needs_reconnect": true,
"license_status": "active",
"license_expires": "2027-08-08T09:00:00.000Z",
"reason": "AUTH_LOST"
},
"timestamp": 1786000000000
}
```
A `qr` connection can stop working for reasons outside anyone's control — the
phone is switched off for a day, WhatsApp is opened on another device, the
session ages out. The number then goes quiet in both directions, and without an
event the first person to notice is your customer.
**The QR code is deliberately not in the payload.** A WhatsApp QR is a
scan-to-login credential: anyone who reads it can take over the session. The
event tells you a re-pair is needed — fetch the QR itself over your
authenticated `GET /connections/{id}` and show it to the number's owner, exactly
as during first setup. Drive your UI off `needs_reconnect`; treat `reason` as an
advisory log hint, since new values can appear.
Detection latency: a disconnect is found by a 5-minute status probe (\~5 min).
When the session looks recoverable an automatic heal is attempted first, so that
path takes \~15–20 minutes.
## Not receiving events? [#not-receiving-events]
* Is the delivery URL HTTPS on a public host? Localhost, private IPs and
`http://` are rejected. Use a tunnel during development, and check what is
actually stored with `GET /webhook`.
* Does the credential carry `whatsapp.events`, and does it cover the connection
the message arrived on?
* Is the connection's licence still active? An expired licence means no events
and `402` on sends.
* Does your endpoint answer `2xx` within 10 seconds? Slow handlers look like
failures and burn all three attempts.
* Is it a `qr` connection? `cloud_api` connections emit no webhooks.
* Only **inbound** messages fire `message.received` — your own sends never do.
# Help Center (/docs/help-center)
Every page here answers one question a customer asked us, in the words they used. Each answer says what happens, where the setting is, and links to the product page that documents the feature in full. The Help Center is kept in step with the product: when a feature changes, its answers change with it.
Not answered here? Write to [support@wasync.app](mailto:support@wasync.app) with your portal name; we answer in writing, usually within the hour on business days.
# Automations (/docs/product/automations)
An **automation** is a Bitrix24 robot you add to a pipeline stage or a trigger. When it fires, WASync reads the lead, deal or contact, asks an AI model to write the message from the instructions you gave and the record's fields, and sends it on WhatsApp from the number you chose. It is the tool for "when the deal reaches this stage, write to the customer about exactly this deal" without a template for every case.
Automations need at least one **Pro** connection on the portal; without it they are listed but do not run.
## Creating one [#creating-one]
**Automations → New automation**: name, the entity it works on (lead, deal, contact), the WhatsApp number that sends, the instructions for the model (what to say, tone, what to use from the record), the language it responds in, and the mode:
| Mode | Behaviour |
| ----------------- | ---------------------------------------------------------------------- |
| **Auto send** | The message goes out the moment the robot fires. |
| **Confirm first** | A person reviews the generated text in Bitrix24 and sends or edits it. |
Then add the robot **WASync AI message** to the automation rules of the stage in Bitrix24 and pick the automation. Reload the Bitrix24 page after adding robots; Bitrix24 reads their definitions at page load.
## Model [#model]
Each automation uses the model set under **Chat Flows → AI assistant** (the same key the Chat Flows AI step uses), or a model of its own chosen in the automation, which overrides the portal default. Keys are stored on the server; the model never sees more than the fields you expose in the instructions.
## Attachments [#attachments]
Up to five files per automation, sent with every message: images, videos, documents, voice notes. The generated text goes as the caption of the first image, video or document; with voice notes only, it goes as a separate message. Files can also come from a file field on the record.
## Statistics [#statistics]
**Stats** on each automation: sent, pending (waiting for confirmation) and failed in the last 30 days, with the failure reasons, typically a record without a phone number, no Pro licence, or a refusal by WhatsApp. **Pause** stops an automation without deleting it.
## Related [#related]
* [Chat Flows](/docs/product/chat-flows) for conversations that ask questions and branch; automations send one message per trigger.
* [Guide: WhatsApp templates](/docs/guides/waba-templates) for Business API numbers outside the 24-hour window.
# Calls (/docs/product/calls)
WhatsApp calls are available on WhatsApp Business API numbers. They are not
available on numbers paired by QR, and not on numbers that run in coexistence
with the WhatsApp Business app on the phone.
Two things have to be in place. The WASync app in Bitrix24 needs the telephony
permission; when Bitrix24 offers an update of WASync in the Market, install it
and calls start working with nothing to reconnect. And calls need a browser tab
with Bitrix24 open, in Chrome, Edge or Bitrix24 Desktop: the voice runs in that
tab, so a closed browser cannot answer.
## Turning calls on for a number [#turning-calls-on-for-a-number]
Calls are a setting of each connection. Open the WASync app, go to
**Connections**, and use the **WhatsApp calls** button on the number. The window
shows **Incoming calls** as ON or OFF; choose **Turn on** or **Turn off**. The
setting is read from WhatsApp every time the window opens, so it always shows
what customers really see. Connections paired by QR show the button as **WhatsApp
calls — WABA only** and cannot be switched on.
With calls on, customers see a call button on that number in WhatsApp. Turn it on
only when someone is available to answer: a call nobody picks up shows the
customer a missed call.
Calling a customer needs their permission, and WhatsApp asks for it with a
call-permission request:
* Tick **Also ask permission for a WhatsApp call after sending** in the template
picker, or choose a template that carries the call-permission card.
* Add the **Ask permission to call** step to a Chat Flow.
A template that carries the call-permission card works only on a number with
calls turned on: WhatsApp approves such a template anyway, then refuses every send
from a number without calls. WASync therefore offers **Include a WhatsApp
call-permission request** in the template builder only when calls are on, marks
these templates **Needs calling** and greys them out in the template picker on a
number without calls, and refuses the send before it reaches WhatsApp, from the
chat, automation rules and Chat Flows alike, with the reason in the conversation.
The customer sees a card in the chat asking whether you may call them. Their answer
is recorded on the contact. In the CRM widget and in WASync Chat the phone icon
turns green while the permission is active, and a chip beside the name reads
**Calls allowed** or **Calls declined**.
WhatsApp allows one permission request per customer per 24 hours and two per
seven days. After four unanswered calls in a row it withdraws your permission to
call that customer, so wait a few minutes before trying again.
## Who is rung for an incoming call [#who-is-rung-for-an-incoming-call]
In **Settings**, administrators find the **Incoming calls** card. It decides who
is rung first when a known customer calls.
| Option | Who rings first |
| --------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
| **The contact's responsible person** | The person responsible for the contact (or company, or lead) in the CRM. |
| **The responsible person of the most recent open deal or lead** | That person. With no open deal or lead, it falls back to the contact's responsible person. |
| **Both at once** | Both people ring together. |
Only people who are online in Bitrix24 and have access to the number are rung.
Access to a number means being in its Open Channel queue or having the number in
**Connections → Staff**; either is enough. Bot users are never rung.
If the person who should ring first is missing, offline, or does not handle the
number, the call goes straight to everyone online who handles it, up to 5 people
at once. The same happens when the first person has not answered after 8
seconds: everyone online who handles the number is rung while the first card keeps
ringing. The 8 seconds are fixed. The first to answer takes the call, and the
other cards close with **Taken by** and that person's name.
When nobody who handles the number is online, the call is saved as missed.
If an operator never gets the call, check two things first: which Bitrix24 user is
logged in in that browser, and whether that user has access to the number in
**Connections → Staff**.
## Answering in the Bitrix24 call card [#answering-in-the-bitrix24-call-card]
A WhatsApp call rings as an ordinary Bitrix24 incoming call. The card shows the
customer's name and number as the title, with **WhatsApp** and the line under it.
Use Bitrix24's own buttons:
* **Answer** takes the call. The card switches to connected and Bitrix24's timer runs.
* **Ignore** declines the call.
* **Mute** and **End** work from the card.
When the call ends, the card says why for a few seconds: **Call ended**, **Missed
— the caller hung up**, **Call declined** or **The call could not be connected**.
The card has a tab named **WASync**. It shows a status line (**Incoming call**,
then **Connected** with a timer) and, under it, the WhatsApp conversation with the
caller on the number they called. You can read the history and write to the
customer while the phone rings or during the call; new messages from the customer
appear by themselves. An operator without access to the called number sees only
the call status. The conversation stays in the tab after the call, until the card
is closed.
The voice runs in the browser tab where the call was answered, inside Bitrix24's
own frame. Keep that tab open: the card tells you so, and the browser asks before
the tab is closed or reloaded.
If the browser blocks the microphone, the WASync panel opens and offers the call
window instead. The call window is also what you use to call a customer.
## Calling a customer [#calling-a-customer]
Place a call from the chat: use the **Call** button in the WhatsApp widget of the
CRM record. The call window shows **Ringing…** with the
customer's name while the phone rings, and switches to **In call** only when the
customer picks up. The timer starts then, so the duration is talk time only.
When the customer does not pick up, the window says why: **No answer**, **Call
declined** or **Line busy**. The last two appear only when WhatsApp reports them.
Calling needs the customer's permission, as described under
[Turning calls on for a number](#turning-calls-on-for-a-number).
Calling back from the **Call** button of Bitrix24's own call card does not work.
Use the Call button in the WhatsApp widget of the CRM record.
Incoming calls are free; outgoing calls are billed by Meta.
## What is logged [#what-is-logged]
Every call is written in Bitrix24 with the CRM record attached:
* The call appears in the **timeline** of the matching contact, lead or deal.
* A call that was answered keeps its talk time as the duration.
* A call that was not picked up is saved as an unanswered outgoing call with no
duration.
* A missed incoming call is saved on the responsible employee.
* The call is also listed in the **Telephony** section of Bitrix24 (call details).
This is the part that needs the telephony permission; if call details stay empty,
update WASync from the Market.
# Chat Flows (/docs/product/chat-flows)
A Chat Flow is a scripted WhatsApp conversation. It sends messages, asks
questions and saves the answers, branches on them, fills in CRM fields, moves
the record to a stage, assigns it to a colleague and hands the chat to a person.
It runs on numbers connected through WASync, both QR connections and the
official WhatsApp Business API ones.
Flows live in the WASync app in Bitrix24: choose **Chat Flows** in the left
menu. The list shows each flow with its on/off switch; opening one opens the
editor. This page describes how flows behave and what the controls do.
## When a flow starts [#when-a-flow-starts]
The Start card of a flow says in plain sentences when it starts. The button
**Change when it starts** opens the trigger panel, where **How the flow starts**
has two choices:
| Choice | What starts the flow |
| ---------------------------- | -------------------------------------------------------------------------------------------------------------- |
| **Bitrix24 automation rule** | A rule you add to a pipeline stage in Bitrix24. The lead or deal already exists; the flow does not create one. |
| **Customer writes first** | A WhatsApp message arrives on the number you choose under **WhatsApp number**. |
With **Bitrix24 automation rule**, the phone on the lead or deal must include
its country code (for example +52 …). WASync does not guess a missing code: the
flow does not start, and the record gets a timeline comment that says why. Add
the prefix in Bitrix24, or set the
[Default country](/docs/product/settings#default-country) in Settings.
For **Customer writes first**, **Which first message** narrows it:
* **Any message**: any message that starts a conversation.
* **Keywords**: only when the first message contains one of the words you list,
separated by commas.
* **From a specific ad**: only when the customer arrives from one of the Meta
Click-to-WhatsApp ads you list, by ad id (from Ads Manager). For a campaign,
list all of its ad ids. An empty list matches any ad.
A customer who sends several messages in a row before the bot answers ("hi",
"good evening", "where are you?") starts one run, not one per message: the
first message is the trigger, the rest are read as part of the same
conversation, and the opening sequence goes out once.
A number can have several inbound flows. When more than one matches, the most
specific wins: the flow for the customer's ad first, then keywords, then *Any
message*. A flow bound to the number beats a workspace-wide one, and at the same
level the older flow wins. A message from an unlisted ad, or from no ad, falls
back to the keywords or *Any message* flow.
A few rules keep a flow from starting when it should not:
* **A reply to your team is not a new conversation.** If a colleague wrote to
the customer in the last 72 hours, from the CRM widget, WASync Chat, the Open
Channel or the business phone, the customer's answer does not start the flow.
Messages sent by flows, automations and robots do not count. The option
**Don't start when we wrote first** turns this off or sets the window to
between 1 and 168 hours.
* **An *Any message* flow waits for a new conversation.** It does not start
while another flow on that conversation ended inside the same window. A flow
that was completed, handed to a person or cancelled counts; one closed for
inactivity does not. Flows started by an ad or by keywords are explicit
intent and still start. Pressing **Allow the flow again** on the
conversation in WASync Chat clears this wait too, so the next message starts
the flow at once, which is handy when you retest a flow from your own phone.
* **A message delivered twice is ignored.** WhatsApp sometimes delivers the
same message again, for example after a session re-sync. The copy never
starts a flow or makes a running flow move on.
The Start card also says whether the flow runs **Once per customer** or **Can
run again for the same customer**, and whether it **Stops when a colleague
replies**.
## Only customers who never wrote to you before [#only-customers-who-never-wrote-to-you-before]
On a **Customer writes first** flow, the switch **Only customers who never wrote
to you before** limits the flow to brand-new numbers. With it on, the flow
skips any phone number that has ever exchanged a message with any of your
WhatsApp numbers in WASync, on this number or another, in either direction. An
existing customer who writes again gets no greeting and no new record; the
message simply reaches your team.
The switch is off by default. Off, the flow starts for anyone when no other rule
holds it back, and the Start card reads *Any message that starts a
conversation*.
## Which record a flow creates or binds to [#which-record-a-flow-creates-or-binds-to]
Under **When it starts**, a **Customer writes first** flow is attached to a
lead, a deal or a Smart Process item (a deal flow also picks the pipeline and
stage). The flow finds the contact by phone number. It never creates a
duplicate of a contact you already have.
| Flow type | What happens at the first message |
| --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Lead** | Binds to the contact's open deal, else to the contact's open lead, else to an open lead that holds the number without a CRM contact, else creates a contact (if needed) and a lead. |
| **Deal** | Binds to the contact's open deal in the chosen pipeline, else creates a contact (if needed) and a deal. |
So a customer who is already being worked never gets a second lead from a flow.
With **Each number creates its own lead** switched on, "already being worked"
means on this number: a first-time contact gets the number's own lead, and an
older lead that merely holds the phone (another tool's lead) is not reused.
The deal is checked first. A lead that carries the customer's number but is not
linked to any CRM contact, such as a lead imported from another tool, counts
too: the flow binds to it instead of creating a lead next to it.
Two settings from **WASync Chat → Chat rules** apply to the records a flow
creates:
* **Who is responsible.** Bitrix24 puts a record without a responsible on the
user who installed the app. To avoid that, a contact, lead or deal created by
a flow takes its responsible from the rule **New chats from unknown numbers**
(a fixed person or round-robin). With that rule **Off**, the flow leaves
Bitrix24's default.
* **Each number creates its own lead.** With this option on, "already being
worked" means on the number the customer wrote to: the flow reuses only the
record created or linked from that number. An open deal or lead the contact
has from another channel, for example an import or another WhatsApp tool, is
left alone and the flow creates the number's own lead.
* **Re-contact window after a closed lead.** A flow that creates a lead uses the
same window as the rule. A customer who writes back inside the window lands on
the lost lead, not on a second one. See [Leads from WhatsApp chats](/docs/guides/leads-from-whatsapp-chats).
## The CRM source of the record [#the-crm-source-of-the-record]
For lead and deal flows, the **Source** selector under **When it starts** lists
your CRM sources. The source you pick is written on the contact, lead or deal the
flow creates. You can, for example, leave a placeholder such as "not selected"
for your team to fill in later, or stamp a campaign source of its own.
The default, **Automatic — the WhatsApp line's source**, gives the record the
source of the WhatsApp Open Channel it came through. A record the flow reuses
instead of creating keeps its own source; the flow never rewrites it.
## Create only the lead, without a new contact [#lead-only-without-a-new-contact]
A lead flow normally creates a CRM contact for a customer it does not know yet
and links the new lead to it. If your own automation rules create contacts
later, or a lead that already has a contact is treated as a repeat customer in
your portal, tick **Create only the lead (no new contact)** under the **Source**
selector on the Start card.
With the option on, the lead is created without a CRM contact. It still gets
the phone number, the name, the source and the responsible as usual. If a
contact with this phone already exists, the lead is linked to it. An open lead
that already holds the number is reused, so a customer who writes again does
not get a second lead. Deal flows do not have this option, because a deal
always needs a client.
## Assign to a person or rotate within a group [#assign-to-a-person-or-rotate-within-a-group]
The **Assign to a colleague** step makes someone the responsible of the lead or
deal, then the flow continues to the next step. **Who gets the record** has two
modes:
| Mode | What happens |
| ------------------------- | ------------------------------------------------------------------------------------------------------------- |
| **One person** | The record goes to the person you choose by name. |
| **Rotate within a group** | You tick up to 50 employees. Each new conversation that reaches the step goes to the next person in the list. |
Every Assign step keeps its own rotation, and saving the flow again does not
restart it. Employees deactivated in Bitrix24 are skipped. If nobody in the
group is active, the record keeps its current responsible and a note on the
timeline says why. A customer who passes the same step twice in one conversation
stays with the same person. A test run shows who is next without using up a real
turn.
**Notify this person in Bitrix24** sends the chosen person a Bitrix24
notification.
## Messages built from CRM fields [#messages-built-from-crm-fields]
A message step can be made only of CRM fields, for example just
`{{UF_CRM_PROMO_TEXT}}`. If those fields are empty on a lead or deal, the step is
skipped and the flow continues with the next step, instead of stopping the
conversation; the editor warns you under the text when a message is made only of
fields. A step that also has files still sends the files, without a caption, and a
question with options still sends its options.
## Fill in a field [#fill-in-a-field]
A **Fill in a field** step writes a value into a CRM field of the lead, deal or
contact: a fixed value, a variable, or the answer to an earlier question. By default
it replaces whatever the field holds. Tick **Only if the field is empty** to keep an
existing value instead, which is what you want for origin fields such as Source or
the UTM fields, so a later flow never changes where a lead came from. When the field
already has a value the step writes nothing and the flow simply continues. A list
field that shows no choice counts as empty; for other fields, including numbers, a `0`
is a value and is kept.
### Save the origin when there is no lead yet [#pending-origin]
Some flows should record where a customer came from without creating a lead, for
example a keyword flow for a code like `(OR)` that only writes **UTM source**
or **Source**, while a supervisor decides later whether the conversation deserves
a lead. Tick **If there is no CRM record yet, save as pending origin (no record is
created)** on a **Fill in a field** step that writes to the lead or deal.
* When the conversation has no lead or deal, the field and its value are saved on
the contact as a pending origin. Nothing is created in the CRM.
* WASync Chat shows a line under the conversation header, for example
*Pending origin: UTM\_SOURCE=OR · will be applied when a lead is created*.
* When someone creates the lead from the chat (**Create lead**), or a flow or the
rule for unknown numbers creates one, the pending values are written into the new
lead or deal and the line disappears. A field the new record already gets (for
example the description WASync sets) keeps its value, and a **Source** that is
not in your CRM source list is skipped.
* Linking the conversation to an existing lead or deal writes nothing on it: an
existing record's origin is never changed. The pending values stay for a record
created later.
* When the conversation already has a record, the step writes to it as usual.
A later save of the same field replaces the earlier value. Up to 20 fields are
kept per contact, and a pending value older than 30 days is ignored.
## Showing the options as buttons [#showing-the-options-as-buttons]
A question step can show its options to the customer, so nobody has to guess
what to type. Turn on **Show the options to the customer** under the options of
the step.
* **WhatsApp Business API numbers:** up to 3 options arrive as buttons under the
question; 4 to 10 options arrive as a list behind one button. The customer taps
instead of typing, and the flow continues on that option.
* **QR numbers**, and whenever buttons are not possible (more than 10 options,
two options that look the same once shortened, a question over 1,024
characters): the options arrive as a numbered list under the question, and the
customer can answer with the number.
WhatsApp limits the text of a button to 20 characters and of a list row to 24;
a longer option is shortened on the button with "…", and the editor shows how it
will look. Keywords keep working: a customer who types the answer instead of
tapping still reaches the right option.
Buttons are a reply inside the 24-hour window: a question step always follows a
message from the customer, so this is met by itself.
Keywords of an option are separated with commas or semicolons
(`continuar, 1, si`).
## WhatsApp forms [#whatsapp-forms]
The **WhatsApp form** step (group **Ask**) sends a message with a button; the
customer opens a native form inside WhatsApp, fills it in and sends it. Each
answer can be written to a field of the lead or deal (or of its contact or
company), and all answers are available to the next steps of the flow.
* Up to 8 fields: short text, long text, email, phone, number, date, single
choice and multiple choice (up to 10 options each), each optional or required.
* Set the text above the button, the button label (up to 20 characters) and the
form title. When the flow is saved, WASync creates and publishes the form on
your WhatsApp Business account; a changed form is published again as a new
form.
* The step has two exits: **Submitted** and **Not submitted** (no answer within
the step's inactivity time).
* WhatsApp Business API numbers only. On a QR number, or when the customer has
not written in the last 24 hours, the form is not sent and the flow continues
on **Not submitted**, with a note on the record.
* Choice answers are written as the option text.
## HTTP request step [#http-request-step]
The **HTTP request** step asks an external system over HTTPS and uses the answer
in the next steps: look up an order, check a balance, fetch a delivery date. The
step has a success line and an error line. The request is made under a fixed
safety policy, not from your browser.
Method, headers, response mapping and limits are covered in
[HTTP request step in Chat Flows](/docs/guides/chat-flows-http-request).
## The AI assistant tab [#ai-assistant-tab]
Everything the AI step needs is set up in one place: **Chat Flows → AI
assistant** (administrators). From top to bottom:
1. **AI provider, key and model** — your own key. It is shared: the AI robots in
Automations use the same one. (Settings only keeps a card that points here.)
2. **Knowledge** — the texts, PDFs and web pages the AI may answer from.
3. **Try a question** — type a question a customer might ask and see the answer,
the passages of your knowledge it used and the model that replied. It runs the
same checks as a real answer, sends nothing to WhatsApp, saves nothing, and
uses your provider's credit like a real answer (up to 20 tries a minute). If
it fails, the message says why: no key, key rejected, model not found,
provider account out of credit or at its limit, or the AI took too long.
## AI step [#ai-step]
The **AI reply** step (group **Talk**) asks your own AI for an answer and sends
it to the customer: questions about opening hours, delivery or your products
that do not fit a fixed menu. It uses the AI provider, key and model you set in
**Chat Flows → AI assistant**, so the cost is on your AI account, not on WASync.
It works on Pro (paid) numbers only.
At the top of the step's panel a short checklist shows what is missing: the AI
key and model, a paid licence on the flow's number (only for a flow bound to one
number) and, for information, how many knowledge sources are selected. **Set up
the key** opens the key card over the editor, so you do not lose the changes you
have not saved yet. **Test this step** at the bottom of the panel runs one
question through the step as it is now, saved or not (reply steps).
What you set in the step's panel:
* **Instructions** — who the AI speaks for, what it may answer and what it must
leave to a person (up to 4,000 characters). Facts it may quote, such as your
hours or a link to your site, go here. **Start from an example** writes a
starting text for you.
* **What the AI reads** — the last messages of this conversation (0–20, 10 by
default), the AI's own earlier answers in this conversation, and the CRM
fields you pick with **Insert field**. Only those fields of this customer's
record are sent to your AI provider; never other customers, never keys.
* **Knowledge** — the texts, PDFs and pages from your
[knowledge base](#knowledge-base) this step may answer from, and whether it
should answer **only** from them.
* **The answer** — send it to the customer (on by default) or only store it.
The answer is saved in a variable, `ai_reply` by default, which later steps
use as `{{AI_REPLY}}`. Maximum length 50–1,000 tokens (400 by default).
* **Safety** — what happens when the AI fails, takes longer than 10 seconds or
a limit is reached: **hand the conversation to a person** (default),
**continue to the next step**, or **end the flow**. `{{AI_ERROR}}` holds the
reason. And what happens when a message looks like an attempt to give the AI
orders (prompt injection): **do not answer and use the fallback** (default),
or **leave that message out and answer the rest**.
How WASync protects the conversation:
* The AI takes no actions. It only writes a text: it does not change the CRM,
assign the lead, check anyone's identity or confirm anything. Steps you
configure do that.
* The customer's messages and the CRM fields reach the AI as data in separate
blocks, after a fixed instruction that tells it to treat them as information,
never as orders, and never to claim it did something.
* Messages that look like an attempt to give the AI orders (in several
languages), role tags, long encoded blocks or messages over 4,000 characters
are caught before the AI is called.
* The answer is checked before it is sent: role tags are removed, links to any
site other than your Bitrix24 portal and wasync.app are removed, and the
length is capped.
* Limits: 10 AI answers per flow run and 500 per day per portal. Each call is
logged with its outcome and token count.
Answers written by the step appear in the chat with a **WASync Bot · AI** label.
The Preview shows `(AI answer)` in place of the answer and never calls your AI.
These protections reduce the impact of prompt injection and make every incident
visible; they do not eliminate it. A customer can still push the AI to say
something you would not have written. What limits the damage is that the AI
step never performs an action and that, by default, anything suspicious goes to
a person. Write instructions that tell the AI what to leave to your team, and
test the flow before you switch it on.
### Choose from a list [#ai-choose-from-a-list]
At the top of the step's panel, **What the AI does** switches between **Write a
reply** (above) and **Choose from a list**. In this mode the AI writes nothing to
the customer: it only picks one of the options you list, and the flow continues
on that option's line. Use it to route a free-text message: "Price", "Book an
appointment", "Complaint", each with its own next steps.
* **Options** — 2 to 12, each with a name and, optionally, **When to choose
it** (a short description that helps the AI). Every option gets its own exit
on the card; reorder or remove them in the panel and the exits follow.
* **Anything else** — on by default: an extra exit taken when no option fits.
* **Ask the customer first** — optional. When filled in, the step sends this
text, waits for the reply like a question and has the AI classify the reply.
Left empty, the AI classifies the latest messages of the conversation.
* **Instructions** are optional here: add context that helps the AI choose.
* The chosen option's name is saved in `{{AI_CHOICE}}` and its id in
`{{AI_CHOICE_ID}}` (`none` for **Anything else**). You can rename the variable.
The AI must answer with exactly one of your options; WASync checks the answer
strictly. An answer that names no option, or one that is not in the list, goes
to **Anything else** when it is on, otherwise to the step's fallback, with
`{{AI_ERROR}}` set. Errors, timeouts, limits and suspected prompt injection
always take the fallback: hand to a person (default), end the flow, or continue
on the **If the AI fails** exit, which appears on the card when you choose it.
The same protections, limits and Pro requirement as **Write a reply** apply.
In the Preview, the flow stops at the step and you pick which option the AI
"chose", so you can test every branch without calling your AI.
## Knowledge base [#knowledge-base]
Give the AI step your own documents to answer from: an FAQ, a price list,
delivery and return terms, a product page. You add them once, in **Chat Flows →
AI assistant → Knowledge**, and pick them in each AI step that should use them.
**Adding knowledge** (administrators):
* **Paste text** — plain text or Markdown. It is ready as soon as you add it. You
can also do this from inside the AI step's panel (**Paste text**): the new
source is added and selected without leaving the editor.
* **Upload PDF** — up to 10 MB. Only the text layer is read, so a scanned PDF
(pictures of pages) has nothing to read; export it with text instead.
* **Add a web page** — an `https://` address. WASync fetches the page **once**,
keeps only its text (no scripts, no images) and does not follow it to another
site. When the page changes, press **Re-index** to fetch it again. Of a very
long page only the beginning is kept (the source says so); a page slower than
10 seconds cannot be added; a page behind a login only gives the login form —
paste its text instead.
Each source shows its state (**Indexing…**, **Ready** or what went wrong), its
size, how many passages it was split into and when it was last indexed. Untick
**Used by flows** to stop every step from using a source without deleting it;
**Delete** removes the source and everything stored from it. Limits: 100 sources
and 5,000 passages per portal.
**Using it in a flow.** In the AI step's panel, **Knowledge** lists your
sources; tick the ones this step may use (up to 20) and set **Passages per
answer** (3–8, 6 by default). Before each answer, WASync looks up the passages
closest to the customer's latest messages and gives them to the AI as reference
data. In **Choose from a list** mode they help the AI pick the right option.
**Answer only from the knowledge** (Write a reply mode): the AI is told to
answer only from those passages. When they do not contain the answer, or no
passage matches, nothing is sent to the customer and the step takes its
fallback (hand to a person by default) with `{{AI_ERROR}}` set to
`no_knowledge_answer`. Use it when a wrong answer would be worse than a
person's answer a few minutes later.
How matching works: by the words of the customer's message, tolerant of
word endings and small typos. With an OpenAI or Google key in **Chat Flows → AI
assistant**, WASync also compares the meaning of the passages (embeddings,
computed with your key) to pick the best ones; with other providers it matches
on words only.
Where your text goes: it is stored only in WASync. The few passages chosen for
an answer are sent to your own AI provider inside the request, and nowhere
else. Text from a page or a PDF is treated like a customer's message — as
information, never as instructions: a passage that looks like an attempt to
give the AI orders is left out of the request. Everything is deleted with the
source, and with your portal.
## Inactivity reminders and closing [#inactivity-reminders-and-closing]
When a question waits for an answer the customer never gives, the flow can
remind them and then close. Two places set this:
* **Flow settings → If no reply** holds the default for the whole flow. Switch on
**Remind, then close questions that get no reply**. It applies to every
question without its own setting.
* Each question has its own **If no reply** section: **Use the flow default**,
**Own setting for this question**, or **Off for this question**.
An own setting has four parts:
| Setting | Meaning |
| ------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Wait without a reply** | Minutes before the reminder. |
| **Then send this reminder** | The reminder text. Leave it empty to close right after the wait, with no reminder. |
| **Still no reply? Close the run (inactivity) after another** | Further minutes before the run closes. |
| **When the run closes, send this message** | Optional. A last text the customer receives when the run closes, for example "We didn't hear back, so this conversation was closed. Whenever you want to continue, just send us a new message here." Leave it empty to close silently. |
Times are whole minutes, from 1 to 1,440. A question with no default and no
setting of its own simply waits, for up to 24 hours, and then the run is
cancelled.
The reminder and the closing message are sent by the flow, and WASync records
them as the flow's own messages. They do not count as a colleague taking over
(**Stop when a colleague replies**) and they do not count as "you wrote first"
(**Flows do not start on a reply to your team**), so the customer's next
message is treated as a new conversation.
When a run closes for inactivity, a comment is added to the bound lead or deal.
A run closed this way does **not** block the customer. If they write again
later, the flow starts over as a new conversation. Every other way of ending a
flow still counts as "already done" for flows set to run once per customer.
## The editor [#the-editor]
The editor shows the flow as cards joined by lines, with a side panel for the
selected step.
* **Start step.** There is exactly one, and it cannot be deleted. It describes in
plain sentences when the flow starts, for example *Starts when a customer
writes first to +…, with any message.* **Change when it starts** opens the
trigger panel.
* **Side panel.** Clicking a step opens its settings beside the canvas, so the
flow stays visible while you edit. There is no modal.
* **Pickers with names.** People, stages, pipelines, sources and CRM fields are
chosen by name from lists, never by typing an ID. A Branch takes conditions as
Field, Condition, Value.
* **Step palette.** The palette is grouped (*Talk*, *Decide*, *Do in the CRM*,
*Hand over*, *Finish*) and searchable with **Search for a step…**.
* **Top bar.** An editable flow name, a live problems pill (*N problems*) that
jumps to the step to fix, Undo and Redo, and **Flow settings**.
### Insert a step on a connection line [#insert-a-step-on-a-connection-line]
Hover a line between two steps and a **+** appears next to the **×**. It opens
the same step picker as the **+** on a step and puts the new step in between,
keeping the branch or answer option the line carried. The new step lands halfway
along the line with its panel open.
+
### Find a step [#find-a-step]
The **Find a step…** box in the top bar searches every step by name, message
text, question options and keywords, branch names, assignee and step type. Press
**Enter** to jump to the next match and **Shift+Enter** to the previous one; the
step is selected, centred and flashes for a moment. **Ctrl+F** (**Cmd+F** on a
Mac) while on the canvas focuses the box, and **Esc** closes it.
### Highlighted lines [#highlighted-lines]
When a step is selected, its incoming and outgoing lines turn green and come to
the front while the other lines fade. A long connection is easy to follow on a
large canvas.
# Connections (/docs/product/connections)
WASync works with two kinds of number. A **QR connection** links the WhatsApp
on a phone as a linked device, the same way WhatsApp Web does. A **WhatsApp
Business API** connection is the official number registered through Meta, with
message templates and WhatsApp calls.
Everything starts in the WASync app in Bitrix24: choose **Connections** in the
left menu. Each connection is bound to a Bitrix24 Open Channel, so its messages
land there. Only Bitrix24 administrators see the Connections page.
## Pairing a phone by QR or pairing code [#pairing-a-phone-by-qr-or-pairing-code]
Click **Add WAPP (QR)**, give the connection a name, pick the Open Channel it
should feed, and scan the code from WhatsApp → Settings → Linked devices. If
you are setting up on the same phone that runs WhatsApp, use a pairing code
instead of the QR. Details and limits are in
[Pairing code & QR](/docs/guides/pairing-and-qr).
A second scan of a number that is already connected on your workspace is
refused. The refused row says **Number already connected on another row**:
delete it and keep using the connected one. This prevents duplicate history
imports and duplicate CRM notes.
To bring in the chats a number already had before it was connected, use
**Sync history** (**Import chat history**). The import runs on the server, so
it keeps going if you close the page, and anything already imported is skipped.
On a busy number it can take several minutes. It is only available while the
number is online.
## Connecting a WhatsApp Business API number [#connecting-a-whatsapp-business-api-number]
Choose **Add WABA (Facebook)** and follow Meta's Embedded Signup window. You
sign in to Facebook, pick or create the business portfolio and the WhatsApp
Business account, verify the number, and WASync finishes the registration.
If the number is also used in the WhatsApp Business app on your phone, Meta
can connect it in coexistence mode. You keep chatting from the phone, and
every message also appears in Bitrix24. Two limits come with it:
* WhatsApp calls from the CRM are not available on that number. The Call button
is disabled with an explanation, and the phone app can still call.
* A message you write from the phone does not open the 24-hour customer-service
window, so a template may still be needed to reach the customer from the CRM.
The WhatsApp Business account needs a payment method in Meta Business Manager
(WhatsApp Manager → Billing & payments). Without one, Meta blocks sending
and the number shows a sending-blocked notice.
## Bringing a number from another provider [#bringing-a-number-from-another-provider]
If your WhatsApp Business API number runs at another provider today, the
**Bring a number** wizard moves it to WASync and keeps its display name,
quality rating and messaging limits. The wizard works before your first
Business API connection: open it from the link inside **Connect WhatsApp
Business API**, or from **Bring a number from another provider** on the
Connections page. Step by step:
[Bring a number from another provider](/docs/guides/bring-your-own-number).
### Conversation routing at Meta [#conversation-routing-at-meta]
If Meta's **Conversation routing** still makes your previous provider the
primary partner for the number, customer messages keep going there and sends
from WASync fail with error 131070. WASync checks this after the move and
several times a day, and shows a red warning on the number in **Connections** with the steps:
in Meta Business Suite, **Settings**, **WhatsApp accounts**, the number,
**Conversation routing**, set WASync as **Primary** for Customer service,
Click-to-WhatsApp ads, Utility, Marketing and Calls, and as the **Escalation**
partner, or remove the previous partner under **Partners** / **Messaging
accounts**. Full steps:
[Conversation routing at Meta](/docs/guides/bring-your-own-number#conversation-routing-at-meta).
## When a QR connection disconnects [#when-a-qr-connection-disconnects]
A QR connection stays alive only while WhatsApp keeps the linked device. When
it drops, WASync sends a "WhatsApp disconnected" e-mail and a Bitrix24 notice,
and the row shows **Needs reconnect — scan QR**. The alert names the likely
cause:
| Likely cause | What to do |
| --------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Someone logged out the linked device from the phone | Scan the QR again. |
| The same number was moved to the WhatsApp Business API | Use the Business API connection; see below. |
| WhatsApp removed the device after the number messaged many new contacts in a short time | Reply to people who write to you, add only a few new contacts a day, and send bulk or promotional messages from a WhatsApp Business API number. Otherwise WhatsApp can block the number. |
Click **Reconnect** on the row to show the QR and scan it from the phone. The
connection, its chat history and its Open Channel link are kept. **Restart**
is the milder option when the row says Connected but messages stop going out.
When the same number is later connected on the WhatsApp Business API in the
same workspace, the old QR connection is retired quietly: no "disconnected"
alerts and no repeated reconnection attempts for it. Scanning the number by QR
again brings the row back.
Deleting a connection removes its chat history from WASync, unlinks the Open
Channel and stops the automations that use it. If something does not work, use
**Reconnect** or **Restart** first.
## Staff access to a number [#staff-access-to-a-number]
Open **Connections → Staff** to decide who may use which number. A person with
access can send and receive WhatsApp messages on the number through WASync,
in chats and for calls. A person without access sees a **No access** label and
cannot. Use **Edit Access** on a row to change it, and the **Has access** and
**No access** filters to find people quickly. Bitrix24 administrators see every
number.
Each person can also have a primary number. WASync uses it for their leads and
deals when an automation, robot or Chat Flow does not pick a specific number.
Without one, their first accessible number is used.
### Reports for non-administrators [#reports-for-non-administrators]
The Reports page (response times, activity per person, and the CSV/XLSX export
of conversations) is open to Bitrix24 administrators. To give it to someone
else, open **Staff → Access** on their row and set the **Reports** area to
**Read**: they get the Reports page and its export, and nothing else from the
console. Write adds nothing on this area. The export contains every
conversation of the portal, so give it only to people who may see them.
## Trial and licence [#trial-and-licence]
Every number starts with a 7-day free trial, no credit card required. After
the trial each number needs its own plan, a WAPP plan for a QR connection or a
WABA plan for the WhatsApp Business API. Current prices are on
[wasync.app/pricing](https://wasync.app/pricing). A number whose trial or
licence has ended is disconnected until a plan is chosen.
# CRM records and timeline (/docs/product/crm-records)
Every WhatsApp conversation in WASync is linked to a Bitrix24 contact and, by the rules you set, to a lead, a deal or a Smart Process item. The contact is how the customer is recognised by phone number. The lead, deal or item is the record the team works on.
That link decides three things: who sees the chat in WASync Chat, which stage and responsible show on the conversation, and where the messages are written on the CRM timeline. This page describes each piece and where to change it.
## Contacts [#contacts]
WASync stores every customer phone number in one canonical form: digits only, country code first, no "+" and no spaces. A number typed in national format (for example `0745 823 433`) is completed with the **Default Country** of the portal, then with the country of the WhatsApp number it is sent from. If the country cannot be worked out, nothing is created and WASync asks for the country code.
On QR connections the customer's WhatsApp name and profile photo arrive in the Open Channel chat with their first message. If the photo is not ready within about a second and a half, the message is delivered anyway and the photo follows later.
An administrator can also copy them to the CRM contact. Open **Settings** and find **CRM contact name and photo**, then turn on **Copy the WhatsApp name and profile photo to the CRM contact when they are empty**.
* It is off by default.
* It fills the name and photo only when they are empty on the contact. It never overwrites what your team entered.
* It happens once per contact.
* On WhatsApp Business API numbers only the name is available, because Meta does not provide customer photos.
Every lead WASync creates comes with a contact: an existing one found by phone or email, otherwise a new one.
## Leads and deals [#leads-and-deals]
When a customer writes, WASync links the conversation to their open record in this order: an open deal, then an open lead, then the contact. When the number is not in your CRM, the **New chats from unknown numbers** rule decides whether a lead is created and who gets it. That rule, round-robin, and the re-contact window after a closed lead are described in [Leads from WhatsApp chats](/docs/guides/leads-from-whatsapp-chats).
When a lead or deal has several contacts, the conversation of any of them is linked to that lead or deal, not only the primary contact's.
### Each number creates its own lead [#each-number-creates-its-own-lead]
By default an open lead or deal counts for a conversation whatever channel it came from. The option **Each number creates its own lead** (off by default) changes that: an open record counts only if it was created or linked from the same WhatsApp number the customer wrote to.
Use it when one customer can reach you on several numbers and each number is a separate channel or branch with its own team, or when another WhatsApp tool runs next to WASync and creates its own leads. With it on:
* a customer who writes to a new number gets a new lead for that number, attached to their existing contact, assigned by your rule;
* the old record is not touched, and later messages on that number go to the new lead;
* the CRM timeline, the record shown on the conversation row and the stage filter follow the record of the number the last message came through.
Records created before the option was turned on have no number, so they are not matched per number.
### When the number's record is closed [#when-the-numbers-record-is-closed]
With one lead per number, the record of a number can be won or lost while the
customer is still being worked on another open lead or deal. Two things keep
the conversation off a closed record. This behaviour is off by default; write to
support to turn it on for your portal.
* **You send from an open record.** When the conversation's record on that
number is closed and you (or an automation rule) send a message from an open
lead, deal or Smart Process item, that record becomes the conversation's
record on the number. A record that is still open is never replaced; use
*Change record* for that.
* **The customer replies to a closed record.** Before a new lead is created,
WASync looks for an open deal or lead of the customer's CRM contact and, when
it is not another number's record, moves the conversation there.
Only when there is no such open record is a new lead created, as before. This
is on for every portal that uses one lead per number.
### Ad attribution [#ad-attribution]
When the first message comes from a click-to-WhatsApp ad, WASync writes the UTM fields and the ad name on the lead or deal. The attribution is written on the contact as well and on every open deal that has none, and a later ad does not overwrite an existing attribution. A deal created a few minutes after the message still receives it.
When no record exists yet at the first message (for example on a number without an Open Line), the lead or deal you create or link later from WASync Chat receives the attribution, as long as the ad message is from the last 7 days.
WhatsApp tells WASync only which ad it was. By default `UTM Campaign` carries the ad id and `UTM Content` the click id. With a Meta Ads token saved in **Settings → Campaign and ad set on conversations from ads**, WASync also reads the ad set and the campaign from your ad account and writes them Meta's way: `UTM Campaign` = campaign id, `UTM Term` = ad set id, `UTM Content` = ad id, with their names on the timeline note. Setup: [Campaign and ad set on conversations from ads](/docs/guides/meta-ads-campaign-attribution).
## Records with several phone numbers [#records-with-several-phone-numbers]
A lead, deal, contact or company can hold more than one phone, and a deal can
have several contacts. The WASync tab of the record now lists every WhatsApp
number it can reach: the record's own phones, the phones of each contact, and
the company phone, each labelled with the person it belongs to and the phone
type from Bitrix24 (mobile, work, home).
* With one number the tab works as before and shows no picker.
* With two or more, a number picker appears in the header of the tab. Pick a
number and the thread, the 24-hour window and the templates switch to it.
* The tab opens on the number you used last on this record; the first time, on
the number with the most recent message, otherwise on the first phone.
An employee limited to their own records can message any number that is on a
record assigned to them, not only the first one.
## Smart Processes [#smart-processes]
WASync treats a Smart Process item like a lead or a deal: the **WASync** tab on the item card shows the conversation with the item's client, a conversation in WASync Chat can be linked to an item, and messages are written on the item's timeline. WASync robots and Chat Flows can run from a process's automation rules.
The item needs a client with a phone number, so the process must have **Client** enabled. See [Smart Processes (SPA) in WASync](/docs/guides/smart-processes) for the requirements and setup.
## What is written on the timeline [#what-is-written-on-the-timeline]
Each WhatsApp message is written as a comment on the CRM timeline of the linked record: messages sent and received, files, send errors and robot sends. An administrator controls it in **Settings** under **CRM Timeline Log**.
| Setting | Effect |
| ------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| **Log WhatsApp messages in the CRM timeline** | Off stops every timeline comment WASync writes. Nothing is deleted: the conversation stays in the CRM widget and in WASync Chat. |
| **Write the comment only on the conversation's record** | One comment per message, on the record the conversation is linked to: the open deal or lead, otherwise the contact. |
| **One comment per day per record** | One comment per record per day instead of one per message; each message is added to it as a line. See below. |
Without the second setting, every message is logged on every lead, deal, contact and company that carries the customer's number. For a customer with several records that buries the calls, tasks and notes your team needs to see, so most portals with many records per customer benefit from turning it on.
Some details:
* A reply sent from the Open Channel is logged once.
* A message sent by an operator is written as that operator's comment, so Bitrix24 shows them as the author, not the person who installed WASync.
* Incoming messages are logged by the app's user, because the customer is not a Bitrix24 user.
* Ad attribution is still written to the UTM fields when the timeline log is off.
### One comment per day per record [#one-comment-per-day-per-record]
With **One comment per day per record** on, the first message of the day on a record creates one comment, headed with the date and the customer's number. Every later message that day is added to the same comment as a line:
```
WhatsApp — 4 Nov 2026 · +40712345678
09:05 ← Good morning, is the room still free?
09:12 → Yes, I'll send you the offer now (Ana Pop)
09:13 → 📎 offer.pdf (Ana Pop)
```
`←` is a message from the customer, `→` one from your team, followed by the operator's name. Files appear as a link and a failed send as a `⚠️ Error` line. The next day starts a new comment.
Some details:
* The day follows the time zone of your portal's country (the **Default country** in Settings, otherwise the country of the portal's address or of the WhatsApp number).
* The daily comment is written by the user who installed WASync, not by the operator: Bitrix24 cannot change the author of a comment that keeps growing. The operator's name is on each line instead.
* If someone deletes the daily comment, the next message starts a new one.
* A very long day continues in a second comment marked "(cont.)".
* Combine it with **Write the comment only on the conversation's record** to get a single comment per day on a single record.
## Moving a conversation to another record [#moving-a-conversation-to-another-record]
A conversation that is linked to a lead or a deal has a **Change record** button in WASync Chat, next to the responsible person. It opens the same search as **Link to record**. Pick the lead, deal or contact, confirm, and the conversation moves.
Only WASync's link changes. The old record keeps what is already written on its timeline, and new messages go to the new record. With **Each number creates its own lead** on, the link of that number is replaced and the target must be a lead or a deal.
If the deal a conversation was linked to is deleted in Bitrix24, you do not need to do anything. WASync confirms the record is gone, drops the old link and re-links the conversation: an open deal first, then an open lead, then the contact. A record you simply cannot read is never treated as deleted.
## The responsible of records WASync creates [#the-responsible-of-records-wasync-creates]
When WASync creates a lead for a new chat, or a Chat Flow creates a contact, lead or deal when it starts, the responsible is taken from the **New chats from unknown numbers** rule: the fixed person, or the next person in the round-robin list. Records created from the **Create lead** button in WASync Chat are assigned to the operator.
With the rule set to **Off**, no responsible is given, and Bitrix24 puts the record on the app's user: the administrator who installed WASync.
If your Open Channel routes conversations to the CRM responsible, every conversation of that customer then goes to the administrator who installed WASync. Set **New chats from unknown numbers** to **Fixed person** or **Round-robin** so that records created by WASync start with the right owner.
## WhatsApp from CRM Marketing and automation rules [#whatsapp-from-crm-marketing-and-automation-rules]
WASync registers itself in Bitrix24 as a message provider named **WASync
WhatsApp**. It appears wherever Bitrix24 lets you choose a message channel,
and what the customer receives is a WhatsApp message, never an SMS:
* **CRM Marketing → campaigns**, under *Send using*. The campaign text goes to
every recipient of the segment on WhatsApp.
* The **Send message** automation rule in a pipeline.
* The message button on a lead, deal, contact or company. Bitrix24 labels that
button *SMS*; with WASync WhatsApp selected it sends on WhatsApp.
SendSMS
· using SendSMS
ROSMS
· using ROSMS
WASync· using WASync
Messages leave from your WASync number: the one chosen in Settings, otherwise
your default connection, otherwise the first connected number, with a Business
API number preferred over a QR one. Each message is written on the timeline of
the record it was sent from and shows in WASync Chat like any other message.
Bitrix24 shows the delivery status it gets back from WASync: *sent*, or
*failed* with the reason.
Campaign text is free text. On a WhatsApp Business API number a free-text
message reaches only customers who wrote to you in the last 24 hours; everyone
else needs an approved template, which you send from WASync Chat or the
template automation rule. On a QR number the usual warm-up limits of a new
number apply, and a customer who asked you to stop receiving messages is never
written to.
## Robot messages and the record [#robot-messages-and-the-record]
When an automation rule sends **Send WhatsApp message** or **Send WhatsApp
template (WABA)** from a lead or deal, WASync treats it like a message sent
from that record's widget. If your portal uses [one lead per number](#each-number-creates-its-own-lead)
and the conversation has no record on that number yet, it is bound to the lead
or deal the robot ran on. The customer's reply then stays on that record with
its responsible, instead of opening a new lead. A conversation that already has
a record on that number is not moved unless that record is closed
([when the number's record is closed](#when-the-numbers-record-is-closed));
use *Change record* for that.
## Large batches [#large-batches]
When an automation rule runs the WASync robots **Send WhatsApp message**,
**Send WhatsApp template (WABA)** or **Start chat flow** on many records at
once, for example when you move hundreds of deals into a stage, Bitrix24 limits
how fast an app may read your CRM. WASync does not drop those runs: it puts
them in a queue and sends them at a steady pace, about one per second for your
portal, in the order the rule started them. You do not need to split a
campaign into small batches by hand.
* In the automation log Bitrix24 shows the robot's status as *queued*. The
message follows within minutes and is written on the record's timeline as
usual.
* A large batch goes out one record after another: 3,000 records take about an
hour.
* A run that still cannot go out after about a quarter of an hour of retries
leaves one comment on the record's timeline with the reason, so you can run
the robot again on that record.
## Related [#related]
* [Leads from WhatsApp chats](/docs/guides/leads-from-whatsapp-chats): the new-chats rule, round-robin and the re-contact window.
* [Smart Processes (SPA) in WASync](/docs/guides/smart-processes): the WASync tab and automation on items.
# WhatsApp groups (/docs/product/groups)
On a **QR number**, WASync can mirror every WhatsApp group the number belongs to into a Bitrix24 group chat. Group members keep using WhatsApp; your team follows and answers from Bitrix24. Business API numbers do not take part in WhatsApp groups, so the bridge is QR-only.
## Turning it on [#turning-it-on]
**Connections → the number → Edit → WhatsApp Groups Bridge.** From then on, the first message in each group creates a Bitrix24 group chat named after the WhatsApp group, through WASync's supervisor bot, with the members of the number's Open Channel queue as participants. Groups the number joins later are added the same way, at their first message.
## What is mirrored [#what-is-mirrored]
* **Incoming messages**, posted by the bot as `Sender: text`, where the sender is the member's WhatsApp name and phone; your own number's messages typed on the phone appear as `ME`.
* **Media**: images, audio, video and documents are uploaded into the Bitrix24 chat with the sender in the same message; older portals fall back to a file plus a separate line.
* **Edits and deletions** in the group: a note in the Bitrix24 group chat, never a separate one-to-one conversation.
* **Replies from Bitrix24**: a message or file written in the group chat is sent to the WhatsApp group from the number, and appears there as the business.
Group messages are kept apart from one-to-one conversations: they do not create leads, do not start Chat Flows, and are not listed in WASync Chat's inbox. WhatsApp group calls are not bridged.
## Related [#related]
* [Connections](/docs/product/connections)
* [Connection types](/docs/concepts/connection-types)
# Product (/docs/product)
WASync connects WhatsApp numbers to your Bitrix24 CRM: conversations reach the
Open Channel and WASync Chat, records are created and linked by rules you set,
flows answer customers automatically, and WhatsApp calls ring inside Bitrix24.
Each page below covers one surface of the app and is kept up to date as the
feature changes; the dated [changelog](/docs/changelog) only says *when*
something arrived and points here.
Looking for the API, webhooks, MCP or n8n? Those live under
[Quickstart](/docs/quickstart), [Guides](/docs/guides) and the
[API reference](/docs/api-reference).
# Quick replies (/docs/product/quick-replies)
Quick replies are saved texts an operator inserts by typing **/** at the start of a line, or after a space, in the composer of WASync Chat or of the WhatsApp tab on a CRM record. The list filters as you type the shortcut; Enter inserts the reply with its variables already filled for the open customer.
## Personal and team replies [#personal-and-team-replies]
Each reply is either **personal** (visible only to the person who created it) or **shared with the team** (visible to everyone on the portal). Both kinds live in the same list, managed under **Quick replies** in the sidebar: shortcut, text, language versions, and who may see it. A shortcut must be unique within a person's own replies and within the team's.
## Variables [#variables]
Written with double braces, rendered on the server at the moment of insertion:
| Variable | Value |
| ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `{{greeting}}` | "Good morning", "Good afternoon" or "Good evening" in the customer's language, by the customer's local time |
| `{{contact.first_name}}`, `{{contact.name}}`, `{{contact.phone}}` | From the WhatsApp contact |
| `{{record.title}}`, `{{record.stage}}`, `{{record.responsible}}` | From the lead or deal the conversation is linked to |
| `{{crm.FIELD}}` | Any field of that record, by its code, for example `{{crm.UF_CRM_1764232595}}`; lists and dates are rendered as labels and formatted values |
The customer's language and time zone are deduced from the country of their phone number; when the portal has no time zone, UTC is used.
## Language versions [#language-versions]
A reply can hold several language versions under one shortcut. The version matching the customer's language (from the phone country) is inserted; the default version otherwise. Useful for teams who serve several countries from one number.
## Related [#related]
* [WASync Chat](/docs/product/wasync-chat)
* Help Center: [Do you have quick replies?](/docs/help-center/wasync-chat/quick-replies-with-slash)
# Reports and export (/docs/product/reports)
**Reports** in the sidebar is for Bitrix24 administrators. It reads the conversations of every WhatsApp number on the portal and shows, for the period you pick:
## Tiles [#tiles]
| Tile | Meaning |
| ------------------------ | -------------------------------------------------------------------------------------------------------------------- |
| **Conversations** | Distinct customers who wrote in the period, with the number of inbound messages. |
| **Answered by a person** | Conversations where someone from the team replied, as opposed to conversations handled only by flows or automations. |
| **Median response time** | The median time between a customer's message and the first human reply, over the replies in the period. |
| **Waiting now** | Customers whose last message has no reply yet. |
Times are shown in UTC, which the page says next to the figures.
## Daily chart [#daily-chart]
Inbound messages and human replies per day, with the median response time as a second series. **Show table** lists the same numbers day by day.
## Per employee [#per-employee]
Conversations, replies and median response time for each employee. A reply counts for an employee when WASync could attribute it: messages sent from WASync Chat, the CRM tab or the Open Channel are attributed; messages typed on the phone or sent before attribution existed show as **not attributed**.
## Export [#export]
**Export** produces a CSV or XLSX of every conversation on the portal, across every number, for the period you choose: timestamp, direction, contact, linked CRM record, message type, template, status, and links to media (valid for 24 hours). Exports are capped at 50,000 rows; narrow the period if you hit the limit. The export respects nothing but the period: it is an administrator's view of everything.
## Related [#related]
* [WASync Chat](/docs/product/wasync-chat)
* [Settings and Chat rules](/docs/product/settings)
# Settings and Chat rules (/docs/product/settings)
Two pages hold the portal-wide behaviour of WASync. **Settings** (sidebar) covers the CRM, ads, alerts and defaults. **WASync Chat** in the sidebar opens the **Chat rules**: who sees which conversation, what happens with a chat from an unknown number, who may change stages. Both are for Bitrix24 administrators; everything else is per number, under [Connections](/docs/product/connections), or per person, under [Team](/docs/administration/team-and-access).
## Chat rules [#chat-rules]
### Who sees what [#who-sees-what]
The default visibility for employees who have no level of their own, set per person in Team: **All chats of the numbers they may use**, **Department**, or **Only the records they are responsible for**. Bitrix24 administrators always see everything. The level applies to the conversation list, the search, the "Assigned to" filter and the export.
### New chats from unknown numbers [#new-chats-from-unknown-numbers]
What happens when a number that is not in your CRM writes for the first time:
| Choice | Effect |
| ---------------- | ----------------------------------------------------------------------------- |
| **Off** | No record is created; the chat is visible to people who see all chats. |
| **Fixed person** | WASync creates a lead and assigns it to that person. |
| **Round-robin** | WASync creates a lead and assigns it to the next person on the list, in turn. |
Numbers already in your CRM are linked to their existing record instead. Three switches refine the rule:
* **Also on connections bound to an Open Line.** Bitrix24 creates its own lead only when an operator takes the chat; with this on, WASync creates it at the first message.
* **Also when an operator writes first.** A conversation started from WASync Chat to an unknown number gets a lead with that operator as the responsible.
* **Lead for a known contact without an open record.** A contact that exists but has no open lead or deal gets a lead on its first message.
Flows that create records at enrolment take the responsible from the same rule. [The responsible of records WASync creates](/docs/product/crm-records#the-responsible-of-records-wasync-creates).
### Each number creates its own lead [#each-number-creates-its-own-lead]
Off by default: one customer is one record across all your numbers. On: the record belongs to the conversation on that number, so a customer handled on two numbers has two leads, and flows reuse only the record of the number they run on. Useful when each number is a separate business line or when another tool creates records on the same customers.
### Re-contact window after a closed lead [#re-contact-window]
In hours, 0 by default. A customer who writes back while their **lost** lead was closed less than that many hours ago returns to that lead instead of getting a new one; an option reopens the lead into a stage you choose. Converted leads are never reused. With one lead per number, a lost deal the conversation is linked to counts too; it is never reopened. The window applies to new chats and to flows that create a lead at enrolment.
### Hide closed [#hide-closed]
Off by default. On, a closed lead or deal stops giving visibility to its former responsible after the number of days you set (0 = immediately), on the Department and Only-my-records levels. **Ignore the contact's responsible** is usually needed with it: otherwise a contact assigned to the same agent keeps the chat visible.
### Stage picker [#stage-picker]
Who may change the CRM stage from the WASync Chat header: everyone, administrators only, or nobody (the stage is shown, not editable). The picker already respects each employee's CRM rights in Bitrix24.
### Required fields per stage [#required-fields-per-stage]
For each lead or deal stage, the fields an operator must fill before moving a record there from the chat. Bitrix24 does not apply its own required-field rules to stage changes made through the API and does not expose them, so this list is maintained here by hand; the chat asks for the fields in a small panel before the stage changes.
### Contact owner only without record [#contact-owner-only-without-record]
Not in the interface; set per portal on request. By default a conversation counts as "mine" also through the responsible of the CRM contact. With this option, the contact's responsible counts only when the customer has no open lead or deal; otherwise the lead or deal owner wins.
## Settings [#settings]
### CRM timeline log [#crm-timeline-log]
Where messages are written on the timeline: on every record that carries the number (default, including closed leads), or **one comment on the conversation's record**, the one shown in the chat header. Comments already written are never moved. [CRM records and timeline](/docs/product/crm-records).
### CRM contact name and photo [#crm-contact-name-and-photo]
Off by default. On, the WhatsApp name is copied to the contact card when the card has no name or only the phone number as its name, and the photo when the card has none; nothing existing is overwritten. The photo is available on QR numbers only.
### Campaign and ad set on conversations from ads [#campaign-and-ad-set]
A Meta Ads System User token with `ads_read`. With it, conversations from Click-to-WhatsApp ads carry the campaign, ad set and ad in the record's UTM fields; without it, only the ad id. [Guide](/docs/guides/meta-ads-campaign-attribution).
### Bitrix24 Open Channels [#bitrix24-open-channels]
Which Open Channel each number feeds, and the option to create a channel for a number that has none. A conversation reaches the channel's queue and its CRM rules in addition to WASync Chat. A photo, video, voice message or document the customer sends without a caption arrives with a short one in the portal's language (for example “🎬 Video”), and when Bitrix24 cannot attach a file, the message still arrives with that caption and a link to the file.
### Chat title from CRM fields [#chat-title-from-crm-fields]
Names every Open Channel chat from a template, for example `WA: {{company.UF_CRM_CODE}} {{company.TITLE}} - {{contact.name}}` gives “WA: 1042 Comercio - María”. Empty (the default) keeps the title Bitrix24 gives the chat. The card has the CRM field picker and a preview built from your latest WhatsApp chat.
* **Fields:** `{{contact.name}}`, `{{contact.first_name}}`, `{{contact.phone}}`, `{{contact.FIELD}}` (the CRM contact), `{{record.title}}`, `{{record.stage}}`, `{{record.responsible}}`, `{{crm.FIELD}}` (the conversation's lead, deal or other record), `{{company.FIELD}}` (the record's company, else the contact's), `{{line.name}}` (the Open Channel's name) and `{{line.phone}}` (the WhatsApp number the chat is on, for example “+595981000111”). A field with no value is left out together with the separator next to it; when no field has a value, the chat keeps its title.
* **Skip the rename when a field is empty:** off by default. On, a chat is renamed only when every field in the template has a value; otherwise it keeps its current title (Bitrix24's own, or the last one WASync set). The preview shows when that would happen. The title is checked again when the conversation is linked to another record, when the template changes, or when the automation step runs, for example on the company after its code is filled in.
* **Open Channels:** tick the channels whose chats WASync may rename. None ticked (the default) means every channel with a WhatsApp number.
* **Timeline note on every rename:** on by default. Each time WASync renames a chat, the conversation's CRM record gets the note “WASync set the chat title: «…»” in the portal's language, so a rename is never silent. Nothing is written when a chat is left as it is. Notes follow the CRM timeline switch above: with timeline logging off, none are written.
* **When it is set:** when an operator first answers in the chat, and again when the conversation is linked to another CRM record or the template changes. To set it at a given stage, add the **Set WhatsApp chat title** step to a Bitrix24 automation rule on leads, deals, contacts or companies; on a company it renames the chats of the company's contacts (up to 50 contacts). Its own title box can hold Bitrix24 fields or these tokens, and empty uses the template. After an update, use [Reinstall placements](#reinstall-placements) if the step is missing from company automation.
* **Who renames it:** Bitrix24 lets only a chat's members rename it, so WASync renames it as the operator who answered. If no member has opened WASync yet, the title is set at a later answer.
* **Manual renames are kept:** once someone renames a chat by hand, WASync leaves it alone. With **Re-apply after a manual rename** on, WASync writes its title again when the CRM values behind it change.
### Default country [#default-country]
The country used to complete phone numbers stored in national format (a leading 0, no country code) when sending from a CRM record. When it is not set, the country of the sending number is tried.
### Reconnect alerts [#reconnect-alerts]
Who is emailed when a number disconnects and when it is back, and the Bitrix24 notification that goes with it. The alert names the probable cause. [Connections](/docs/product/connections).
### Read status in WASync Chat [#read-status]
Whether opening a conversation in WASync Chat marks the customer's messages as read on WhatsApp (blue ticks) for everyone, or whether each operator decides.
### AI provider (for Automations) [#ai-provider]
The model and key used by [Automations](/docs/product/automations) when an automation has no model of its own.
### Reinstall placements [#reinstall-placements]
Re-registers the WASync tabs and robots in Bitrix24 after an update or when a tab is missing. Reload the Bitrix24 page afterwards; Bitrix24 reads the definitions at page load.
# WASync Chat (/docs/product/wasync-chat)
WASync Chat is the shared WhatsApp inbox inside Bitrix24. Open the WASync app
and choose **WASync Chat** in the left menu. Every conversation of every number
connected to your portal is in one list, with the whole history of each customer.
People see it when they have Staff access to at least one number. The same
conversations also reach the Open Channel, so operators who prefer the Bitrix24
chat window keep working there. Both sides write to the same conversation.
## Who sees which conversations [#who-sees-which-conversations]
Each employee has a visibility level, set by an administrator. The default for
the portal is **all chats**, and you can override it per person on the Staff page.
| Level | What the employee sees |
| -------------- | ----------------------------------------------------------------------------------------- |
| **All** | All chats of the numbers they may use. |
| **Department** | The records of everyone who shares a Bitrix24 department with them. A team leader's view. |
| **Only mine** | Only the leads, deals and contacts they are responsible for. |
Bitrix24 administrators always see everything. The rule is enforced on the
server, not only hidden in the interface: the list, search, the conversation
itself, every action on it and every send are checked.
If Bitrix24 cannot say who owns a record, a scoped employee sees nothing rather
than everything.
The **All employees** filter above the list offers only the colleagues whose
conversations you are allowed to see. A person set to **Only mine** does not get
the filter. A person set to **Department** sees only colleagues from their
department. There is nothing to configure: it follows the level above.
With **Each number creates its own lead** on, a customer who writes to two of
your numbers has a lead or deal on each, and by default an employee sees the
conversation when either of them is theirs. Switch on **My conversations: only
through the number they are on** in the Chat rules to count only the record of
the number the conversation is on (the number of its latest message): a
colleague's lead on another number no longer opens it, the **From** picker
offers only numbers whose record is yours (or that have none yet), and a send
from a colleague's number is refused. With the switch off, the conversation
header says when you see a conversation only because of your record on another
number. Only a Bitrix24 administrator can change it.
### After a record is closed [#after-a-record-is-closed]
The **Closed leads and deals** card in the Chat rules removes a conversation
from its former responsible employee a number of days after the lead or deal
closes. `0` means it disappears immediately. The chat comes back for whoever
receives the customer's next lead or deal. Administrators and people who see
all chats are not affected.
## Changing the CRM stage from the chat [#changing-the-crm-stage-from-the-chat]
The header of a conversation shows the stage of the linked lead or deal. Who may
change it is a Chat rules setting, **Stage picker in WASync Chat**. Only a
Bitrix24 administrator can edit it.
| Option | What operators see |
| ----------------------------------- | -------------------------------------------------------------------------------------------- |
| **All operators** (default) | The stage dropdown, and they can move the record. |
| **Admins only** | Administrators keep the dropdown. Everyone else sees the current stage as a read-only label. |
| **Hidden (read-only for everyone)** | Nobody changes the stage from WASync Chat. The stage stays visible. |
The setting is enforced on the server, and Bitrix24 CRM permissions still apply
on top: an operator who cannot edit a record in Bitrix24 cannot move its stage
here either.
### Required fields before a stage change [#required-fields-before-a-stage-change]
Bitrix24 applies "required on this stage" fields only in its own form, not when
a stage is changed through the API. WASync adds its own rule. In the Chat rules,
**Before moving to a stage, ask for these fields** lets an administrator pick,
for leads and for every deal pipeline, the fields that must be filled for each
stage.
When an operator changes the stage, a panel asks for those fields, pre-filled
from the record. The stage changes only once they are filled, in a single CRM
update. **Cancel** leaves the stage as it was. Chat Flows are not affected, and
the CRM widget has no stage picker.
### Sequential stages [#sequential-stages]
To guide operators through the pipeline one stage at a time, turn on
**Sequential stages** in the Chat rules. It is off by default, and only a
Bitrix24 administrator can change it.
With it on, the stage dropdown still lists the whole pipeline of the record,
but only the next stage can be picked; the stages further on are greyed out
with the hint "Go through *next stage* first". The order is the order of the
pipeline in Bitrix24, for leads and for every deal pipeline.
| Option | Default | What it allows |
| ------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Also allow one step back** | On | The previous stage can be picked too. |
| **Allow "Lost" from any stage** | On | The lost stages (and "Junk" for leads) can be picked from any stage, so a lost lead or deal is closed without filling in the stages in between. Off: only from the last stage before them. |
| **Allow "Won" from any stage** | Off | The won stage can be picked from any stage. Off: only from the last stage before it, so a record goes through the whole pipeline before it is won. |
A record in a won or lost stage can only be reopened to the first stage. A
jump the rule does not allow is refused on the server too, with the message
"Move to *next stage* first", and the required fields of the stage still have
to be filled in.
The rule applies only to stage changes made from WASync Chat. Bitrix24 has no
such setting and does not let an app restrict its own Kanban, the record card
or automation rules, so a record moved there can still skip stages.
## Create or link a lead from a conversation [#create-or-link-a-lead-from-a-conversation]
**Create lead** does not create anything at first. It shows **Already in the
CRM**: the leads found by phone number and by the linked contact (closed ones
are tagged **Closed**), plus the contact's open deals. Each has a **Link**
button. **Create new lead** sits below the list.
On a conversation linked only to a contact, the button reads **Create or link
lead**, and **Link to record** is available too. Operators see only the records
their Bitrix24 role allows. Nothing is created or linked automatically by
opening the list.
To move a conversation that is already linked, use **Change record** next to the
responsible person. It opens the same search as **Link to record**. Pick a lead,
a deal or a contact and confirm.
* Only WASync's link changes. The old record keeps its history, and nothing in
Bitrix24 is edited.
* New messages are logged on the new record.
* With **Each number creates its own lead** on, the link of that number is
replaced, and the target must be a lead or a deal.
For when WASync creates leads on its own, see
[Leads from WhatsApp chats](/docs/guides/leads-from-whatsapp-chats).
## Quick replies with "/" [#quick-replies-with-]
Quick replies are saved answers with a short command name, either for the whole
team (**Team**) or personal (**Mine**). They work in WASync Chat and in the
WhatsApp tab of the CRM.
Type `/` at the start of the message box or after a space. A picker opens with
every reply already filled in for the open customer. Keep typing to filter
(`/cuo`), choose with the arrow keys and press Enter or Tab to insert. A reply
is never sent by itself, so you can edit it first. Esc closes the picker. The
lightning button next to the box does the same for mouse and phone users.
Hi, how much is the premium plan?
Good afternoon, Maria!
/price
Variables are filled in on the server when the reply is inserted:
| Variable | Filled with |
| ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `{{greeting}}` | Good morning, Good afternoon or Good evening, in the customer's language and at the customer's local time. Both come from the country of the phone number (UTC when the country is unknown). |
| `{{contact.first_name}}`, `{{contact.name}}` | The customer. |
| `{{me.first_name}}`, `{{me.name}}` | The person sending. |
| `{{record.title}}`, `{{record.stage}}`, `{{record.responsible}}` | The lead or deal linked to the conversation. |
| `{{crm.FIELD}}` | Any CRM field of that lead or deal, for example `{{crm.OPPORTUNITY}}`. |
A reply can carry versions in other languages. The picker chooses the version
that matches the country of the customer's phone number.
Manage replies on the **Quick replies** page (the lightning icon in the app
menu), open to administrators and anyone with write access to Settings. It lists
Team and Mine replies with add, edit and delete, language versions, how often
and when each was used, and promote to team for a personal reply.
* **Save as quick reply** (menu on any message you sent) turns it into a reply,
with the customer's name, the greeting and the record title replaced by
variables.
* After you insert a reply, change it and send it, WASync asks whether to update
the saved reply with your version.
Quick replies are not the canned responses of Bitrix24 Open Channels. Those live
in the Contact Center and do not fill in CRM data.
## Templates on Business API numbers [#templates-on-business-api-numbers]
On a WhatsApp Business API number, a conversation outside the 24-hour window
accepts only approved templates. The composer marks such a number as **templates
only (outside 24 h)** and the template picker takes over.
The window opens only when the customer writes to you. A contact who has never
written, or whose last message is older than 24 hours, gets a locked composer
with the explanation and a **Pick a template** button, in WASync Chat and in
the WhatsApp tab of a CRM record. A missed or placed call does not open the
window. If a free-text send is still refused by WhatsApp's rule, the message is
not sent and the composer shows why: *Your message was not sent: this contact is
outside the 24-hour window. Send a template first.* The lock lifts the moment
the customer replies.
Templates with an image, video or document header keep the file uploaded when
they were created. Every send from WASync Chat uses it by default: the operator
sees **Template image** preselected with a preview and can still change it
before sending. For templates approved earlier, or created in Meta's own
interface, **Set default image** in the template list sets the file once.
The picker fills `{{1}}` with the contact's first name only when it is a real name and the template describes `{{1}}` as a name (or does not describe it at all). A contact with no name, or a `{{1}}` labelled as something else, such as a date, is left empty for the operator to type.
How to create and approve templates: [WhatsApp Business API templates](/docs/guides/waba-templates).
## Long messages [#long-messages]
On the WhatsApp Business API, a text over 4,096 characters is sent as several
messages, in order, with the delivery ticks on each. In Bitrix24 the operator
still sees the single original message. The limit is 10 messages (about 40,000
characters). Beyond that the operator is told the message is too long and
nothing is sent.
Templates and file captions keep their own limits and are not split.
## Opening and downloading files [#opening-and-downloading-files]
Photos, videos and files in a conversation open with a link made at the moment
you click, so they work even when the chat has been open for hours. This is the
same in WASync Chat and in the WASync tab of a CRM record.
* **Photos, PDFs and videos** open inside the app, over the conversation. Use
**Open** for a new browser tab, **Download** to save the file, and **Esc** or a
click outside the file to close it. A PDF is shown in the page itself; if it is
larger than 25 MB, or your browser cannot show PDFs inside a page (most phones),
the window offers **Open** and **Download** instead.
* **Other documents** (Word, Excel, zip and so on) open in a new browser tab.
* **Download** under a photo, video or file saves it with its original name.
Files open inside the app because some browsers add a small extra code to any
address opened in a new tab, which makes the storage service refuse the link.
If nothing opens, check that your browser allows pop-ups for Bitrix24.
## Sending from the right number [#sending-from-the-right-number]
When a customer has written to two or more of your numbers, WASync Chat keeps
one conversation with the whole history of that person. A small **via +number**
badge marks messages that came through a number other than the one selected for
replying.
The composer always shows the number a reply will go out from. With two or more
numbers it becomes a picker (**Send from number**). It defaults to the number
the customer wrote to last. A Business API number outside the 24-hour window is
marked **templates only**.
Every send path follows the number you chose: text, files, templates, voice
notes, notes, takeover, and the stage or responsible changes written to the CRM.
## Starting a conversation with a number that has no chat yet [#starting-a-conversation-with-a-new-number]
WASync Chat lists conversations, so a number that has never exchanged a
message with any of your WhatsApp numbers is not in the list. To write to it
first, type the full number in the search box, with the country code. When no
conversation matches, the list offers **Start a conversation with +number**.
Choose which of your numbers sends, and the thread opens empty with that
number selected in **Send from**.
* On a Business API number the first message to a new number is a template:
the composer shows the template picker, as it does outside the 24-hour
window.
* Once the first message is sent, the conversation appears in the list like
any other.
* An employee limited to their own records can start a conversation only with
a number that is on a lead, deal or contact assigned to them. WASync looks
the number up in the CRM and links the conversation to that record. If the
number is on nobody's record, create the lead or contact in Bitrix24 first
and open WhatsApp from the record.
This is also the way to reach the second phone of a customer whose record has
several numbers; from the record itself, use the number picker in the WASync
tab ([Records with several phone numbers](/docs/product/crm-records#records-with-several-phone-numbers)).
## When a contact changes their number [#when-a-contact-changes-their-number]
On a Business API number, WhatsApp tells us when a contact moves to a new
WhatsApp number. WASync then:
* adds a note to the conversation, "This contact changed their WhatsApp number
to +number", in your portal's language. The same note appears in the
Bitrix24 Open Channel chat;
* adds the new number to the phone field of the conversation's lead, contact or
company (for a deal or a smart process item, to its contact). The old number
stays on the record. A comment on the CRM timeline says which number changed
to which;
* shows a banner over the old conversation, **This contact now uses +number**,
with **Open conversation**. The new number's conversation is linked to the
same CRM record. Replies can't be sent from the old conversation any more,
but you can still write internal notes there.
If you prefer to update phone numbers yourself, turn off **When a contact
changes their WhatsApp number** in the Chat rules. The note and the banner
still appear. A chat flow that was running on the old number keeps running
there and does not move to the new one.
QR connections don't receive this notice from WhatsApp, so nothing changes on
them.
## Contacts without a phone number (usernames) [#contacts-without-a-phone-number]
WhatsApp is introducing usernames, country by country. A customer who has a
username can keep their phone number hidden from businesses. When such a
customer writes to one of your **WhatsApp Business API** numbers, WhatsApp
sends their username but no phone number. WASync then:
* shows the conversation in WASync Chat as usual, with **@username** where the
phone number would be (or **No phone number** when they have no username;
hover over it for a short explanation). You can search for the conversation
by the username, with or without the "@";
* forwards the messages to the Bitrix24 Open Channel. The chat is named after
the username, and the lead Bitrix24 creates from it has no phone number;
* lets you reply as usual, from WASync Chat and from the Open Channel. The
reply goes to the customer's WhatsApp account directly, without a phone
number. Templates work too, except authentication (one-time code) templates,
which WhatsApp only delivers to a phone number;
* when **Unknown chats** creates leads, creates the lead titled with the
username and without a phone number.
Some things need a phone number and are not available for these
conversations: QR connections can't reach them (only Business API numbers are
offered in **Send from**), WhatsApp calls, scheduled messages, and starting a
new conversation by typing a number. A chat flow still runs and answers, but
it does not create or link a CRM record for a contact without a phone number,
and **Each number creates its own lead** skips them.
### When the customer later shares their number [#when-the-customer-later-shares-their-number]
If the same customer later writes from their phone number (or turns off the
hidden number), WhatsApp tells us both identities belong to one person. WASync
keeps the two conversations apart and adds a note to each one, for example
"This contact also writes as +57 300 111 2233" in the username conversation
and "This contact also writes as @username" in the phone one. The note also
appears in the Open Channel chats. Nothing is merged automatically; if they
are the same person for you, ask our support to merge the two conversations.
## Disappearing messages [#disappearing-messages]
When a contact has turned on disappearing messages in WhatsApp, the
conversation header shows a small amber label next to their name, for example
**Disappearing: 24 h**, **Disappearing: 7 days** or **Disappearing: 90 days**.
It appears in WASync Chat and in the WASync tab of a CRM record. Hover over it
for a short explanation.
* On the customer's phone, messages are deleted after that time, so a quote or
an offer you send may disappear before they read it. Consider asking them to
confirm they received it, or send the important part again closer to when
they need it.
* Nothing is deleted on your side: the full history stays in WASync and in
Bitrix24.
* The label is updated from the customer's own messages. It appears after their
next message once they turn the setting on, and goes away after their next
message once they turn it off.
This works on QR connections only. WhatsApp does not share the setting with
WhatsApp Business API numbers, so no label appears on them.
## Sending a message later [#sending-a-message-later]
Write the message, then click the clock next to **Send** (in WASync Chat and in
the WASync tab of a CRM record). Pick **In 1 hour**, **Tomorrow, 09:00**,
**Monday, 09:00** or any date and time up to 30 days ahead, and click
**Schedule**. The message waits above the text box until it goes out; the ×
cancels it until then. WASync sends it at that time even if nobody has the chat
open, from the number you chose, and the CRM timeline credits you as the author.
* Text messages only: a message with files cannot be scheduled.
* On WhatsApp Business API numbers, WhatsApp only accepts a free-form text if the
customer wrote to you in the 24 hours before. If they did not, the scheduled
message is not sent; use a template instead.
* Each person sees and cancels their own scheduled messages; an administrator
can cancel anyone's.
## Voice-note transcription [#voice-note-transcription]
WASync can write out WhatsApp voice notes, so operators read them instead of
listening. An administrator turns it on in **Settings → Voice-note
transcription**. From then on, every voice note a customer sends, and every
voice note your team sends, gets its text under the player in WASync Chat and in
the WASync tab of a CRM record; while it is being processed the bubble shows
"Transcribing…". The text is also in the chat export.
* It runs on **your own account** with the service you choose on the card:
**OpenAI** (Whisper), **Groq** (Whisper large-v3, fast and inexpensive) or
**ElevenLabs** (Scribe, very accurate on noisy audio). For OpenAI, the key
from your AI settings is used when your AI provider is OpenAI; otherwise, and
for Groq and ElevenLabs, enter that service's API key on the card. The audio
is sent to the service under your key and your contract with them, and the
service bills the transcription to your account.
* Voice notes over 10 minutes or 25 MB are not transcribed.
* Voice notes sent by automations, chat flows and robots are not transcribed.
* Voice notes received before the setting was turned on stay as they are.
## Carousel templates [#carousel-templates]
A carousel template is a message followed by 2 to 10 cards the customer swipes
sideways. Create one in **Templates → New template → Carousel**:
* the main text above the cards (variables allowed, as in any template);
* the media of the cards: all images or all videos;
* each card: its file, an optional short text (up to 160 characters; give every
card a text, or none) and 1 or 2 buttons. The buttons are the same kind and in
the same order on every card: quick reply, link or phone number.
WhatsApp accepts carousels only as **Marketing** templates. WASync keeps each
card's file with the template and sends it every time, because WhatsApp asks for
the media again at each send. Send a carousel like any other template: from
WASync Chat, the WASync tab of a CRM record, a chat flow or a robot. In the
conversation it shows as a strip of cards with their text and buttons.
A carousel created in Meta's own tool can be sent only if its card files are
public links; create it in WASync to be sure each card has its file.
## Link click tracking [#link-click-tracking]
An administrator can turn on **Settings → Link click tracking**. From then on,
links in text messages sent from WASync (WASync Chat, the WASync tab of a CRM
record, chat flows and scheduled messages) are sent as a short link on our
domain that opens the original page.
* Under the message you see **Opened N× · last 14:05**, or **Not opened yet**.
* The first time the customer opens a link, a comment appears on the record's
CRM timeline: "Customer opened the link: …".
* The preview WhatsApp builds when the message is sent does not count as an
open; neither do other link-preview robots.
* The customer sees our short domain instead of yours. Templates, files and
replies typed in the Bitrix24 Open Channel are not changed.
* We store when a link was opened and the kind of device, not the IP address.
# Create an account and a key (/docs/quickstart/create-account-and-key)
There are two equally valid ways to get an API key, depending on how you use
WASync.
Open the app in Bitrix24, go to **Settings → API & Agents**, and find the
**API keys** card. Name the integration and click **Create key**.
Creating a key needs at least one connection with the **API add-on** active
($12 per number per month) — without one, the button is disabled with the
reason, and the server answers `403 addon_required`. The key is shown once,
right there, with a **Copy** button, and carries the standard scopes
`whatsapp.read whatsapp.send`.
IP allowlists, webhook configuration, and managing several portals from one
account live in the developer console, not in this card — the card links to it.
Go to [https://developers.wasync.app/keys](https://developers.wasync.app/keys), create an account with an email and
a password, and create a key. Give it a name, tick the scopes you need, and
optionally restrict it to a set of IP addresses.
The key is shown **once** — only a hash of it is stored. Copy it into your
environment straight away.
```bash title="env"
export WASYNC_API_KEY=wsk_live_…
```
Send it on every request:
```http
Authorization: Bearer $WASYNC_API_KEY
```
That is the whole auth setup. No redirect URI, no PKCE, no consent screen, no
token refresh.
## Scopes [#scopes]
Tick only what the integration needs — scopes are per key.
| Scope | What it allows |
| ----------------- | --------------------------------------------------------- |
| `whatsapp.read` | List connections and read messages. |
| `whatsapp.send` | Send messages and read receipts. |
| `whatsapp.events` | Receive webhooks, and configure where they go. |
| `whatsapp.manage` | Create, inspect, restart, log out and delete connections. |
Scopes and the reachable connection list are resolved live on every request, so
revoking a key or narrowing it takes effect on the very next call — there is
nothing cached and nothing to refresh. The details, and what each scope costs
you if it leaks, are under [Scopes](/docs/concepts/scopes).
The optional IP allowlist is enforced on API calls only. The page where you edit
it is authenticated by your account, not by the key, so it stays reachable from
any address. See [IP allowlist](/docs/security/ip-allowlist).
## What a connection costs [#what-a-connection-costs]
Each WhatsApp number needs an active licence to send and receive. A new number
starts on a **7-day free trial**, then $19 per number per month for a `qr`
(WAPP) number or $29 per number per month for a `cloud_api` (WABA) number, in
USD. On a Bitrix24 portal, API access to a number is a separate **$12 per number
per month** add-on. [Licences & trial](/docs/concepts/licences-and-trial) has
the full picture.
# Your first call (/docs/quickstart/first-call)
Base URL `https://developers.wasync.app/api/v1`.
## List the connections you may use [#list-the-connections-you-may-use]
```bash title="GET /connections"
curl https://developers.wasync.app/api/v1/connections \
-H "Authorization: Bearer $WASYNC_API_KEY"
```
Only connections with an active licence appear. Each carries a `provider` of
`qr` or `cloud_api`, an `id` (a cuid — the stable identifier you should store
against your own customer record) and a `status`. Uses `whatsapp.read`.
`developers.wasync.app` is the canonical host, but `cloudapi.wasync.app` is a
permanent alias for exactly the same API — same keys, same paths, same
responses — and it remains valid indefinitely. No existing integration has to
change anything. The OAuth endpoints, the `/.well-known/…` documents and the MCP
server URL are protocol identifiers registered by clients: they stay on
`cloudapi.wasync.app` on purpose.
## Check your capacity before you promise it [#check-your-capacity-before-you-promise-it]
```bash title="GET /account"
curl https://developers.wasync.app/api/v1/account \
-H "Authorization: Bearer $WASYNC_API_KEY"
```
```json title="200 response"
{
"slots": {
"total": 30,
"used": 28,
"available": 2,
"nextExpiry": "2027-08-08T09:00:00.000Z"
},
"connections": {
"total": 28,
"connected": 27,
"needsReconnect": 1
}
}
```
`slots.available` tells you whether you can onboard another number right now,
and `nextExpiry` is the date you need to invoice your own customer before — so a
slot never expires underneath someone who has already paid you.
`connections.needsReconnect` counts the numbers currently waiting for their owner
to scan a QR; subscribe to [connection events](/docs/guides/webhooks) to be told
the moment that number changes instead of polling for it. Uses `whatsapp.read`.
A slot is capacity, not a phone number. Delete a connection and its slot returns
to your pool carrying whatever time is left on it — the next number you connect
picks it up automatically. That is what lets you move a paid slot from a
departing customer to a new one without paying twice.
## Connect a number [#connect-a-number]
One call creates the connection and returns a QR code to scan. It works on a
brand-new workspace with no connections at all — with a key there is nothing to
click in a portal first.
```bash title="POST /connections"
curl -X POST https://developers.wasync.app/api/v1/connections \
-H "Authorization: Bearer $WASYNC_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"label":"Support line"}'
```
```json title="201 response"
{
"connection": {
"id": "conn_8f3a21",
"status": "connecting",
"qr": "data:image/png;base64,iVBORw0KGgo…"
}
}
```
WhatsApp rotates the pairing code roughly every **20 seconds**, so the `qr` in
the create response is stale within seconds of being displayed. This fails
silently: the phone never pairs and nothing on screen explains why. Poll
`GET /connections/{id}` every 3–5 s and re-render the `qr` from every response.
Do not cache it, and do not hide the refresh behind a button the user has to
press. [Pairing code & QR](/docs/guides/pairing-and-qr) covers the one-device
alternative.
Uses `whatsapp.manage`. Connections created this way are `qr` numbers;
`cloud_api` numbers are onboarded through Meta embedded signup instead. This
endpoint is standalone-workspace only — a Bitrix24 portal is answered with
`403 forbidden_portal_kind`, because there connections are created by the portal
admin inside WASync. Send an `Idempotency-Key` — creating a connection consumes
a paid slot, and a timed-out retry without one buys you two.
[Errors & idempotency](/docs/concepts/errors-and-idempotency) has the four cases
you must handle.
# Your first message (/docs/quickstart/first-message)
## Send a text [#send-a-text]
```bash title="POST /messages"
curl -X POST https://developers.wasync.app/api/v1/messages \
-H "Authorization: Bearer $WASYNC_API_KEY" \
-H "Content-Type: application/json" \
-d '{"connectionId":"conn_8f3a21","to":"40700000000","text":"Hi from my app 👋"}'
```
```json title="200 response"
{
"messageId": "cmqj3k2ab0001xyz",
"waMessageId": "true_40700000000@c.us_3EB0A1B2C3",
"status": "sent"
}
```
`to` is international digits only, no `+` — e.g. `40700000000`. `text` is at
most 4096 characters. For media, supply `media` instead of `text`:
`{ filename, mimetype, data (base64, ≤ 16 MB), caption? }` — exactly one of the
two. Voice notes use `mimetype: audio/ogg` and a `voice-*.ogg` filename. Uses
`whatsapp.send`.
A `qr` send normally takes 1–7 s, up to about 20 s for long texts, and the
self-heal path can take \~2.5 minutes. A `cloud_api` send is about 1 s. **A slow
send is not a failure** — a client that gives up at 30 s and retries sends the
customer the message twice. Always pass an `idempotencyKey` (a UUID per logical
send) and retry with the *same* one.
## Two ids — join on the right one [#two-ids--join-on-the-right-one]
The response carries two identifiers and they are not interchangeable.
| Id | Where it appears | Use it for |
| -------------------- | ---------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| `messageId` (a cuid) | `messageId` on POST, `id` on GET, `message.id` in both webhooks | The **only** joinable id. Store it on send, dedupe on it, match `message.status` events against it. |
| `waMessageId` | `waMessageId` (REST), `wa_id` (webhooks), `wa_message_id` (media send) | Support tickets and debugging. It can be `null` — never join or dedupe on it. |
One degraded case is worth coding for: `{ "messageId": null, "waMessageId": "…",
"status": …, "persisted": false }` with HTTP 200 means the message **was
delivered** but was not persisted. Do not retry it.
## Read the thread back [#read-the-thread-back]
```bash title="GET /messages"
curl "https://developers.wasync.app/api/v1/messages?connectionId=conn_8f3a21&limit=20" \
-H "Authorization: Bearer $WASYNC_API_KEY"
```
```json title="200 response"
{
"messages": [
{
"id": "cmqj3k2ab0001xyz",
"waMessageId": "true_40700000000@c.us_3EB0A1B2C3",
"connectionId": "conn_8f3a21",
"direction": "outgoing",
"text": "Hi from my app 👋",
"mediaUrl": null,
"mediaType": null,
"status": "delivered",
"errorMessage": null,
"createdAt": "2026-07-22T10:00:00.000Z"
}
],
"nextCursor": "cmqj3k2ab0001xyz",
"hasMore": true
}
```
Newest first, cursor-paginated: `limit` is 1–100 (default 20), and `cursor`
takes the previous response's `nextCursor`. Uses `whatsapp.read`.
## Give the customer blue ticks [#give-the-customer-blue-ticks]
```bash title="POST /messages/read"
curl -X POST https://developers.wasync.app/api/v1/messages/read \
-H "Authorization: Bearer $WASYNC_API_KEY" \
-H "Content-Type: application/json" \
-d '{"connectionId":"conn_8f3a21","phone":"40700000000"}'
```
Call this when an operator opens the conversation in *your* UI — otherwise
nobody ever opens the chat in WhatsApp, the customer's messages stay on double
grey ticks and the thread looks ignored. Body is
`{ connectionId, phone?, messageId? }` with at least one of `phone` /
`messageId` (the cuid of an *incoming* message; `messageId` wins when both are
given). It uses `whatsapp.send`, not `whatsapp.read`, because it transmits a
receipt to the customer. Idempotent, no key, no rate limit. Returns
`{ "ok": true, "marked": 3 }`.
## Next [#next]
* Be told about inbound messages instead of polling: [Webhooks](/docs/guides/webhooks).
* Build it without code: [n8n](/docs/guides/n8n) or [MCP](/docs/guides/mcp).
* Generate a client from the contract:
`npx @openapitools/openapi-generator-cli generate -i https://developers.wasync.app/openapi.json -g typescript-fetch -o ./wasync-client`
# Quickstart (/docs/quickstart)
From nothing to a delivered WhatsApp message in under five minutes.
# API keys (/docs/security/api-keys)
## Shown once [#shown-once]
A key is displayed **exactly once**, at the moment you create it. Only a hash of
it is stored, so nobody — including us — can read it back to you afterwards. The
page will not show it again and support cannot recover it.
The practical consequence: copy it into your secret store *before* leaving the
page. If you lose it, you do not recover it — you revoke it and create another.
That is a two-minute operation, and it is the only safe design: a key a support
process can retrieve is a key a support process can leak.
## Where a key is created [#where-a-key-is-created]
There are two places, and they are not the same tool:
* **The API keys card in Bitrix24** (Settings → API & Agents) — an admin names
the integration and creates or revokes keys. It needs at least one
connection with the API add-on active. Keys made here carry the standard
scopes `whatsapp.read whatsapp.send`.
* **The developer console** at
[developers.wasync.app/keys](https://developers.wasync.app/keys) — the same
create/revoke, plus the things the Bitrix24 card does not do: an IP
allowlist per key, a choice of scopes beyond the standard pair, and several
portals or numbers under one account.
Revoking a key takes effect immediately no matter which place you revoke it
from — there is nothing cached on either side.
## Where a key must never go [#where-a-key-must-never-go]
* Not in a query string. URLs end up in access logs, proxies, browser history
and referrer headers.
* Not in client-side code. Anything shipped to a browser or a mobile app is
readable by whoever runs it.
* Not in source control, not in a screenshot, not in a ticket.
Put it in an environment variable or a secret manager, and send it only as
`Authorization: Bearer …`.
## Scope it down [#scope-it-down]
Each key carries its own [scopes](/docs/concepts/scopes). A key that only needs
to send should not be able to delete connections. Scopes are resolved live on
every request, so tightening an existing key takes effect on the next call — you
do not have to reissue it to narrow it.
## Two keys are cheaper than one incident [#two-keys-are-cheaper-than-one-incident]
There is no limit that forces you to share one key across everything. A separate
key per deployment (staging vs production) and per job (a read-only reporting
task vs a sender) means a leak is contained to one blast radius and can be
revoked without taking the rest down.
## Prefix [#prefix]
Keys are prefixed `wsk_live_`. Secret scanners can be taught the prefix, and a
value in a log that starts with it should be treated as compromised and revoked
immediately.
# Developer console sign-in (/docs/security/developer-console)
The developer console at [developers.wasync.app](https://developers.wasync.app)
holds API keys that can read and send your customers' WhatsApp messages, so its
sign-in is held to a higher bar than a typical dashboard: a choice of sign-in
methods, a mandatory second step, and a re-confirmation before anything
sensitive happens.
## Three ways to sign in [#three-ways-to-sign-in]
* **Password** — your email and password. Passwords must be 12–128 characters;
we do not enforce upper/lower/symbol rules, and we never force a periodic
reset. Every password is checked against a breach database when you set it —
if it has appeared in a known breach, we refuse it and ask for a different
one.
* **Email code** — enter your email and we send a 6-digit code. It is valid
for 10 minutes, works once, and is invalidated after 5 wrong guesses.
* **Passkey** — a single "Continue with passkey" button. Passkeys use Face ID,
Touch ID, Windows Hello or a hardware key, never leave your device, and
cannot be phished or reused on another site.
## Two-step sign-in [#two-step-sign-in]
A password or an email code proves you know something; it does not prove the
device is yours. So on top of one of the three methods above, most accounts
also confirm a **second step**:
* **Passkey** — recommended. Because a passkey already required your device
and your face, fingerprint or PIN, signing in *with* a passkey satisfies
both the first and second step at once. Signing in with a password or an
email code still asks for the second step separately.
* **Authenticator app** — any standard TOTP app (Google Authenticator, 1Password,
Authy, etc.). Scan the QR code once to enrol; after that it asks for the
6-digit code it shows.
* **Recovery codes** — ten single-use codes, shown exactly once when you set up
two-step sign-in. Store them somewhere safe. Each one works instead of a
passkey or authenticator code, and using one does not disable the others.
## What's mandatory, and when [#whats-mandatory-and-when]
* **New accounts** must set up a second step right after creating the account.
You can put it off once; after that the console will ask again before
letting you continue.
* **Existing accounts** get a 14-day banner asking them to set it up voluntarily;
after those 14 days it becomes mandatory, the same as a new account.
* **Admin accounts** have no grace period — a second step is required from the
moment this changed.
## Devices and sessions [#devices-and-sessions]
Signing in creates a session tied to your browser, not a token you copy
around. By default a session is good for 12 hours of inactivity or 24 hours
total, whichever comes first. Checking **Keep me signed in for 30 days**
extends that to 30 days total, with a 7-day inactivity limit.
Under **Security → Devices** you can see every signed-in session — browser,
approximate location and last-seen time — and sign any of them out, including
the one you are currently using. When we notice a sign-in from a device we
have not seen before, we email you with the device, approximate location and
time, and a link to sign it out if it was not you.
## Activity log [#activity-log]
**Security → Activity** shows the last events on your account: sign-ins,
sign-outs, password and two-step changes, API key creation, and similar. We
keep this history for 12 months. It is there so that if something looks
wrong, you can see exactly what happened and when, without having to ask us.
## Confirming it's you again [#confirming-its-you-again]
A handful of actions are sensitive enough that the console asks you to
confirm your second step again, even if you are already signed in — this
matters if your second step was verified more than five minutes ago:
* Creating or revoking an API key
* Rotating a webhook secret
* Deleting a WhatsApp connection or closing a workspace
* Turning off a passkey or authenticator app, or regenerating your recovery
codes
* For account admins: extending a licence or changing a partner's status
When one of these is triggered, a "Confirm it's you" dialog appears asking
for your passkey, authenticator code or a recovery code. Once confirmed, the
action goes through and the confirmation is good for a few more minutes.
## Repeated failed attempts [#repeated-failed-attempts]
A few wrong passwords in a row bring up a Cloudflare Turnstile challenge on
the sign-in form — the same kind of check you see on many sites, not a code
sent anywhere. Ten wrong passwords within 15 minutes apply a 15-minute
temporary lock to the account, and we email the owner when that happens. The
lock only affects password sign-in — you can still sign in with a passkey or
an email code while it is active, so a lock can never be used to keep you out
of your own account.
## What we never do [#what-we-never-do]
* We never send a sign-in code or a password reset by SMS.
* We never put a one-time code or any secret in the subject line of an
email — it only ever appears in the body, so it cannot leak through a
notification preview or a mail client's list view.
## Recovering access [#recovering-access]
If you lose your passkey or authenticator device, use one of your ten
recovery codes to sign in and set up a new second-factor device from
**Security**. If you have also lost your recovery codes, there is no
self-service recovery for two-step sign-in by design — the whole point is
that it cannot be bypassed by anyone who only has your email. Contact us in
writing at [support@wasync.app](mailto:support@wasync.app) and we will verify
your identity before restoring access.
# Security (/docs/security)
How keys are stored, how to pin them to addresses, and how fast a revocation takes effect.
# IP allowlist (/docs/security/ip-allowlist)
A key can optionally be pinned to a set of IPv4/IPv6 addresses or CIDR ranges.
Edit the list at [https://developers.wasync.app/keys](https://developers.wasync.app/keys).
A call from an address that is not on the list is refused with:
```json title="403"
{ "error": "ip_not_allowed" }
```
## Why it is a different code from `invalid_key` [#why-it-is-a-different-code-from-invalid_key]
`403 ip_not_allowed` and `401 invalid_key` are deliberately distinct, because
the fix is opposite:
| Code | What is wrong | What to do |
| -------------------- | ------------------------------------------------------------ | ------------------------------------------------ |
| `401 invalid_key` | The key is unknown or revoked. | Create a new key. Retrying will never help. |
| `403 ip_not_allowed` | The key is **fine**; the calling address is not on its list. | Add the address. **Do not rotate the key.** |
Collapsing the two would send you rotating a perfectly good key while the real
problem — a new egress address after a deploy, a container that moved hosts —
stays unfixed. Branch on the code, never on the status alone.
## You cannot lock yourself out [#you-cannot-lock-yourself-out]
The allowlist is enforced on API calls. The page where you edit it is
authenticated by your **account**, not by the key, so it stays reachable from
any address. There is no state in which a key's own allowlist prevents you from
fixing that allowlist.
## When it is worth it [#when-it-is-worth-it]
An allowlist is most useful when your callers have stable egress: a fixed NAT
gateway, a VPC egress IP, an on-premise server. It turns a leaked key into a
key that only works from your infrastructure.
It is worth less when your callers are elastic — serverless platforms and CI
runners rotate addresses, and a list you have to keep chasing will eventually be
widened to something meaningless. In that case, prefer narrow
[scopes](/docs/concepts/scopes) and short-lived deployments of the key.
# Revocation timing (/docs/security/revocation)
Scopes and the reachable connection list are resolved **live, on every
request**. Nothing about a credential is cached in the credential itself and
nothing has to be refreshed.
## What that buys you [#what-that-buys-you]
**Revocation is immediate.** Delete a key and the next call using it gets
`401 invalid_key`. There is no propagation window, no token that stays valid
until it expires, and no cache to wait out. If a key is in a log you can pasted
into a ticket, revoking it now is genuinely now.
**Narrowing is immediate too.** Remove a scope from an existing key and the next
call that needed it gets `403 insufficient_scope`. You do not have to reissue the
key to tighten it.
**A new connection is visible immediately.** A connection you just created shows
up on the very next `GET /connections`. There is nothing to refresh after a
provisioning step.
## OAuth tokens [#oauth-tokens]
An OAuth `access_token` is the one thing with a lifetime of its own: 15 minutes.
Its **scopes and connection list are still resolved live**, so revoking the
grant stops it reaching anything immediately — but the token string itself
remains syntactically valid until it expires.
`refresh_token` lives 30 days and **rotates on use**. Persist the new one
atomically and serialise refreshes across workers: two workers refreshing at once
will invalidate each other, and the symptom is an integration that logs out at
random under load.
## Webhook secrets [#webhook-secrets]
Rotation has **no overlap window**. `POST /webhook/rotate` issues a new secret
and the old one stops verifying immediately. Deploy the new secret promptly —
the delivery retry policy (3 attempts: immediate, 500 ms, 1 s) covers a rollout
measured in seconds, not hours, and anything dropped in between has to be picked
up by your [reconciliation poll](/docs/guides/webhooks).
## If you think a credential leaked [#if-you-think-a-credential-leaked]
Revoke it at
[https://developers.wasync.app/keys](https://developers.wasync.app/keys)
. It stops working on the next call.
Create a replacement with the narrowest scopes that still work.
Rotate the webhook secret if the leak could have exposed it —
`GET /webhook`
never returns it, so a leak means it came from your side.
Read back
`GET /messages`
over the affected window to see what was sent while the credential was out.
Support is written-only: email or chat.
# Slot quota and connection health (/docs/api-reference/account/getAccount)
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
# Create a new connection (/docs/api-reference/connections/createConnection)
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
# Delete a connection (/docs/api-reference/connections/deleteConnection)
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
# Get connection status (/docs/api-reference/connections/getConnection)
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
# List authorized connections (/docs/api-reference/connections/listConnections)
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
# Log out a connection (/docs/api-reference/connections/logoutConnection)
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
# Request a pairing code (link with phone number) (/docs/api-reference/connections/requestPairingCode)
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
# Restart a connection session (/docs/api-reference/connections/restartConnection)
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
# List recent messages (/docs/api-reference/messages/listMessages)
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
# Mark inbound messages as read (blue ticks) (/docs/api-reference/messages/markMessagesRead)
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
# Send a WhatsApp message (text or media) (/docs/api-reference/messages/sendMessage)
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
# Read the webhook configuration (/docs/api-reference/webhook/getWebhook)
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
# Rotate the webhook signing secret (/docs/api-reference/webhook/rotateWebhookSecret)
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
# Set the webhook endpoint (/docs/api-reference/webhook/setWebhook)
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
# How do I answer a WhatsApp call in Bitrix24 without hunting for the notification? (/docs/help-center/calls/answer-whatsapp-call-in-bitrix24)
An incoming WhatsApp call rings in the Bitrix24 call card, the same card used for telephony, with **Answer**, **Ignore**, **Mute** and **End**; the voice runs in the browser, and the right panel shows the WASync tab with the customer's conversation. After the call its duration is logged on the record.
Calls need a WhatsApp Business API number on the Cloud API (not a number in coexistence with the phone app), a verified business, an approved display name and calling enabled on the number, which you do from **Connections → the number's menu → Calling**. Availability by country is decided by Meta and checked by the app before it lets you enable it. Use Chrome, Edge or Bitrix24 Desktop.
## Related [#related]
* [Calls](/docs/product/calls)
# The call duration in the CRM is wrong; it includes the ringing time. (/docs/help-center/calls/call-duration-includes-ringing)
The logged duration is the talk time only: the timer starts when the call is answered (confirmed by Meta or by the first audio packet), not when it starts ringing. A call that nobody answered is logged as missed with a duration of zero, so the reports count real conversations.
## Related [#related]
* [Calls](/docs/product/calls)
# If the responsible person does not answer, do colleagues ring too? (/docs/help-center/calls/colleagues-ring-if-responsible-does-not-answer)
Yes. The call first rings the responsible person for about eight seconds; if they do not answer, or they are offline, it rings everyone who is online and has access to that number in **Team**. The first person to answer takes the call. If the responsible is not even logged in, the second step starts right away.
## Related [#related]
* [Calls](/docs/product/calls)
# WhatsApp calls (/docs/help-center/calls)
Answering in the Bitrix24 call card, who is rung, what is logged.
# Who is rung first for an incoming call? (/docs/help-center/calls/who-is-rung-first)
You choose in **Settings → Calls**, for the whole portal: ring the **contact's responsible** first, or the responsible of the customer's **latest open deal** (if there is none, the open lead, then the contact). After that first step the usual fallback applies: everyone online with access to the number.
## Related [#related]
* [Calls](/docs/product/calls)
# My card is refused by Stripe. How else can I pay? (/docs/help-center/api-and-billing/card-refused-by-stripe)
A refusal with a generic code comes from the issuing bank, not from WASync, so the first thing to try is another card or asking the bank to allow the payment. If that is not possible, write to [support@wasync.app](mailto:support@wasync.app) with your portal name and the plan: we send a **Revolut payment link** by email, and once the payment is in, the licence is activated by hand, usually the same day. The invoice is issued the same way as for card payments.
## Related [#related]
* [Licences and trial](/docs/concepts/licences-and-trial)
# API, MCP and billing (/docs/help-center/api-and-billing)
Files through the MCP, payments, invoices.
# Do I get an invoice? (/docs/help-center/api-and-billing/invoices)
Yes. Stripe emails an invoice and a receipt for every payment, and all of them are available at any time from **Connections → the number → Manage subscription** in the app, which opens the Stripe customer portal. The company details on the invoice (name, address, VAT number) are the ones in that portal: fill them in before the payment, because an invoice is issued with the details at the moment of payment. Prices are in USD, without VAT; VAT is added according to your country and VAT status at checkout. Companies outside Romania also receive a fiscal invoice from TDACRM Solutions SRL for each payment.
## Related [#related]
* [Plans, trial and invoices](/docs/administration/billing)
# Can the MCP send files, or only text? (/docs/help-center/api-and-billing/mcp-send-files)
Files too. The MCP server exposes **send\_whatsapp\_file** next to the text tool: the agent passes a public **https URL** (preferred, any reasonable size) or the file itself in **base64** up to 5 MB, plus a file name, the type and an optional caption, and the file goes out from an authorised number like a text message, with the same permissions, audit and limits. URLs are fetched with strict checks (https only, public hosts only). Larger media goes through the REST API.
## Related [#related]
* [Guide: MCP](/docs/guides/mcp)
# Can I bring my WhatsApp Business API number from Twilio, 360dialog or Wazzup? (/docs/help-center/connections/bring-number-from-another-provider)
Yes. In **Connections** use **Bring a number from another provider**. The wizard runs the checks first (your business is verified with Meta, the account has room, two-step verification is off at the current provider), then Meta's own dialog where you enter the number, receive the code by SMS or call, and the number moves into a WhatsApp Business Account that you own. Your old provider keeps working until the move completes, usually a few minutes.
What comes along: the number, its display name, the Official Business Account status, the quality rating and the messaging limits, plus the approved, good-quality templates, which Meta copies without re-approval. What stays behind: the chat history at the old provider and templates that were rejected or pending.
If the number's page at your current provider has no **Two-step verification** tab, Meta has already retired the PIN for that number: proceed and tick the box in the wizard.
## Related [#related]
* [Guide: bring a number from another provider](/docs/guides/bring-your-own-number)
# Connections and numbers (/docs/help-center/connections)
QR and Business API numbers: disconnections, bringing a number, coexistence, deleting a connection, reliability.
# Can I keep WhatsApp Business on my phone and still have the number in Bitrix24? (/docs/help-center/connections/keep-whatsapp-business-on-phone-and-in-bitrix24)
Yes. Choose **Add WABA** in Connections and, in Meta's dialog, the option for a number that is already in the **WhatsApp Business app**; you scan a QR from the app and the number stays on the phone. It is then a Business API number too: templates, Meta's limits on business-initiated conversations and the 24-hour window apply, while the app keeps working as before.
Three things to know: a message typed on the phone does not open the 24-hour window for the API side; WhatsApp calls are not available on a number in coexistence; and the import of the last six months of conversations and of the contacts can be requested once, in the first 24 hours after connecting, after which Meta no longer offers it.
## Related [#related]
* [Connections](/docs/product/connections)
* [Connection types](/docs/concepts/connection-types)
# A message sent from the phone at 8 pm did not appear in Bitrix24. Can that happen? (/docs/help-center/connections/message-from-phone-missing-in-bitrix24)
On a connected number, no. Every message is stored by WASync before it is passed on, and the hand-over to Bitrix24 is retried for hours when Bitrix24 is slow or refuses it; an undeliverable message raises an alert instead of disappearing. Messages typed on the phone are mirrored the same way.
What can lose a message is the connection itself being down at that moment: a QR number whose linked device was removed, or a phone that was offline for a long time. Check the connection's history in **Connections** around that time; if it shows a disconnection, the message never reached WASync and is only on the phone.
## Related [#related]
* [Connections](/docs/product/connections)
# Messages go to my old provider, or sending fails with error 131070. (/docs/help-center/connections/messages-go-to-old-provider-error-131070)
This happens to a number brought from another provider when Meta's **Conversation routing** is on for it and the old provider is still its primary partner. The number shows as connected in WASync, but Meta hands every conversation to the old provider: customer messages do not arrive in WASync, and what you send fails with error **131070** ("another app is controlling this thread"). Reconnecting or re-registering the number does not change it; the setting is yours, at Meta.
WASync checks this after the move and several times a day, and shows a red warning on the number in **Connections** when it finds it. To fix it: in **Meta Business Suite → Settings → WhatsApp accounts**, select the number, open **Conversation routing** and set **WASync** as **Primary** for **Customer service**, **Click-to-WhatsApp ads**, **Utility**, **Marketing** and **Calls**, and as the **Escalation** partner. If you no longer use the old provider, you can remove it under **Partners** or **Messaging accounts** instead. The warning clears itself at the next check.
## Related [#related]
* [Guide: Conversation routing at Meta](/docs/guides/bring-your-own-number#conversation-routing-at-meta)
* [Connections](/docs/product/connections#conversation-routing-at-meta)
# I scanned the QR twice with the same phone and now I have duplicate notes. (/docs/help-center/connections/scanned-qr-twice-duplicate-notes)
Since 30 September 2026 a second scan of a number that is already connected on your portal is refused, so this cannot happen again: the new connection is marked as a duplicate and dismantled, and the existing one keeps working. The duplicate timeline notes created before that guard stay in Bitrix24; delete them from the record if they bother you. If you need a number on two connections on purpose, that is not supported; use one connection and give more people access to it in **Team**.
## Related [#related]
* [Connections](/docs/product/connections)
# I want to delete a connection. What do I lose? (/docs/help-center/connections/what-do-i-lose-when-deleting-a-connection)
Before deleting, the dialog shows what the number is doing: whether it is live, how many messages it carried in the last 24 hours (all traffic, as a sign it is in use), and which flows and automations are attached to it. Deleting removes the number from WASync, its conversations in WASync Chat, the Open Channel line that was created for it and the flows bound to it.
Nothing in the CRM is touched: leads, deals, contacts, the timeline comments and the files remain. If you only need to re-pair the same number, use **Reconnect** instead; it keeps everything.
## Related [#related]
* [Connections](/docs/product/connections)
# Why did my WhatsApp disconnect? (/docs/help-center/connections/why-did-my-whatsapp-disconnect)
When a QR number drops, WASync emails the administrators and shows the cause it could establish on the connection: most often WhatsApp removed the linked device, which happens when the number was logged out from the phone, when the same number was moved to the Business API, or after WhatsApp's own enforcement on messages to many new contacts in a short time. The alert also says how many new contacts were written in the hours before the drop, which is the usual sign of the last case.
To reconnect: **Connections → the number → Reconnect**, scan the QR with the phone, and the conversations resume. Flows, the Open Channel line and the team's access stay attached to the connection.
To keep a QR number healthy: no bulk sends to contacts who never wrote to you, warm a new number up gradually, and keep the phone online. For higher volumes or campaigns, use a Business API number.
## Related [#related]
* [Connections](/docs/product/connections)
# Can the customer's WhatsApp name and photo be copied to the CRM contact? (/docs/help-center/crm/copy-whatsapp-name-and-photo-to-contact)
Yes. Turn on **Copy WhatsApp name and photo to the contact card** in **Settings → CRM**; it is off by default. When a conversation becomes linked to a contact, the name from WhatsApp is written only if the card has no name or just the phone number as its name, and the photo only if the card has none. Existing names and photos are never overwritten.
The photo is available on QR numbers only; the Business API does not provide it.
## Related [#related]
* [CRM records and timeline](/docs/product/crm-records)
# CRM records and timeline (/docs/help-center/crm)
Leads, deals, contacts, timeline comments, sources, ads attribution, Smart Processes.
# All new chats land on me, the administrator, instead of the Open Channel queue. Why? (/docs/help-center/crm/new-chats-land-on-the-administrator)
Because a record created without an explicit responsible lands on the Bitrix24 user who installed the app, and the Open Channel then routes the conversation to the responsible of the record. Set the rule in **Settings → Chat rules → New chats from unknown numbers**: **Off** (no lead is created for unknown numbers), a **fixed person**, or a **rotation** over a list of employees. Flows that create records at enrolment follow the same rule.
Three switches in the same place refine it: create the lead also on numbers that feed an Open Channel; create the lead when an operator writes first to an unknown number, with that operator as the responsible; and create a lead for a known contact that has no open lead or deal.
## Related [#related]
* [The responsible of records WASync creates](/docs/product/crm-records#the-responsible-of-records-wasync-creates)
# The same message appears on lead 1, lead 2 and the contact. Can it be logged on one record only? (/docs/help-center/crm/one-timeline-comment-per-conversation)
Yes. By default every message is written on every record that carries the customer's phone number, including closed leads. In **Settings → CRM → Where to write the timeline** choose **One comment on the conversation's record**: from then on each message is written once, on the record the conversation is linked to (the one shown in the chat header, which you can change with **Change record**).
Nothing is deleted: comments already written stay on the records that have them; only new messages follow the new rule.
## Related [#related]
* [CRM records and timeline](/docs/product/crm-records)
# The lead was lost, the customer writes back an hour later, and a new lead is created. Can it reattach? (/docs/help-center/crm/recontact-window-after-lost-lead)
Yes. In **Settings → Chat rules → New chats from unknown numbers** set the **re-contact window**, in **hours** (it is 0, off, by default). A customer who writes back while their lost lead was closed less than that many hours ago is attached to that lead again instead of getting a new one, and an option reopens the lead into a stage you choose.
The window applies only to leads closed as **lost**, not to converted ones, and it is used both for new chats and when a flow would create a lead at enrolment. Outside the window the normal rule applies and a new lead is created.
## Related [#related]
* [CRM records and timeline](/docs/product/crm-records)
# Can I send WhatsApp from a CRM Marketing campaign or an automation rule? (/docs/help-center/crm/send-whatsapp-from-crm-marketing-or-automation-rule)
Yes. WASync registers as a message provider in Bitrix24, so **WASync WhatsApp** appears wherever Bitrix24 lets you pick an SMS provider: CRM Marketing campaigns, the automation rule **Send message**, business processes and the message button on a lead, deal or contact. The text is sent as a free WhatsApp message from the number you set as default for this in the connection's settings, and the delivery status comes back to Bitrix24.
On a Business API number a free text reaches only customers who wrote to you in the last 24 hours; outside that window Meta refuses it and Bitrix24 shows the message as failed. On a QR number there is no such window. For messages outside the window use templates, from WASync Chat or from a Chat Flow.
## Related [#related]
* [WhatsApp from CRM Marketing and automation rules](/docs/product/crm-records#whatsapp-from-crm-marketing-and-automation-rules)
# The customer writes to number X (from an ad) but already has a deal on another number. I want a separate lead per number. (/docs/help-center/crm/separate-lead-per-whatsapp-number)
Turn on **Each number creates its own lead** in **Settings → Chat rules → New chats from unknown numbers**. The setting is portal-wide and applies to all your WhatsApp numbers. From then on the record of a conversation is kept per number: a customer who writes to number X gets X's lead, even if the same person has a deal from number Y, and flows that create records at enrolment follow the same rule.
The reverse is also true, by design: one customer handled on two of your numbers has two leads. If you want one customer to be one record across all numbers, leave the setting off.
## Related [#related]
* [CRM records and timeline](/docs/product/crm-records)
* [Which record a flow creates or binds to](/docs/product/chat-flows#which-record-a-flow-creates-or-binds-to)
# We work with Smart Processes. Does WASync work on them? (/docs/help-center/crm/smart-processes-support)
Yes, on every Smart Process type. Items get the WASync tab with the conversation, messages are written on the item's timeline, the WhatsApp robots are available in the process's automation rules, and Chat Flows can be attached to items. Attribution from ads is written in the item's UTM fields.
One condition for the automatic linking of a conversation to an item: the process must have **Client** (contact) enabled, because the phone number lives on the contact. Without it the tab is there, but you link conversations by hand.
## Related [#related]
* [Guide: Smart Processes](/docs/guides/smart-processes)
# All timeline comments are signed by the person who installed the app. Can they be signed by the operator? (/docs/help-center/crm/timeline-comments-signed-by-operator)
Yes, and this is the current behaviour. A message sent by an operator from the Open Channel, from WASync Chat or from the WhatsApp tab on a record is written on the timeline as that operator. Incoming messages from customers are written as the app's technical user, because no employee wrote them.
The exception is a message typed on the company phone or in WhatsApp Web: it reaches Bitrix24 without an operator identity, so it is also written as the technical user.
## Related [#related]
* [CRM records and timeline](/docs/product/crm-records)
# Which ad brought the customer? I want the campaign and ad set, not only the ad id. (/docs/help-center/crm/which-ad-brought-the-customer)
Without any setup, a conversation that starts from a Click-to-WhatsApp ad already carries the ad id, on the contact and on the open leads or deals. To get the campaign and the ad set as well, add a **Meta Ads token** (a System User token with `ads_read` from your Business Manager) in **Settings**, card **Campaign and ad set on conversations from ads**. From then on the record's UTM fields hold the campaign, the ad set and the ad, in Meta's convention, and the timeline notes the attribution.
The ad information arrives with the message the customer sends from the screen the ad opened, whether they kept the suggested text or not. A message written later from the normal chat list carries no ad. It works on Business API and on QR numbers.
## Related [#related]
* [Guide: campaign and ad set on conversations from ads](/docs/guides/meta-ads-campaign-attribution)
# An employee filters by their own name and still sees other people's chats. Why? (/docs/help-center/wasync-chat/employee-filter-shows-other-peoples-chats)
Because the "Assigned to" filter and the **Only my records** level match a conversation by the responsible of the lead or deal **and** by the responsible of the CRM contact. A lead handed to a colleague stays visible to the person who still owns the contact, which is what most portals expect.
If your process gives every contact to one fixed employee while the leads rotate, that rule gets in the way. On request we can switch your portal so that the contact's responsible counts only when the customer has no open lead or deal; otherwise the lead or deal owner wins. Write to support with your portal name.
## Related [#related]
* [WASync Chat](/docs/product/wasync-chat)
# After an agent closes the lead, I want the chat to disappear from them so another agent can take the customer. Possible? (/docs/help-center/wasync-chat/hide-chat-from-agent-after-closing-lead)
Yes. In **Settings → Chat rules → Hide closed** turn the rule on and set after how many days a closed lead or deal stops giving visibility; **0** means the chat disappears the moment the record is closed. The rule applies to employees on the **Department** and **Only my records** levels; administrators and the **All** level keep seeing the conversation.
A second switch, **Ignore the contact's responsible**, is usually needed too: without it, a contact assigned to the same agent keeps the chat visible even after the lead is closed. When the customer writes again and a new lead is created, the conversation appears for the new lead's responsible.
## Related [#related]
* [WASync Chat](/docs/product/wasync-chat)
# Operators can change the stage from the chat. Can I hide that button? (/docs/help-center/wasync-chat/hide-stage-button-in-chat)
Yes. In **Settings → Chat rules → Stage picker** choose who may change the CRM stage from the WASync Chat header: **everyone**, **administrators only**, or **hidden** so the header shows the stage but nobody changes it there. The stage filter in the conversation list and the picker already respect each employee's CRM rights in Bitrix24; this setting narrows them further.
## Related [#related]
* [WASync Chat](/docs/product/wasync-chat)
# WASync Chat (/docs/help-center/wasync-chat)
The shared inbox: who sees what, stages, quick replies, linking conversations to records, long messages.
# My long message was rejected by WhatsApp (over 4,096 characters). What now? (/docs/help-center/wasync-chat/long-message-over-4096-characters)
Nothing: WASync splits it for you. WhatsApp's limit for one text message on the Business API is 4,096 characters; a longer text is cut into several messages, choosing the cut in this order: a paragraph break, a line break, the end of a sentence, any space. Code blocks are never split in the middle, and each part is recorded as its own message in the thread. Up to ten parts are sent.
The limit on a file description (caption) is 1,024 characters and is not split: a longer caption is refused, so keep captions short and put the long text in a separate message.
## Related [#related]
* [WASync Chat](/docs/product/wasync-chat)
# A chat stayed linked to someone else's deal. Can I move the conversation to another record? (/docs/help-center/wasync-chat/move-conversation-to-another-record)
Yes. Open the conversation, press **Change record** in the header and pick the lead, deal or contact it should belong to. From then on the header shows that record, new timeline comments go to it, and the "Assigned to" filter and the visibility levels follow it.
Nothing is moved or deleted: the chat thread belongs to the WhatsApp number and stays whole, and the comments already written on the old record's timeline remain there.
## Related [#related]
* [WASync Chat](/docs/product/wasync-chat)
# Do you have quick replies? I want to type "/" like in other tools. (/docs/help-center/wasync-chat/quick-replies-with-slash)
Yes. Type **/** at the start of a line, or after a space, in WASync Chat or in the WhatsApp tab on a CRM record, and pick a reply from the list. Replies are **personal** or **shared with the team**, in the same list, and are managed under **Quick replies** in the app.
A reply can contain variables with double braces: `{{greeting}}` for a greeting that follows the customer's local time, `{{contact.first_name}}` and other contact fields, `{{record.title}}` for the current lead or deal, and `{{crm.UF_CRM_…}}` for any CRM field. The greeting and the date formats follow the language and time zone deduced from the customer's phone country. A reply can also have versions in several languages, picked by the customer's country.
## Related [#related]
* [WASync Chat](/docs/product/wasync-chat)
# When I close a lead from the chat, the required field "reason" is not asked. How do I enforce it? (/docs/help-center/wasync-chat/required-fields-when-changing-stage-from-chat)
Bitrix24 does not apply its "required fields per stage" when a stage is changed through the API, which is how the chat changes stages, and it does not expose that configuration to apps. WASync has its own list for this: in **Settings → Chat rules → Required fields per stage** an administrator picks, for each lead or deal stage, the fields that must be filled before a record can be moved there from the chat.
When an operator picks such a stage in the chat header, a panel asks for exactly those fields and the stage changes only after they are filled. The list has to mirror the one in your CRM by hand; it is not read from Bitrix24.
## Related [#related]
* [WASync Chat](/docs/product/wasync-chat)
# Can I restrict employees to see only the chats of their own leads and deals? (/docs/help-center/wasync-chat/restrict-employees-to-their-own-chats)
Yes. Open the WASync app in Bitrix24, go to **Team**, and on the employee's row choose the visibility: **All conversations**, **Department** (the records of people in their Bitrix24 department) or **Only my records** (the leads, deals and contacts where they are the responsible person). Employees without an explicit choice get the level set in **Settings → Chat rules → Default visibility**.
Bitrix24 administrators always see everything. The same level applies to the conversation list, the search, the "Assigned to" filter and the export.
## Related [#related]
* [WASync Chat](/docs/product/wasync-chat)
# How do I send a voice note? (/docs/help-center/wasync-chat/send-a-voice-note)
Use the microphone button at the right end of the message box, in WASync Chat and in the WhatsApp tab of a CRM record. Click it to start (the tooltip reads **Record a voice note**), speak, then choose **Send voice note**; **Cancel recording** throws the recording away.
The first time, your browser asks for access to the microphone. If it is blocked, the button tells you so: allow microphone access in the browser's site settings for the page and try again. Inside the Bitrix24 window the microphone can be blocked too, so check that setting if the button still refuses.
It works on both kinds of number, QR and WhatsApp Business API. On a Business API number the note goes out as an audio message, and only while the 24-hour customer-service window is open; outside it, WhatsApp accepts only approved templates.
If you already have a recording, use the attach button in the same box and pick the audio file instead.
Voice notes your customers send play right in the conversation, and they reach the Bitrix24 Open Channel as a file.
## Related [#related]
* [WASync Chat](/docs/product/wasync-chat)
* [Voice-note transcription](/docs/product/wasync-chat#voice-note-transcription)
* [The 24-hour window and templates](/docs/guides/waba-templates#what-a-template-is-and-when-you-need-one)
# When I send a template with an image, why does it ask for the image again? (/docs/help-center/wasync-chat/template-with-image-asks-for-image-again)
Because Meta keeps the header image only for the approval of the template; at every send the file has to be supplied again. WASync stores the sample you uploaded when the template was created and pre-selects it in the send dialog, so in practice you confirm it or pick another file for this customer. Syncing templates from Meta does not remove the stored sample. This applies to Business API numbers only; QR numbers do not use templates.
## Related [#related]
* [WASync Chat](/docs/product/wasync-chat#templates-on-business-api-numbers)
* [Guide: WhatsApp templates](/docs/guides/waba-templates)
# How do I make the bot write only to new customers, not to people we already talk to? (/docs/help-center/chat-flows/bot-only-for-new-customers)
On the flow's Start card, under **Change when it starts**, turn on **Only customers who never wrote to you before**. The flow then starts only for a number that has never exchanged a message, in either direction, with any WhatsApp number of your portal.
"New" is decided from the conversation history, not from the CRM: a customer who exists in Bitrix24 but never wrote on WhatsApp is new; a customer who wrote once last year is not, even without a CRM record. Skipped customers are visible in the flow's history with the reason "known contact".
## Related [#related]
* [Only customers who never wrote to you before](/docs/product/chat-flows#only-customers-who-never-wrote-to-you-before)
# The bot started when a customer only replied to a message we sent. How do I avoid that? (/docs/help-center/chat-flows/bot-started-on-a-reply-to-our-message)
Leave the flow option **Flows do not start on a reply to your team** on; it is on by default, with a window of 72 hours that you can change. When the newest outgoing message to that customer on that number was written by a person, an incoming message inside the window is treated as a reply to your team, not as a new conversation, and the flow stays quiet.
What counts as "written by a person": a message from WASync Chat, from the WhatsApp tab on a record, from the Open Channel, or typed on the company phone. What does not count: the bot's own messages, robots, automations and the inactivity reminders. So a customer who answers your bot late still gets a fresh run, while a customer who answers your colleague does not get greeted by a bot.
## Related [#related]
* [Chat Flows: when a flow starts](/docs/product/chat-flows#when-a-flow-starts)
# How do I make the WhatsApp bot stop when a colleague replies? (/docs/help-center/chat-flows/bot-stops-when-colleague-replies)
It stops by itself. Every flow has a switch, **Stop when a colleague replies**, in **Flow settings → Handover**, and it is on by default. The moment a person from your team writes to the customer, from WASync Chat, the WhatsApp tab on a CRM record or the Open Channel, the run ends and the customer talks to the colleague. No step is needed in the flow for this.
Two details worth knowing:
* Messages typed on the phone or in WhatsApp Web do not stop the bot; they do not carry an operator identity.
* Messages sent by the bot itself, by robots, by automations and the inactivity reminders never count as a colleague, so they never stop a run by mistake.
The companion switch in the same place, **Run once per customer**, prevents the flow from enrolling a contact it has already finished with.
## Related [#related]
* [Chat Flows: when a flow starts](/docs/product/chat-flows#when-a-flow-starts)
# Leads created by the bot get the wrong source. Can I choose it? (/docs/help-center/chat-flows/choose-crm-source-of-flow-leads)
Yes. On the Start card there is a **Source** selector with your portal's CRM sources. Every contact, lead or deal the flow creates carries that source. A record the flow reuses, such as an open deal, is left untouched.
Without a selection the record gets the source configured on the Bitrix24 Open Channel that received the message: **Contact Center → the channel → CRM settings → Source**. That is also the setting to check when leads created by the Open Channel itself, not by a flow, show an unexpected source such as the name of a channel that was used for something else before.
## Related [#related]
* [The CRM source of the record](/docs/product/chat-flows#the-crm-source-of-the-record)
# Can I start a different flow for each Meta ad? (/docs/help-center/chat-flows/different-flow-per-meta-ad)
Yes. On the Start card choose **Customer writes first → From a specific ad** and list the ad ids from Ads Manager (one flow can hold several ids, so a whole campaign can share a flow). A number can have as many inbound flows as you need.
When a message matches more than one flow, the most specific wins: the flow for the customer's ad first, then a keywords flow, then **Any message**. A message from an ad you did not list, or from no ad at all, falls through to the keyword and "Any message" flows. The ad id, and with a Meta Ads token the campaign and ad set, are also written on the lead.
## Related [#related]
* [Chat Flows: when a flow starts](/docs/product/chat-flows#when-a-flow-starts)
* [Campaign and ad set on conversations from ads](/docs/guides/meta-ads-campaign-attribution)
# My flow has 200 steps. How do I find one? (/docs/help-center/chat-flows/find-a-step-in-a-large-flow)
Press **Ctrl+F** in the editor, or use **Find a step** in the toolbar, and type part of the step's title or message. The canvas jumps to the first match and flashes it; **Enter** and **Shift+Enter** move to the next and previous match. While a step is selected, its incoming and outgoing lines are coloured and the rest of the canvas fades, so you can follow one path through a large flow.
A flow can hold up to 300 steps.
## Related [#related]
* [The editor](/docs/product/chat-flows#the-editor)
# The flow creates a new lead although the customer already has an open deal. Can it attach to the existing one? (/docs/help-center/chat-flows/flow-attaches-to-existing-open-deal)
It does, by default. A lead flow first looks for the customer's contact in the CRM, then for an open deal of that contact, then for an open lead of that contact, then for any open lead that holds the number even without a contact (leads imported from another tool). It binds to the first one it finds and creates a lead only when nothing open exists.
Three situations still produce what looks like a duplicate, on purpose:
* **Each number creates its own lead** is on in Chat rules: the record is per WhatsApp number, so a customer handled on two numbers has two leads.
* The existing lead is **closed**. A lost lead can be taken back only inside the re-contact window set in Chat rules; otherwise a new lead is right.
* The phone on the old record is stored in a format that does not match (no country code, a different spelling); fix the phone on the record.
## Related [#related]
* [Which record a flow creates or binds to](/docs/product/chat-flows#which-record-a-flow-creates-or-binds-to)
# Can a flow look something up in an external system through an API? (/docs/help-center/chat-flows/flow-calls-external-api)
Yes. Add an **HTTP request** step. It calls any REST endpoint with the method, headers and body you define; flow variables such as the customer's answers or CRM fields can be inserted anywhere in the URL, the headers or the body. Fields from the JSON response are mapped into variables that later steps use in messages, conditions or CRM fields, and the step has separate branches for success and error.
Headers you mark as secret, typically the API key, are stored encrypted and are not shown again after saving; a re-save without retyping keeps the stored value. The request itself is made by an isolated worker, not by the WASync server, and only to public addresses.
## Related [#related]
* [HTTP request step](/docs/product/chat-flows#http-request-step)
* [Guide: HTTP request in Chat Flows](/docs/guides/chat-flows-http-request)
# The general flow greeted the customer again right after another flow handed them to a person. Why, and how do I stop it? (/docs/help-center/chat-flows/general-flow-greeted-again-after-handoff)
This used to happen because "Any message" really meant "any message while no flow is running": the moment the ad flow handed the customer to a person, the next message started the general flow. It no longer does.
An **Any message** flow now stays quiet when any flow on that number ended with the customer in the last 72 hours, whether it completed, handed off, escalated or was cancelled. The window is the same one used for "Flows do not start on a reply to your team". A close for inactivity does not count, so a customer who went silent and comes back later is greeted again. Flows triggered by an ad or by keywords are not affected by this rule and still start.
## Related [#related]
* [Chat Flows: when a flow starts](/docs/product/chat-flows#when-a-flow-starts)
# Chat Flows (/docs/help-center/chat-flows)
Bots on WhatsApp: when they start, when they stop, reminders, ads, sources and the records they create.
# How do I insert a step between two steps that are already connected? (/docs/help-center/chat-flows/insert-step-between-connected-steps)
Hover the connecting line between the two steps. A **+** appears on the line; press it, pick the step type, and the new step is inserted with the connections rewired: the first step now leads to the new one, and the new one leads to the step that followed. Nothing has to be dragged or reconnected by hand.
## Related [#related]
* [The editor](/docs/product/chat-flows#the-editor)
# Can the bot send a reminder if the customer does not reply, and close after that? (/docs/help-center/chat-flows/reminder-and-close-after-inactivity)
Yes. Open **Flow settings → If no reply**, or the same section on a single question to override it for that step. You set four things: after how many minutes to send a reminder, the reminder text, after how many more minutes to close the run, and an optional **closing message** the customer receives at that moment.
The close touches only the conversation: the run ends, the lead or deal keeps its stage, nothing is changed in the CRM. The customer is not locked out either: a message that arrives after the close starts the flow again from the beginning. The reminder and the closing message are recorded as the bot's own messages, so they never count as a colleague taking over.
## Related [#related]
* [Inactivity reminders and closing](/docs/product/chat-flows#inactivity-reminders-and-closing)
# Can I rotate new conversations among a group of employees? (/docs/help-center/chat-flows/rotate-conversations-among-employees)
Yes. Add an **Assign to** step and switch it from "one person" to **rotate within a group**, then order up to 50 employees. Each new run takes the next person on the list and sets them as the responsible of the lead or deal; the step's counter survives re-saves of the flow, so the rotation does not restart when you edit something else.
The counter belongs to the step: two steps, or two flows, with the same list rotate independently. Employees who have been deactivated in Bitrix24 are skipped automatically, and the history of the run names the person who was chosen.
## Related [#related]
* [Assign to a person or rotate within a group](/docs/product/chat-flows#assign-to-a-person-or-rotate-within-a-group)