Changelog
What changed in the API, and the security hardening behind it
This API is on the integration branch and rolling out. Confirm availability before building against anything below.
Full Parity for Keys
The API moved from a small partner-only surface to near-parity with the dashboard.
| Area | What is new |
|---|---|
| MCP | 43 tools, up from 20 - inbox reads, chat control, flows, deletes, channels, WhatsApp templates and Telegram bot settings joined messaging and contacts. See MCP. |
| Inbox reads | Keys can read conversations, threads, collections, labels and inbox counts under MESSAGES_READ. See reading the inbox. |
| Chat control | Mark read, retry a failed send, labels, internal notes, start and stop published flows. See managing the inbox. |
| Deletes | New CONVERSATIONS_DELETE scope for deleting chats and conversations. Irreversible. |
| Channels | Pause, resume, rename and set AI auto-reply; full WhatsApp template CRUD; eight Telegram bot settings operations. See channels. |
| Contacts | Upsert keyed on your own externalId, channel-identity binding, and new filters - externalId, phone, channel, custom fields, created range. See contacts. |
| Async send | sendMessage(async: true) returns immediately and reports the outcome by webhook. See async send. |
| Acting as an operator | actingUserId authors a message or note as a named operator. Omitted, the author is the organisation that owns the key. |
| Richer sends | trigger_conversation takes name and externalId, so a new contact arrives named and bound to your own id. The MCP message object gained from.name, externalMessageId, errorCode and errorMessage. |
Changes to Watch For
| Change | What to do |
|---|---|
author.kind can now be Organisation | A key send with no actingUserId is authored by the organisation owning the key. Add it to any strict allow-list, or those messages are dropped. See shared types. |
A WhatsApp template send starts as PENDING with placeholder text [template:<name>] | Wait for the status transition before treating the text as final. See template sends. |
New error TENANT_CONNECTION_UNAVAILABLE | An org on its own database or Redis is refused rather than served from shared infrastructure when that infra is down. Retry later. See errors. |
| BYO database and Redis URIs are validated | Schemes, hosts and Mongo query options are checked and a connection is probed before a client org is created. See bring your own database. |
trigger_conversation needs integrationId when an org has several WhatsApp numbers | It no longer picks the first one. Single-number orgs are unaffected. See which number the message goes out on. |
message.outbound.updated is now edits only | Delivery-status transitions moved to the new opt-in message.outbound.status. Subscribe to it, or you stop seeing status changes. |
| Page sizes are clamped to 100 for keys on every list operation | Page with the cursor rather than requesting a larger page. |
| Rate limits are enforced per key and per org | Honour retryAfterMs and Retry-After. See rate limits. |
| Webhook receivers must be public HTTPS, and redirects are not followed | A receiver answering 301 or 308 fails permanently. Point the subscription at the final URL. |
| PII filters are refused, not emptied | Without PII_READ, a rule on contact name, assignee or a profile field is a 403. |
| The organisation slug is permanent | See general settings. |
| Only published flows can be started | In the dashboard and over the API alike. |
| Flow HTTP cards cannot reach private addresses | See the fetch card. |
Security Hardening
A round of hardening shipped alongside the new surface. No exploit detail is published here.
| Area | What was hardened |
|---|---|
| Tenant isolation | Every client-supplied id on the key and MCP surface is checked against the target organisation before use. A foreign id behaves exactly like a missing one. |
| Flows | Starting flows, sub-flows, triggers, card references and flow media are confined to the organisation that owns them - for members as well as keys. |
| Media | Sends, widget visitor attachments, WhatsApp template media, organisation logos, support attachments and several delete paths are confined to the organisation's own media. |
| Outbound requests | SSRF protection on webhook delivery (public HTTPS only, no redirects, DNS-rebinding safe), flow HTTP fetch cards, custom AI provider URLs, news and help feeds, and Salesforce instance URLs. |
| Rate limiting and abuse | Per-key and per-organisation limits, failed-authentication throttles, GraphQL operation limits, an MCP body limit, and widget visitor handshake limits by real client IP. |
| Authentication | Strict API-key header parsing, so a malformed header can never fall through into another tenant's context, plus a tenant-context guard on key requests. |
| Privacy | PII and internal-note oracles closed in search and collection rules; sensitive fields masked for keys; no platform emails to partner-managed organisations; destructive operations require explicit scopes and write audit lines. |
| Real-time | WebSocket subscriptions reject a stale organisation handshake. |
Two of these change behaviour you may be relying on: a foreign or malformed id now answers the same way a missing one does, and a webhook receiver behind a redirect stops working. Both are listed under changes to watch for.
Also Worth Knowing
These affect the dashboard as well as the API:
- A user goes offline 12 seconds after their last connection closes, so a page reload no longer flickers their presence.
- Media attached to a send must belong to your organisation, and widget visitors can attach only media they uploaded themselves.
- A visitor can mark read only the messages of their own conversation.
- WhatsApp templates can be created on paused channels, and a bad integration raises a not-found rather than returning a failure object.
- Telegram messages are re-sent as plain text only when Telegram rejects the formatting, not on any error.
- Early delivery receipts from Meta are buffered, so a status arriving before the message was stored is no longer lost.
- A WhatsApp profile name fills an empty or phone-number name only, and never overwrites one you set.
- Replies, templates and the 24-hour window check now resolve against the chat's own channel rather than the organisation's first one, which matters once an organisation has more than one WhatsApp number.
- Flow and bot messages are attributed to the chat's own bot, so an organisation running several Telegram or Viber bots sees each conversation answered by the right one.
- Inbound WhatsApp and Instagram webhooks answer 503 during a tenant-infrastructure outage, so Meta retries them instead of dropping the message.
- Suspended-organisation and operation-limit checks now apply uniformly across inbound Telegram, Viber, WhatsApp and Instagram.
- An organisation with its own database or Redis exposes
tenantConnection, readable only by that organisation.