Turbo Notify: WhatsApp for AI agents
REMOTE · MCP.TURBONOTIFY.COM
Send and receive WhatsApp messages from your AI agent, on your own number, with Turbo Notify.
Available components
Last scanned (22 hours ago)
Scores higher than 69% of remote servers
Reachable. Last reached 4 Nov 2026.
Category Communication
How this component scores in each security and reliability category. Every signal is checked automatically against the live server, and we only credit what we can confirm. How we score → Why this is hard to score →
Endpoint Security92
- The endpoint's TLS certificate is valid, in date, and uses a strong key. View diagnostics → Pass
- Authorisation is enforced on tool calls, advertised via RFC 9728 protected-resource metadata. Discovery is public, which costs nothing: no tool can be invoked without a token. View diagnostics → Pass
- HTTPS is enforced; there's no plaintext access path. View diagnostics → Pass
- HSTS check failed: the Strict-Transport-Security header is absent. See how to fix → View diagnostics → Fail
- DNSSEC check failed: this domain isn't protected by DNSSEC. See how to fix → View diagnostics → Fail
- The authorisation server supports Client ID Metadata Documents, the current MCP client-registration mechanism. View diagnostics → Pass
Transport & Reachability100
- Verified streamable-http transport via a live MCP handshake. View diagnostics → Pass
Schema Quality & AI Usability61
- AI-judged instruction clarity (excellent).Pass
- Context-footprint check failed: tool/resource definitions use about 15099 tokens (~419/item across 36 items; 36 tools + 0 resources), over budget; trim descriptions and params. See how to fix → Fail
- Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management7
- Stability observed for 2 of 30 days with no destabilising changes; credit accrues until the full window elapses.Partial
Tool Coverage100
- 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
- 100% of tool parameters carry a description.Pass
- Structured output schemas are declared (100% of tools); any adoption earns full credit.Pass
Tool Safety100
- No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
- All 8 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation.Pass
- An AI judge read all 37 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
- Implements a current MCP spec version (2026-07-28).Pass
Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.
- 4 Nov 26 +1
- Tool “get_number” rewrote its description, which is the text the model reads security
- 3 Nov 26 0
- Stability: unverified → 0.03 ▲ functional
- This server's schema is too large to store in full, so we cannot compare its tools day to day functional
- 2 Nov 26 +39
- Transport: unverified → pass ▲ security
- Injection markers: unverified → pass ▲ security
- First check of Judged manipulation: pass security
- Authorization: Authorisation is enforced on tool calls, advertised via RFC 9728 protected-resource metadata. Discovery is public, which costs nothing: no tool can be invoked without a token. security
- MCP protocol: unverified → pass ▲ functional
- Tool coverage: unverified → 100 ▲ functional
- First check of Schema quality: fail functional
- First check of Schema quality: excellent functional
- First check of Schema quality: fail functional
- First check of Destructive annotations: 100 functional
- First check of Tool coverage: 100 functional
- First check of Tool coverage: 100 functional
- This server's schema is too large to store in full, so we cannot compare its tools day to day functional
- 28 Oct 26 37
First indexed and scored.
Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.
Captured 4 Nov 2026 · Probed https://mcp.turbonotify.com
TLS valid
Negotiated TLS 1.3 with TLS_AES_128_GCM_SHA256 .
| Subject | Issuer | Valid from | Valid until | Key | Signature | Serial |
|---|---|---|---|---|---|---|
| CN=mcp.turbonotify.com | CN=YR1,O=Let's Encrypt,C=US | 27 Oct 2026 | 25 Jan 2027 | RSA 4096 | SHA256-RSA | 57c75db13fa0dd4ac2f9923e7a37a05a738 |
| SANs: mcp.turbonotify.com | ||||||
| CN=YR1,O=Let's Encrypt,C=US (CA) | CN=Root YR,O=ISRG,C=US | 3 Sept 2025 | 2 Sept 2028 | RSA 2048 | SHA256-RSA | a20253f15f2691c05dc1ce13b9bcca4e |
| CN=Root YR,O=ISRG,C=US (CA) | CN=ISRG Root X1,O=Internet Security Research Group,C=US | 13 May 2026 | 2 Sept 2032 | RSA 4096 | SHA256-RSA | f24b6d17f9d9ad7cb1c9fea78782699f |
Background: What to check on a remote MCP endpoint →
DNSSEC insecure
Validation of mcp.turbonotify.com. — Not signed
| Zone | DS | Keys | Algorithms | Outcome |
|---|---|---|---|---|
| . | trust_anchor | 20326, 38696 | 8, 8 | Verified |
| com. | present | 19718 | 13 | Verified |
| turbonotify.com. | absent | Unsigned (proven) parent-signed NSEC/NSEC3 proves an unsigned delegation |
Authentication Enforced and verified
The endpoint asked for a token and published valid RFC 9728 metadata describing how to get one.
| Result | Enforced and verified |
|---|---|
| Enforced | On tool calls |
| HTTP status | 200 |
WWW-Authenticate challenge Bearer resource_metadata="https://mcp.turbonotify.com/.well-known/oauth-protected-resource", scope="messages:send messages:read numbers:write numbers:read events:read contacts:read contacts:write groups:read"
Bearer resource_metadata="https://mcp.turbonotify.com/.well-known/oauth-protected-resource", scope="messages:send messages:read numbers:write numbers:read events:read contacts:read contacts:write groups:read" Protected resource metadata
| Document | https://mcp.turbonotify.com/.well-known/oauth-protected-resource |
|---|---|
| Retrieved | Yes |
| Resource | https://mcp.turbonotify.com |
| Authorisation server | https://auth.turbonotify.com |
Background: How OAuth 2.1 works in the 2026 MCP spec →
Transports 2 probes
| Transport | URL | Outcome | Status | Location |
|---|---|---|---|---|
| streamable-http | https://mcp.turbonotify.com | Verified | 200 | |
| http (plaintext) | http://mcp.turbonotify.com | HTTPS enforced | 301 | https://mcp.turbonotify.com/ |
The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →
cancel_calendar_event Cancel a calendar event already sent ~751
Cancel a calendar event this number already sent. The event stays in the chat marked as canceled, and WhatsApp tells the guests. Send the same `name` and `start_at` the event has, plus the details you want the canceled card to still show (`description`, `end_at`, `join_link`, `location`, `has_reminder` with `reminder_offset_sec`, `extra_guests_allowed`): the canceled event is shown with what you send here, and anything you leave out disappears from it. Cancel when the date, time or place change and the guests must accept again: cancel the old event here, then send the new one with `send_calendar_event`, because the old answer does not carry over to a new event. To correct a mistake (a typo, the description, a link) use `edit_calendar_event` instead, and the guests keep their answer. A cancel does not change the entry a guest already added to their own calendar with the card's "Add to calendar" button. It stays on the old date, and adding again creates a second entry, which only the guest can delete. Only a calendar event can be canceled. Using this tool on any other message answers `invalid_request: message_not_editable`; to take back a message of another kind, use `delete_message`. Only a message sent THROUGH Turbo Notify can be canceled. One typed on the phone itself belongs to the same number but cannot be canceled here, and neither can a message received from someone else. The 15-minute limit for a text or a caption does not apply to a calendar event. The cancel is accepted at once and the outcome arrives as an event: `message.edited` when it worked, `message.edit.failed` when WhatsApp or the platform could not apply it. Read them with `list_events`. The number first appears online and its unread messages in that conversation are marked as read, then the cancel happens. Opening the conversation this way is automatic and uses no quota of its own.
| Name | Type | Req | Description |
|---|---|---|---|
| description | – | – | Details shown on the event, up to 2000 characters. |
| end_at | – | – | When the event ends. ISO 8601 with an offset, and later than `start_at`. |
| extra_guests_allowed | – | – | Set to true to let guests bring extra people. Off when left out. |
| has_reminder | – | – | Set to true to remind guests before the event. Off when left out. |
| join_link | – | – | A link guests can open to join, for example a video call. |
| location | – | – | Where the event takes place: a map pin with an optional name and address. |
| message_id | string | yes | Message id (`msg_…`), as returned by a send or by `list_messages`. |
| name | string | yes | The event's title, up to 200 characters. |
| number_alias | string | – | Which of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to… |
| reminder_offset_sec | – | – | How many seconds before the event the reminder goes off, for example 600 for ten minutes. Only takes effect together with `has_reminder`. |
| start_at | string | yes | When the event starts. ISO 8601 with an offset, for example `2026-09-10T14:00:00Z`. A time without an offset is rejected. |
Structured output declared, but exposes no named fields.
No examples provided.
connect_number Bring a number back online ~323
Reconnect a number that is currently offline. Uses the credentials already stored for the number, so no QR code and no human are involved. Use it when `get_number` reports `disconnected` and you want to send. Returns immediately, before the connection is established. The answer has the number's `alias`, `status` set to `connecting` and `at`, the moment the request was accepted. The number reaches `connected` a few seconds later: poll `get_number`, which stays the source of the current status and of its own `at`, rather than assuming it worked. It works the same on every number and never charges. On an extra number scheduled for removal it does not change the removal: the number keeps working until its date. Cancelling a removal is not available to agents. This cannot rescue a `revoked` number: that one was unlinked from the phone and needs a person to pair it again. Calling it again changes nothing further. A number that is already `connected` or `connecting` answers with an `already_connected` or `already_connecting` error, which means the goal is met, not that the call failed.
| Name | Type | Req | Description |
|---|---|---|---|
| number_alias | string | – | Which of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to… |
Structured output declared, but exposes no named fields.
No examples provided.
delete_message Delete a message for everyone ~204
Revoke a message for everyone in the conversation. This is WhatsApp's "delete for everyone". It is not reversible, and recipients see a tombstone where the message was, so they can tell something was deleted. Confirm with a human before using it on anything a person has plausibly already read. The number first appears online and its unread messages in that conversation are marked as read, then the message is deleted. Opening the conversation this way is automatic and uses no quota of its own.
| Name | Type | Req | Description |
|---|---|---|---|
| message_id | string | yes | Message id (`msg_…`), as returned by a send or by `list_messages`. |
| number_alias | string | – | Which of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to… |
Structured output declared, but exposes no named fields.
No examples provided.
disconnect_number Take a number offline without unlinking it ~287
Take a number offline deliberately, keeping its link to the phone. The stored credentials survive, so `connect_number` brings it straight back with no pairing. Nothing is deleted. Disconnecting does not stop billing: an extra number is billed every cycle until it is removed. Returns immediately, before the number is offline. The answer has the number's `alias`, `status` set to `disconnecting` and `at`, the moment the request was accepted. `disconnecting` is not a status that `get_number` reports: it keeps showing the previous status and its own `at` until the number is offline. While disconnected the number cannot send or receive, and messages addressed to it are refused rather than queued. Deliberate: a message held for an unknown period and delivered later is worse than one that failed clearly. Calling it again changes nothing further. A number that is already offline answers with an `already_disconnected` error, which means the goal is met, not that the call failed.
| Name | Type | Req | Description |
|---|---|---|---|
| number_alias | string | – | Which of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to… |
Structured output declared, but exposes no named fields.
No examples provided.
edit_calendar_event Edit a calendar event already sent ~734
Correct a calendar event this number already sent. `name` and `start_at` are always required, plus whatever else the event has: `description`, `end_at`, `join_link`, `location`, `has_reminder` with `reminder_offset_sec`, and `extra_guests_allowed`. This REPLACES the whole event: anything you leave out is removed from it, including its location, reminder and guest setting, so send again every detail you want to keep. The event keeps its place in the chat and the guests keep the answer they already gave. Use an edit to fix a mistake (a typo, the description, a link). When the date, time or place change and the guests must accept again, do not edit: cancel the event with `cancel_calendar_event` and send a new one with `send_calendar_event`, because the old answer does not carry over to a new event. Neither an edit nor a cancel changes the entry a guest already added to their own calendar with the card's "Add to calendar" button. It stays on the old date, and adding again creates a second entry, which only the guest can delete. Only a calendar event can be edited here. Using this tool on any other message answers `invalid_request: message_not_editable`. Only a message sent THROUGH Turbo Notify can be edited. One typed on the phone itself belongs to the same number but cannot be edited here, and neither can a message received from someone else. The 15-minute limit does not apply to a calendar event. The edit is accepted at once and the outcome arrives as an event: `message.edited` when it worked, `message.edit.failed` when WhatsApp or the platform could not apply it. Read them with `list_events`. The number first appears online and its unread messages in that conversation are marked as read, then the edit happens. Opening the conversation this way is automatic and uses no quota of its own.
| Name | Type | Req | Description |
|---|---|---|---|
| description | – | – | Details shown on the event, up to 2000 characters. |
| end_at | – | – | When the event ends. ISO 8601 with an offset, and later than `start_at`. |
| extra_guests_allowed | – | – | Set to true to let guests bring extra people. Off when left out. |
| has_reminder | – | – | Set to true to remind guests before the event. Off when left out. |
| join_link | – | – | A link guests can open to join, for example a video call. |
| location | – | – | Where the event takes place: a map pin with an optional name and address. |
| message_id | string | yes | Message id (`msg_…`), as returned by a send or by `list_messages`. |
| name | string | yes | The event's title, up to 200 characters. |
| number_alias | string | – | Which of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to… |
| reminder_offset_sec | – | – | How many seconds before the event the reminder goes off, for example 600 for ten minutes. Only takes effect together with `has_reminder`. |
| start_at | string | yes | When the event starts. ISO 8601 with an offset, for example `2026-09-10T14:00:00Z`. A time without an offset is rejected. |
Structured output declared, but exposes no named fields.
No examples provided.
edit_media_caption Edit the caption of an image, video or document ~462
Replace the caption of an image, video or document this number already sent. The recipient sees the new caption marked as edited. The file itself stays exactly as it was and the message keeps its id: only the caption changes. There is no way to replace the file; to send a different one, send a new message with `send_media`. Only an image, video or document can be edited this way. Audio and stickers have no caption, and a location, contact card or link button cannot be edited at all: `delete_message` is the only change for them. For the text of a text message use `edit_text_message`. Using this tool on any other message answers `invalid_request: message_not_editable`. Only a message sent THROUGH Turbo Notify can be edited. One typed on the phone itself belongs to the same number but cannot be edited here, and neither can a message received from someone else. WhatsApp only accepts a change to a caption within 15 minutes of sending it. A later edit is refused up front with `invalid_request: edit_window_expired`; send a new message instead. The edit is accepted at once and the outcome arrives as an event: `message.edited` when it worked, `message.edit.failed` when WhatsApp or the platform could not apply it. Read them with `list_events`. The number first appears online and its unread messages in that conversation are marked as read, then the edit happens. Opening the conversation this way is automatic and uses no quota of its own.
| Name | Type | Req | Description |
|---|---|---|---|
| caption | string | yes | The new caption, up to 1024 characters. It replaces the whole caption. Writing `@<number>` mentions that person, as in a caption on send. |
| message_id | string | yes | Message id (`msg_…`), as returned by a send or by `list_messages`. |
| number_alias | string | – | Which of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to… |
Structured output declared, but exposes no named fields.
No examples provided.
edit_text_message Edit the text of a message already sent ~423
Replace the text of a text message this number already sent. The recipient sees the new text marked as edited. The message keeps its id and its place in the conversation; only the text changes. Only a text message can be edited here. For the caption of an image, video or document use `edit_media_caption`, and for a calendar event `edit_calendar_event` or `cancel_calendar_event`. A location, contact card, link button, sticker or audio message cannot be edited at all: `delete_message` is the only change for them. Using this tool on any message that is not text answers `invalid_request: message_not_editable`. Only a message sent THROUGH Turbo Notify can be edited. One typed on the phone itself belongs to the same number but cannot be edited here, and neither can a message received from someone else. WhatsApp only accepts a change to a text within 15 minutes of sending it. A later edit is refused up front with `invalid_request: edit_window_expired`; send a new message instead. The edit is accepted at once and the outcome arrives as an event: `message.edited` when it worked, `message.edit.failed` when WhatsApp or the platform could not apply it. Read them with `list_events`. The number first appears online and its unread messages in that conversation are marked as read, then the edit happens. Opening the conversation this way is automatic and uses no quota of its own.
| Name | Type | Req | Description |
|---|---|---|---|
| message_id | string | yes | Message id (`msg_…`), as returned by a send or by `list_messages`. |
| number_alias | string | – | Which of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to… |
| text | string | yes | The new text. It replaces the whole text of the message. |
Structured output declared, but exposes no named fields.
No examples provided.
get_contact Get one contact ~258
Fetch one contact: name, phone number and activity timestamps. `first_messaged_at` is when a message from this number first reached them on WhatsApp, and `last_interaction_at` is the last message that passed in EITHER direction, so it moves when they write to you as well. A message that failed before reaching WhatsApp moves neither. `refresh` shows the last `refresh_contact` you asked for: when it was requested, when it finished, and its `outcome` (`updated`, `unchanged`, `number_not_connected` or `unavailable`). While `completed_at` is null it is still running. The id must belong to the inbox named by `number_alias`. An id from a different number returns not found even though the person exists.
| Name | Type | Req | Description |
|---|---|---|---|
| contact_id | string | yes | Contact id (`ct_…`), from `list_contacts`. |
| number_alias | string | – | Which of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to… |
Structured output declared, but exposes no named fields.
No examples provided.
get_contact_profile_picture Get a contact's profile picture ~180
Get a contact's profile picture, or the reason there is none. The answer carries `kind`: `available` with a temporary URL, or `unavailable` with a reason. `no_storage` means the organization has not configured object storage, which is a setup step rather than a fault with this contact. The person may also simply have no picture, or have hidden it in their privacy settings.
| Name | Type | Req | Description |
|---|---|---|---|
| contact_id | string | yes | Contact id (`ct_…`), from `list_contacts`. |
| number_alias | string | – | Which of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to… |
Structured output declared, but exposes no named fields.
No examples provided.
get_contact_quota Get a number's contact quota for this billing cycle ~146
Check how much of this number's contact allowance is left. A contact counts once per billing cycle when this number messages them through Turbo Notify, new **or** returning. Messaging the same person again in a later cycle counts again. Like the message quota, this is per number rather than per organization, and it resets at `cycle_end`.
| Name | Type | Req | Description |
|---|---|---|---|
| number_alias | string | – | Which of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to… |
Structured output declared, but exposes no named fields.
No examples provided.
get_group Get one group ~195
Fetch a group: its name, description, picture and settings. Returns how many participants it has, not who they are. Membership is deliberately not readable: it arrives as it changes, on the `group.participants_added` / `_removed` / `_promoted` / `_demoted` events, which `list_events` can read.
| Name | Type | Req | Description |
|---|---|---|---|
| group_id | string | yes | Group id (`grp_…`), from `list_groups`. It belongs to the number you listed it under: passing it under a different number answers not found, which means wrong inbox rather than deleted. |
| number_alias | string | – | Which of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to… |
Structured output declared, but exposes no named fields.
No examples provided.
get_group_picture Get a group's picture ~181
Get a group's picture, or the reason there is none. Same shape as a contact's picture. The answer carries `kind`: `available` with a temporary URL, or `unavailable` with a reason. `no_storage` means the organization has not configured object storage.
| Name | Type | Req | Description |
|---|---|---|---|
| group_id | string | yes | Group id (`grp_…`), from `list_groups`. It belongs to the number you listed it under: passing it under a different number answers not found, which means wrong inbox rather than deleted. |
| number_alias | string | – | Which of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to… |
Structured output declared, but exposes no named fields.
No examples provided.
get_message Get one message in full ~235
Fetch one message with its full content, parties and mentions. The answer includes the number's stable `number_id` (`num_…`) next to `number_alias`. `at` is when the message actually happened on WhatsApp; `status.at` is when it reached its current delivery status and keeps moving as receipts arrive. They answer different questions and are not interchangeable. Returns not found if the id belongs to a different number. Past the organization's content retention window (1 hour by default, up to 72 hours depending on the plan) the message is still returned, with `content_expired` true and its content empty.
| Name | Type | Req | Description |
|---|---|---|---|
| message_id | string | yes | Message id (`msg_…`), as returned by a send or by `list_messages`. |
| number_alias | string | – | Which of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to… |
Structured output declared, but exposes no named fields.
No examples provided.
get_message_quota Get a number's message quota for this billing cycle ~166
Check how much of this number's message allowance is left. The quota is **per number**, not per organization: an organization with three numbers has three separate allowances. It resets at `cycle_end`, which is the organization's real billing boundary rather than a rolling window, so `resets_at` is a date you can plan around. Only messages sent through Turbo Notify consume it. Messages someone sends from the phone itself do not.
| Name | Type | Req | Description |
|---|---|---|---|
| number_alias | string | – | Which of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to… |
Structured output declared, but exposes no named fields.
No examples provided.
get_message_reactions Get the reactions on a message ~179
List the emoji reactions on a message, and who left each one. Each entry names the reactor and the emoji. Reactions are replaced rather than accumulated per person: someone who reacts twice leaves one entry showing their latest emoji, so this is a current snapshot and not a history. An empty list is the normal answer for most messages, and is not an error.
| Name | Type | Req | Description |
|---|---|---|---|
| message_id | string | yes | Message id (`msg_…`), as returned by a send or by `list_messages`. |
| number_alias | string | – | Which of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to… |
Structured output declared, but exposes no named fields.
No examples provided.
get_message_receipts Get per-recipient delivery and read receipts ~166
See who received and who read a message. Most useful for group messages, where the single status on the message cannot express that some members read it and others have not. Requires a plan that includes read receipts; on plans without it the call is refused with `feature_not_available`, which no retry will fix.
| Name | Type | Req | Description |
|---|---|---|---|
| message_id | string | yes | Message id (`msg_…`), as returned by a send or by `list_messages`. |
| number_alias | string | – | Which of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to… |
Structured output declared, but exposes no named fields.
No examples provided.
get_message_responses Get the guests' answers to a calendar event ~272
See how the guests answered a calendar event: going, not going or maybe. Only works on a calendar event; any other message answers `invalid_request: message_not_calendar`. The answer has `counts` (how many guests are going, not going or maybe, and how many extra guests those who are going or maybe are bringing) and `responses`, one entry per guest with who they are, their answer, any extra guests they bring and when they answered. A guest who changes their mind leaves one entry showing the latest answer, so this is a current snapshot and not a history. To be told as answers come in, watch for `message.calendar_responded` with `list_events`. An event nobody has answered yet returns zero counts and an empty list, which is the normal answer and not an error.
| Name | Type | Req | Description |
|---|---|---|---|
| message_id | string | yes | Message id (`msg_…`), as returned by a send or by `list_messages`. |
| number_alias | string | – | Which of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to… |
Structured output declared, but exposes no named fields.
No examples provided.
get_message_status Get a message's delivery status ~176
Check where a message got to: queued, sent, delivered, read, failed. Status only moves forward. A failed status always carries an error code, and for a few media and reaction problems it also carries a hint naming the field to change; most failures give the code alone. Read the code before retrying, because most failures repeat identically.
| Name | Type | Req | Description |
|---|---|---|---|
| message_id | string | yes | Message id (`msg_…`), as returned by a send or by `list_messages`. |
| number_alias | string | – | Which of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to… |
Structured output declared, but exposes no named fields.
No examples provided.
get_number Get one number and its connection status ~536
Check one number: its phone number, status, and when that status began. `id` (`num_…`) is the number's permanent identifier. The alias can be renamed, the `id` cannot. Either one works as `number_alias`. `connected` means it can send right now. `connecting` means a connection was just requested and is being set up; check again in a few seconds. `reconnecting` means the number lost its connection and Turbo Notify is bringing it back by itself: there is nothing to do but wait and check again. Until it is `connected` again, sends are refused with `number_not_connected`. `disconnected` means the link to the phone still exists but the number is offline, so `connect_number` brings it back. `inactive` is the same for a number that was linked and has not been brought online yet: `connect_number` brings it online too. `pending` means the number was never linked to a phone, and `no_main_number` (what a brand-new account gets for `main`, and `list_numbers` is empty) means there is no number at all yet: either way a person has to link it from the Numbers page of the dashboard, so tell them and do not retry the send meanwhile. `revoked` means the phone unlinked the device, or another connection took it over. `failed` means a pairing did not complete, and `reason` says why (for example `pairing_timeout` when the code or QR code was not used in time, `paired_phone_mismatch` when another WhatsApp used it). Either one has to be paired again by a person holding that phone: from the dashboard (main or extra number) or, for an extra number, through the API's pairing endpoint, by code or by QR code. No tool here pairs a number: it needs a person with the phone. `pairing` means a person is pairing the number right now. The code or QR code they use is not part of this answer: it belongs to that person. Check again later; the status moves to `connected`, or to `failed` with a `reason`.
| Name | Type | Req | Description |
|---|---|---|---|
| number_alias | string | – | Which of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to… |
Structured output declared, but exposes no named fields.
No examples provided.
get_usage Get the organization's usage across all numbers ~129
Get message and contact usage for the whole organization. The top-level totals are the **sum across every live number**: an organization with two numbers on a 50,000-message plan reports a quota of 100,000, not 50,000. The `numbers[]` breakdown shows each number separately, which is what you need to find the one that is close to its own ceiling, so a healthy-looking total can hide a number at 99%. For one number, `get_message_quota` and `get_contact_quota` are more direct.
Input schema present but exposes no named parameters.
Structured output declared, but exposes no named fields.
No examples provided.
list_contacts List an inbox's contacts ~421
List the people this number has exchanged messages with. Filter by `phone` or by `name`. They are separate filters, not one search box: `name` matches the contact's name, `phone` matches the number. `source` restricts to how the contact first appeared: `inbound` (they messaged this number), `outbound` (this number messaged them), `mention` (named in a group message) or `self` (the number's own contact card). `contacted_in_cycle=true` narrows the list to exactly the people counting against this number's contact quota this billing cycle: those messaged through Turbo Notify inside the cycle, whether newly or again. Use it to see what the quota gauge is actually counting.
| Name | Type | Req | Description |
|---|---|---|---|
| contacted_in_cycle | – | – | When true, return only the people who count against this number's contact quota in the current billing cycle: those messaged through Turbo Notify inside the cycle, new or returning. Use it to see exa… |
| cursor | – | – | Opaque cursor for the next page. Pass back the `cursor` from the previous response, with the same filters; omit it for the first page. |
| limit | – | – | How many items to return, 1-200. Defaults to 50. |
| name | – | – | Only contacts whose name matches. |
| number_alias | string | – | Which of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to… |
| phone | – | – | Only contacts whose phone number matches. |
| source | – | – | Only contacts that first appeared this way: `inbound` (they messaged this number), `outbound` (this number messaged them), `mention` (named in a group message) or `self` (the number's own contact car… |
Structured output declared, but exposes no named fields.
No examples provided.
list_events Poll the organization's event log ~1,081
Poll everything that happened: messages, contacts, groups, numbers, quotas. This is how an agent learns about inbound messages without hosting a webhook endpoint. **Events come back newest first, so polling for new ones uses `ending_before`, not `starting_after`.** Typical loop: call with no cursor and remember the id of the FIRST event in the page (the newest one); next time, pass that id as `ending_before` to get only what has happened since. An empty page means you are caught up. `starting_after` does the opposite: it walks BACKWARD into history, which is what you want for reading a backlog, and never what you want for noticing something new. Passing the last id you handled to `starting_after` in a loop returns steadily older events and never reaches the present. `request_id` returns everything that came of one earlier call. A write tool's result carries `request_id` when the platform issued one; keep it and you can ask later what became of that specific send. `number_id` restricts to one number and keeps matching its events after the number is renamed. `number_alias` restricts to one inbox by the alias it had when the event happened, so a rename hides the older events; the two can be combined. Either one excludes `storage.*` and `media.unavailable` events, which belong to the organization rather than to any one number. Most events carry a `number_alias` telling you which inbox they belong to, and `number_id` (`num_…`), the same number's permanent identifier. The alias is the one at the time of the event and can be renamed later; the `number_id` cannot. You need one of them: message, contact and group ids are unique but not self-addressing, so an id alone does not tell you which number's tools to use with it, and both work as `number_alias` in the other tools. Read the fields defensively rather than assuming they are there: `storage.*` and `media.unavailable` belong to the organization as a whole and have no single number to name, so on those the keys are…
| Name | Type | Req | Description |
|---|---|---|---|
| created_gte | – | – | Only events created at or after this instant. ISO 8601 with an offset, e.g. `2026-09-01T00:00:00Z`. |
| created_lte | – | – | Only events created at or before this instant. ISO 8601 with an offset, e.g. `2026-09-10T00:00:00Z`. |
| ending_before | – | – | Catch up: return events NEWER than this id. Pass the newest id you have already handled to see only what has happened since. This is the one to poll with. |
| event_type | – | – | Filter to exactly one event type, e.g. `message.received`. Common ones: `message.sent`, `message.delivered`, `message.read`, `message.received`, `message.reacted`, `message.edited` (a text or caption… |
| event_types | – | – | Filter to several event types at once, e.g. `message.sent` and `message.delivered`. Same vocabulary as `event_type`. The API accepts at most 20. |
| limit | – | – | How many events to return, 1-100. Defaults to 25. |
| number_alias | – | – | Restrict results to one inbox by the alias it had when the event happened, so events from before a rename are missed. Use `number_id` to follow a number across renames. **Absent means every number**,… |
| number_id | – | – | Restrict results to one number by its `id` (`num_…`, as returned by `list_numbers`). It keeps matching the number's events after the number is renamed, unlike `number_alias`, which matches the alias… |
| request_id | – | – | Return only the events that came of one earlier call (`req_…`). A write tool's result carries `request_id` when the platform issued one; keep it and you can ask later what became of that send. |
| starting_after | – | – | Read further back: return events OLDER than this id. This is the one for walking a backlog, and the wrong one for noticing something new. |
Structured output declared, but exposes no named fields.
No examples provided.
list_groups List the groups a number belongs to ~261
List the WhatsApp groups this number is a member of. The list is built when the number connects: every group it belongs to is picked up then, whether or not anything has been said in it. A group joined since then is picked up from the join itself, without waiting for anyone to speak in it. `name` filters by group name. `include_left=true` also returns groups this number has left, which are otherwise hidden.
| Name | Type | Req | Description |
|---|---|---|---|
| cursor | – | – | Opaque cursor for the next page. Pass back the `cursor` from the previous response, with the same filters; omit it for the first page. |
| include_left | – | – | Include groups this number has left. Off by default, so a plain listing shows only groups the number is currently in. |
| limit | – | – | How many items to return, 1-200. Defaults to 50. |
| name | – | – | Only groups whose name matches. |
| number_alias | string | – | Which of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to… |
Structured output declared, but exposes no named fields.
No examples provided.
list_messages List messages in an inbox ~535
List messages for one number, newest first, received and sent. Each item says who it is from and to, which number it belongs to, its `direction`, `content_type`, `origin`, a short `preview`, `at`, `status` and `content_expired`. Mentions, transcription and full media detail are only on `get_message`, so fetch the one message you care about rather than paging for detail. To read a group, find its `grp_` id with `list_groups` and pass it as `group_id`. `contact_id` returns what that contact sent or received, which in a group includes what they said there. `direction` keeps only `inbound` or `outbound`. Filters combine: `group_id` with `contact_id` answers what one person said in one group. Ids belong to one number, so use the same `number_alias` you got them from: an id from another number answers not found. For the next page, pass back the `cursor` from the previous response together with the same filters. Content older than the plan's retention window comes back with `preview` empty and `content_expired` true. The message, its sender and its group stay listed for 12 months.
| Name | Type | Req | Description |
|---|---|---|---|
| contact_id | – | – | Only the messages this contact sent or received (`ct_…`, from `list_contacts`). In a group that includes what the contact said there. The contact must be one of this number's: an id from another numb… |
| cursor | – | – | Opaque cursor for the next page. Pass back the `cursor` from the previous response, with the same filters; omit it for the first page. |
| direction | – | – | Only messages the number received (`inbound`) or sent (`outbound`). Absent means both. |
| group_id | – | – | Only the messages of one group (`grp_…`, from `list_groups`). The group must be one of this number's: an id from another number answers not found. Can be combined with `contact_id`. |
| limit | – | – | How many items to return, 1-200. Defaults to 50. |
| number_alias | string | – | Which of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to… |
Structured output declared, but exposes no named fields.
No examples provided.
list_numbers List the organization's WhatsApp numbers ~208
List every WhatsApp number this organization has, with its status. Start here when you do not know which aliases exist. The main number is always `main`; extras carry the alias the customer chose, and that alias is what every other tool's `number_alias` expects. Each number also carries `id` (`num_…`), which never changes, even when the alias is renamed. Keep it if you need to recognise a number later: events carry the same value as `number_id`, and the other tools accept either one as `number_alias`. To find the numbers that need attention, pass `status`, for example `disconnected`. Only `connected` numbers can send. `status.at` is when the number entered its current state, which is how you tell a fresh disconnection from one that has been down for hours.
| Name | Type | Req | Description |
|---|---|---|---|
| status | – | – | Only numbers currently in this status, for example `disconnected` to find the numbers that need attention. |
Structured output declared, but exposes no named fields.
No examples provided.
mark_as_read Clear a conversation's unread backlog ~430
Mark a conversation's unread messages as read, without sending anything. Set exactly one recipient: `number`, `group_id`, or `contact_id`. This is independent of the automatic mark-as-read that already happens when you send, reply, react, edit, delete or start typing (the number also appears online first): use it to clear an unread badge on its own, for example when handing a conversation to a human who has already seen it. No message is sent and no `message.*` event is produced, but the sender sees the messages as read (blue ticks) on WhatsApp. Needs a plan that includes read receipts (BUSINESS and above). Without it this answers `payment_required: feature_not_available`, and the answer will not change by retrying.
| Name | Type | Req | Description |
|---|---|---|---|
| contact_id | – | – | Recipient contact id (`ct_…`), from `list_contacts`. A contact id belongs to one number: an id from one inbox does not address the same person in another. Set exactly one of `number`, `group_id` or `… |
| group_id | – | – | Recipient group id (`grp_…`), from `list_groups`. A group id belongs to one number: an id from one inbox does not address the same group in another. Set exactly one of `number`, `group_id` or `contac… |
| number | – | – | Recipient phone number in E.164 form, digits only, country code first (e.g. `5511999999999`). Set exactly one of `number`, `group_id` or `contact_id`. |
| number_alias | string | – | Which of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to… |
Structured output declared, but exposes no named fields.
No examples provided.
react_to_message React to a message with an emoji ~293
Attach an emoji reaction to a message, or remove one. Pass a single emoji character, e.g. `👍`. Passing an empty string removes the reaction this number previously left. A new emoji replaces this number's previous reaction rather than adding beside it; to bring the earlier one back, react with it again. Works on messages in either direction: reacting to something a customer sent is often a cheaper acknowledgement than a reply. The number first appears online and its unread messages in that conversation are marked as read, then the reaction is sent. Opening the conversation this way is automatic and uses no quota of its own. Needs a plan that includes reactions. On a plan that does not, this answers `payment_required: feature_not_available`, and the answer will not change by retrying.
| Name | Type | Req | Description |
|---|---|---|---|
| emoji | string | yes | A single emoji, for example `👍`. An empty string removes the reaction this number left before. |
| message_id | string | yes | Message id (`msg_…`), as returned by a send or by `list_messages`. |
| number_alias | string | – | Which of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to… |
Structured output declared, but exposes no named fields.
No examples provided.
refresh_contact Refresh a contact's WhatsApp name ~289
Ask WhatsApp for this contact's current name. Only the name is refreshed. The profile picture updates on its own the next time this number exchanges a message with the contact, and this does not change how messages reach them. It answers right away with `requested_at`; the refresh then runs in the background. Call `get_contact` and read `refresh`: when `completed_at` is set, `outcome` says what happened (`updated` means the name changed, `unchanged` means it was already current, `number_not_connected` means the number was offline, `unavailable` means WhatsApp did not answer). This is the one contact tool that is not read-only: it queries WhatsApp over the live connection and spends the organization's per-minute refresh budget, so it needs a key with contacts write access. Do not call it in a loop over a list. Refresh the one contact whose name looks stale.
| Name | Type | Req | Description |
|---|---|---|---|
| contact_id | string | yes | Contact id (`ct_…`), from `list_contacts`. |
| number_alias | string | – | Which of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to… |
Structured output declared, but exposes no named fields.
No examples provided.
reply_to_message Reply to a message in the same conversation ~398
Reply to an EARLIER message, quoting it, without naming a recipient. Use it to bring context into the conversation: when the conversation has moved on and your answer depends on something said a while ago (by the contact, by you or, in a group, by any participant). To answer the message you just received, do not use this tool: send a normal message with `send_text` and let the chat carry the context, as a person would. The recipient is worked out from the original: an inbound message is answered to its sender, an outbound one to whoever received it, and a group message to the group. The message must belong to the inbox named by `number_alias`; a `message_id` from a different number returns not found. Like a person opening the chat, the number first appears online and its unread messages in that conversation are marked as read, then the reply is sent. Opening the conversation this way is automatic and uses no quota of its own.
| Name | Type | Req | Description |
|---|---|---|---|
| idempotency_key | – | – | Any printable ASCII text you choose, 1 to 255 characters, for example the id of the event you are answering. Reusing it for the same number suppresses a duplicate if you retry. Without it, retrying a… |
| message_id | string | yes | Message id (`msg_…`), as returned by a send or by `list_messages`. |
| number_alias | string | – | Which of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to… |
| text | string | yes | The text of your reply, 1 to 4096 characters. |
Structured output declared, but exposes no named fields.
No examples provided.
send_calendar_event Send a calendar event ~927
Send a calendar event invitation. Set exactly one recipient: `number`, `group_id`, or `contact_id`. `start_at` and `end_at` are ISO 8601 **with an offset**, for example `2026-09-10T14:00:00Z`. A timestamp without one is rejected: the recipient's phone renders the event in their own timezone, so an ambiguous instant would show the wrong hour on their screen. When set, `end_at` must be after `start_at`; an event that ends before (or exactly when) it starts is rejected. `location` pins where it happens (`latitude` and `longitude`, with an optional `name` and `address`). `has_reminder` reminds guests, and `reminder_offset_sec` says how many seconds before the event; `extra_guests_allowed` lets guests bring extra people. To fix a mistake later (a typo, the description, a link), use `edit_calendar_event`: guests keep their answer. When the date, time or place change and guests must accept again, cancel the event with `cancel_calendar_event` and send a new one with this tool. The entry a guest added to their own calendar with the card's "Add to calendar" button never follows an edit or a cancel: it stays on the old date and adding again creates a second entry, so tell guests to delete the old one. To see who said they are coming, use `get_message_responses`.
| Name | Type | Req | Description |
|---|---|---|---|
| contact_id | – | – | Recipient contact id (`ct_…`), from `list_contacts`. A contact id belongs to one number: an id from one inbox does not address the same person in another. Set exactly one of `number`, `group_id` or `… |
| description | – | – | Details shown on the event, up to 2000 characters. |
| end_at | – | – | When the event ends. ISO 8601 with an offset, and later than `start_at`. |
| extra_guests_allowed | – | – | Set to true to let guests bring extra people. Off when left out. |
| group_id | – | – | Recipient group id (`grp_…`), from `list_groups`. A group id belongs to one number: an id from one inbox does not address the same group in another. Set exactly one of `number`, `group_id` or `contac… |
| has_reminder | – | – | Set to true to remind guests before the event. Off when left out. |
| idempotency_key | – | – | Any printable ASCII text you choose, 1 to 255 characters, for example the id of the event you are answering. Reusing it for the same number suppresses a duplicate if you retry. Without it, retrying a… |
| join_link | – | – | A link guests can open to join, for example a video call. |
| location | – | – | Where the event takes place: a map pin with an optional name and address. |
| name | string | yes | The event's title, up to 200 characters. |
| number | – | – | Recipient phone number in E.164 form, digits only, country code first (e.g. `5511999999999`). Set exactly one of `number`, `group_id` or `contact_id`. |
| number_alias | string | – | Which of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to… |
| quoted_message_id | – | – | Quote an earlier message (`msg_…`) so it appears above yours. Do this only when your text depends on something said a while ago, yours or theirs; do not quote the message you are answering right now,… |
| reminder_offset_sec | – | – | How many seconds before the event the reminder goes off, for example 600 for ten minutes. Only takes effect together with `has_reminder`. |
| start_at | string | yes | When the event starts. ISO 8601 with an offset, for example `2026-09-10T14:00:00Z`. A time without an offset is rejected. |
Structured output declared, but exposes no named fields.
No examples provided.
send_contact_card Send a contact card ~625
Send a contact card the recipient can save to their phone. Set exactly one recipient: `number`, `group_id`, or `contact_id`. `phones` takes plain E.164 numbers, 1 to 10 of them. `emails`, `organization`, `title` and `address` are optional extra fields on the card; `emails` allows up to 10 as well. A contact card cannot be edited after it is sent: `delete_message` is the only change for it.
| Name | Type | Req | Description |
|---|---|---|---|
| address | – | – | The postal address on the card, up to 500 characters. |
| contact_id | – | – | Recipient contact id (`ct_…`), from `list_contacts`. A contact id belongs to one number: an id from one inbox does not address the same person in another. Set exactly one of `number`, `group_id` or `… |
| display_name | string | yes | The name shown on the card, 1 to 200 characters. |
| emails | – | – | The email addresses on the card, up to 10. |
| group_id | – | – | Recipient group id (`grp_…`), from `list_groups`. A group id belongs to one number: an id from one inbox does not address the same group in another. Set exactly one of `number`, `group_id` or `contac… |
| idempotency_key | – | – | Any printable ASCII text you choose, 1 to 255 characters, for example the id of the event you are answering. Reusing it for the same number suppresses a duplicate if you retry. Without it, retrying a… |
| number | – | – | Recipient phone number in E.164 form, digits only, country code first (e.g. `5511999999999`). Set exactly one of `number`, `group_id` or `contact_id`. |
| number_alias | string | – | Which of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to… |
| organization | – | – | The company shown on the card, up to 200 characters. |
| phones | array | yes | The phone numbers on the card, 1 to 10, each in E.164 form with the country code first (e.g. `5511999999999`). |
| quoted_message_id | – | – | Quote an earlier message (`msg_…`) so it appears above yours. Do this only when your text depends on something said a while ago, yours or theirs; do not quote the message you are answering right now,… |
| title | – | – | The job title shown on the card, up to 100 characters. |
Structured output declared, but exposes no named fields.
No examples provided.
send_cta_button Send a message with a call-to-action link button ~628
Send an interactive message carrying one link button. Set exactly one recipient: `number`, `group_id`, or `contact_id`. A link button is the only interactive type WhatsApp accepts on this kind of connection. Reply buttons and list pickers are not available and will not become available, so do not try to emulate them. `body` is the text above the button (up to 1024 characters), `button_text` its label (up to 20), `header` and `footer` optional short lines above and below (up to 60 each). A message with a link button cannot be edited after it is sent: `delete_message` is the only change for it.
| Name | Type | Req | Description |
|---|---|---|---|
| body | string | yes | The text above the button, 1 to 1024 characters. |
| button_text | string | yes | The label on the button, 1 to 20 characters. |
| button_url | string | yes | The link the button opens when the recipient taps it. |
| contact_id | – | – | Recipient contact id (`ct_…`), from `list_contacts`. A contact id belongs to one number: an id from one inbox does not address the same person in another. Set exactly one of `number`, `group_id` or `… |
| footer | – | – | A short line below the text, up to 60 characters. |
| group_id | – | – | Recipient group id (`grp_…`), from `list_groups`. A group id belongs to one number: an id from one inbox does not address the same group in another. Set exactly one of `number`, `group_id` or `contac… |
| header | – | – | A short line above the text, 1 to 60 characters. |
| idempotency_key | – | – | Any printable ASCII text you choose, 1 to 255 characters, for example the id of the event you are answering. Reusing it for the same number suppresses a duplicate if you retry. Without it, retrying a… |
| number | – | – | Recipient phone number in E.164 form, digits only, country code first (e.g. `5511999999999`). Set exactly one of `number`, `group_id` or `contact_id`. |
| number_alias | string | – | Which of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to… |
| quoted_message_id | – | – | Quote an earlier message (`msg_…`) so it appears above yours. Do this only when your text depends on something said a while ago, yours or theirs; do not quote the message you are answering right now,… |
Structured output declared, but exposes no named fields.
No examples provided.
send_location Send a map location ~547
Send a location pin. Set exactly one recipient: `number`, `group_id`, or `contact_id`. `latitude` is between -90 and 90, `longitude` between -180 and 180. `name` and `address` label the pin; `url` adds a link beside it. A location cannot be edited after it is sent: `delete_message` is the only change for it.
| Name | Type | Req | Description |
|---|---|---|---|
| address | – | – | The place's address, up to 500 characters. |
| contact_id | – | – | Recipient contact id (`ct_…`), from `list_contacts`. A contact id belongs to one number: an id from one inbox does not address the same person in another. Set exactly one of `number`, `group_id` or `… |
| group_id | – | – | Recipient group id (`grp_…`), from `list_groups`. A group id belongs to one number: an id from one inbox does not address the same group in another. Set exactly one of `number`, `group_id` or `contac… |
| idempotency_key | – | – | Any printable ASCII text you choose, 1 to 255 characters, for example the id of the event you are answering. Reusing it for the same number suppresses a duplicate if you retry. Without it, retrying a… |
| latitude | number | yes | Latitude, between -90 and 90. |
| longitude | number | yes | Longitude, between -180 and 180. |
| name | – | – | A name for the place, up to 200 characters. |
| number | – | – | Recipient phone number in E.164 form, digits only, country code first (e.g. `5511999999999`). Set exactly one of `number`, `group_id` or `contact_id`. |
| number_alias | string | – | Which of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to… |
| quoted_message_id | – | – | Quote an earlier message (`msg_…`) so it appears above yours. Do this only when your text depends on something said a while ago, yours or theirs; do not quote the message you are answering right now,… |
| url | – | – | A link shown beside the pin. |
Structured output declared, but exposes no named fields.
No examples provided.
send_media Send an image, video, audio, document or sticker ~765
Send media by URL: an image, video, audio clip, document or sticker. Set exactly one recipient: `number`, `group_id`, or `contact_id`. `url` must still be reachable when the send happens: Turbo Notify fetches the bytes from it. A copy is kept in the organization's own object storage afterwards when that is configured, which never blocks the send and is not required for one. `caption` applies to `image`, `video` and `document` only; audio and stickers have nowhere to render one. `filename` applies to `document` only. Pairing either with a kind that cannot carry it is rejected here, before anything is sent. After sending, only the caption of an image, video or document can be changed, with `edit_media_caption`. The file itself, an audio clip and a sticker cannot be edited: `delete_message` is the only change for them. `mime_type` is optional and does not change how the message is sent. The type WhatsApp receives comes from what the URL's own server serves, so point `url` at a file that server labels correctly.
| Name | Type | Req | Description |
|---|---|---|---|
| caption | – | – | Text shown with an image, video or document, up to 1024 characters. Audio and stickers cannot carry one. |
| contact_id | – | – | Recipient contact id (`ct_…`), from `list_contacts`. A contact id belongs to one number: an id from one inbox does not address the same person in another. Set exactly one of `number`, `group_id` or `… |
| filename | – | – | The file name the recipient sees on a document, up to 255 characters. Documents only. |
| group_id | – | – | Recipient group id (`grp_…`), from `list_groups`. A group id belongs to one number: an id from one inbox does not address the same group in another. Set exactly one of `number`, `group_id` or `contac… |
| idempotency_key | – | – | Any printable ASCII text you choose, 1 to 255 characters, for example the id of the event you are answering. Reusing it for the same number suppresses a duplicate if you retry. Without it, retrying a… |
| kind | – | yes | What the file is: image, video, audio, document or sticker. |
| mime_type | – | – | The media's MIME type, recorded alongside the message. It does not change how the file is sent: the type WhatsApp receives comes from what the URL's own server serves. Optional. |
| number | – | – | Recipient phone number in E.164 form, digits only, country code first (e.g. `5511999999999`). Set exactly one of `number`, `group_id` or `contact_id`. |
| number_alias | string | – | Which of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to… |
| quoted_message_id | – | – | Quote an earlier message (`msg_…`) so it appears above yours. Do this only when your text depends on something said a while ago, yours or theirs; do not quote the message you are answering right now,… |
| url | string | yes | Link to the file to send. It must still be reachable when the message goes out. |
Structured output declared, but exposes no named fields.
No examples provided.
send_text Send a text message ~636
Send a WhatsApp text message. Set exactly one recipient: `number`, `group_id`, or `contact_id`. Writing `@<number>` in the text mentions that person, for example `@5511999999999`. The platform detects it automatically; there is no separate mentions argument. This is also how to answer the message you just received: a normal message to its sender, as a person does in a chat, with no quote. Quote (`quoted_message_id`, or `reply_to_message`) only an earlier message that your answer depends on. A text message you sent can be corrected later with `edit_text_message`. Like a person opening the chat, the number first appears online and its unread messages in that conversation are marked as read, then the message is sent. Opening the conversation this way is automatic and uses no quota of its own. Returns the new `message_id` and its initial status. Delivery happens asynchronously; poll `get_message_status` or watch `list_events` for the outcome.
| Name | Type | Req | Description |
|---|---|---|---|
| contact_id | – | – | Recipient contact id (`ct_…`), from `list_contacts`. A contact id belongs to one number: an id from one inbox does not address the same person in another. Set exactly one of `number`, `group_id` or `… |
| group_id | – | – | Recipient group id (`grp_…`), from `list_groups`. A group id belongs to one number: an id from one inbox does not address the same group in another. Set exactly one of `number`, `group_id` or `contac… |
| idempotency_key | – | – | Any printable ASCII text you choose, 1 to 255 characters, for example the id of the event you are answering. Reusing it for the same number suppresses a duplicate if you retry. Without it, retrying a… |
| number | – | – | Recipient phone number in E.164 form, digits only, country code first (e.g. `5511999999999`). Set exactly one of `number`, `group_id` or `contact_id`. |
| number_alias | string | – | Which of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to… |
| quoted_message_id | – | – | Quote an earlier message (`msg_…`) so it appears above yours. Do this only when your text depends on something said a while ago, yours or theirs; do not quote the message you are answering right now,… |
| text | string | yes | The message text, 1 to 4096 characters. Write `@<number>` to mention someone. |
Structured output declared, but exposes no named fields.
No examples provided.
send_typing_indicator Show the typing indicator in a conversation ~525
Show "typing…" to a recipient while you prepare an answer. Set exactly one recipient: `number`, `group_id`, or `contact_id`. Useful before a reply that takes a few seconds to compose, so the person on the other end sees something is happening. It expires on its own, so clearing it is optional: pass `is_typing=false` only if you decide not to answer after all and want the indicator gone at once. There is no duration argument. WhatsApp decides how long it lives. Starting to type also opens the conversation: the number appears online, its unread messages in that conversation are marked as read, and after a short pause "typing…" appears, so it never shows over unread messages. Stopping (`is_typing=false`) only clears the indicator and reads nothing. Opening the conversation this way is automatic and uses no quota of its own. Needs a plan that includes the typing indicator, and showing it in a group needs one that includes group messaging as well. Without either, this answers `payment_required: feature_not_available`, and the answer will not change by retrying.
| Name | Type | Req | Description |
|---|---|---|---|
| contact_id | – | – | Recipient contact id (`ct_…`), from `list_contacts`. A contact id belongs to one number: an id from one inbox does not address the same person in another. Set exactly one of `number`, `group_id` or `… |
| group_id | – | – | Recipient group id (`grp_…`), from `list_groups`. A group id belongs to one number: an id from one inbox does not address the same group in another. Set exactly one of `number`, `group_id` or `contac… |
| is_typing | boolean | – | `true` shows "typing…" (the default), `false` clears it. |
| number | – | – | Recipient phone number in E.164 form, digits only, country code first (e.g. `5511999999999`). Set exactly one of `number`, `group_id` or `contact_id`. |
| number_alias | string | – | Which of the organization's WhatsApp numbers this acts on: `main`, the alias of an extra number, or the number's `id` (`num_…`), which stays the same when the alias is renamed. Call `list_numbers` to… |
Structured output declared, but exposes no named fields.
No examples provided.
How do I install the Turbo Notify: WhatsApp for AI agents MCP server?
Turbo Notify: WhatsApp for AI agents is a hosted endpoint at https://mcp.turbonotify.com/, so there is nothing to install locally. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.
remote · mcp.turbonotify.com
claude mcp add --transport http com-turbonotify-whatsapp 'https://mcp.turbonotify.com/'
What is the Turbo Notify: WhatsApp for AI agents MCP server?
Turbo Notify: WhatsApp for AI agents is an MCP server listed in the public MCP registry as com.turbonotify/whatsapp. Send and receive WhatsApp messages from your AI agent, on your own number, with Turbo Notify. This page covers its hosted endpoint (https://mcp.turbonotify.com).
Is the Turbo Notify: WhatsApp for AI agents MCP server safe to use?
Turbo Notify: WhatsApp for AI agents scores 77 out of 100 on VerifyMCP. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.
What tools does the Turbo Notify: WhatsApp for AI agents MCP server expose?
Turbo Notify: WhatsApp for AI agents exposes 36 tools: send_text, send_media, send_location, send_contact_card, send_calendar_event, and 31 more. Their descriptions and schemas cost roughly 14,572 tokens of context every time the server is loaded.
Does the Turbo Notify: WhatsApp for AI agents MCP server require authentication?
Yes. Turbo Notify: WhatsApp for AI agents asked us for credentials when we connected, so you will need to authorise it in your MCP client before it can do anything.
Is the Turbo Notify: WhatsApp for AI agents MCP server still maintained?
Turbo Notify: WhatsApp for AI agents is still listed as active in the MCP registry. We last reached this channel on 4 November 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.