Support Tools
The support inbox holds one durable conversation per member and channel, the saved replies a team answers with, and the project's support settings.
The support inbox holds one durable conversation per member and channel, the saved replies a team answers with, and the project's support settings. These tools triage and answer conversations, keep the reply picker in sync and switch the inbox's behaviour, the same actions the dashboard inbox runs.
Tools
assign_support_conversationAssign Support ConversationDESTRUCTIVEblock_support_contactBlock Support ContactDESTRUCTIVEcreate_canned_replyCreate Canned ReplyDESTRUCTIVEdelete_canned_replyDelete Canned ReplyREADget_canned_replyGet Canned ReplyREADget_support_conversationGet Support ConversationREADget_support_settingsGet Support SettingsREADlist_canned_repliesList Canned RepliesREADlist_support_conversationsList Support ConversationsDESTRUCTIVEreopen_support_conversationReopen Support ConversationDESTRUCTIVEreply_support_conversationReply to Support ConversationDESTRUCTIVEresolve_support_conversationResolve Support ConversationDESTRUCTIVEunblock_support_contactUnblock Support ContactDESTRUCTIVEupdate_canned_replyUpdate Canned ReplyDESTRUCTIVEupdate_support_settingsUpdate Support Settingsassign_support_conversation
DESTRUCTIVEHand a support thread to one team member, or take it back off everyone. Advisory — it never stops anyone else replying.
Set who owns the answer on a thread. Assignment feeds the Assigned to Me tab in the creator's inbox and says who is responsible; it does not lock the thread, and anyone on the team with support-conversation:update can still reply.
The assignee must be someone who can actually open the thread: the project owner, or a member of the team the project belongs to. Any other account is refused rather than stored, so a token can never park a thread on a user who would never see it. Omit assignee_user_id, or pass null, to clear the assignment.
Emits support.conversation.assigned on every call, with assigned_to_user_id: null when the assignment was cleared.
Idempotent in effect, not in events. Assigning the same person twice leaves
the row exactly as it was, but the event fires again each time — deduplicate
on the event id if you post notifications downstream.
Requires ability
The token behind the MCP session must hold it, or the call is refused with TOKEN_MISSING_ABILITY.
Runs the same action as
The REST endpoint and this tool share one action, so validation, permissions and events are identical.
Fires one event
Delivered to every endpoint subscribed to it once the change is made.
Annotations
A client that honours annotations asks a person before running it. Sending the same arguments twice changes nothing the second time.
Arguments
conversation_id*stringUUID of the support conversation to assign.
assignee_user_idstringoptionalUUID of the project owner or a team member to hand the thread to. Omit or pass null to unassign.
What it returns
{ "data": { "id": "9e042b6f-5d81-4c37-a920-7b3e18cf6d45", "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13", "channel": "telegram", "status": "open", "assigned_to_user_id": "4b7c9d21-3e58-4f16-8a02-6d9e5c1b7f34", "unread_count": 2, "blocked": false, "first_response_at": null, "resolved_at": null }}The same row get_support_conversation returns under its conversation key, so a thread reads the same before and after the change. assigned_to_user_id is a team member's user id — a different namespace from the member's project_user_id.
How it fails
VALIDATION_FAILEDassignee_user_id is not a UUID or names no account (No user found with that id.), or the account is neither the project owner nor on its team (That person is not on this project's team.). Also returned when the token's owner is on the team but their role lacks the support permission on the project.
RESOURCE_NOT_FOUNDunknown conversation_id, another creator's thread, or a project outside the token's scope:project: allow-list. The three are indistinguishable on purpose.
AUTHENTICATION_REQUIREDno authenticated user on the request.
TOKEN_MISSING_ABILITYtoken lacks support-conversation:update.
Related
block_support_contact
DESTRUCTIVEDrop every further support message from the member behind a thread. They get no indication, and their subscription is untouched.
Stop a member's support traffic. Everything they send from now on is dropped at ingestion, before it reaches the inbox; nothing is queued and nothing is stored. Their history stays on the thread.
The block lives on the thread, not on the member, so it silences support only. The member keeps their subscription, their group access and every other bot interaction. To take access away, call kick_member or ban_member instead — blocking is for someone who is abusing the inbox, not someone who should no longer be a member.
Emits support.conversation.blocked when the block is placed. Idempotent: blocking an already-blocked member changes nothing and emits nothing.
Blocking does not resolve the thread. It stays in whatever status it had, so
call resolve_support_conversation
as well if it should leave the open queue. A blocked member's messages can
never reopen it; only
reopen_support_conversation can.
Requires ability
The token behind the MCP session must hold it, or the call is refused with TOKEN_MISSING_ABILITY.
Runs the same action as
The REST endpoint and this tool share one action, so validation, permissions and events are identical.
Fires one event
Delivered to every endpoint subscribed to it once the change is made.
Annotations
A client that honours annotations asks a person before running it. Sending the same arguments twice changes nothing the second time.
Arguments
conversation_id*stringUUID of the support conversation whose member to block.
What it returns
{ "data": { "id": "9e042b6f-5d81-4c37-a920-7b3e18cf6d45", "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13", "channel": "telegram", "status": "open", "assigned_to_user_id": null, "unread_count": 3, "blocked": true, "first_response_at": null, "resolved_at": null }}blocked: true is the only field this call changes. The unread count stays as it was — the messages already received are still there to read.
How it fails
VALIDATION_FAILEDthe token's owner is on the project's team but their role lacks the support permission on it.
RESOURCE_NOT_FOUNDunknown conversation_id, another creator's thread, or a project outside the token's scope:project: allow-list.
AUTHENTICATION_REQUIREDno authenticated user on the request.
TOKEN_MISSING_ABILITYtoken lacks support-conversation:update.
Related
create_canned_reply
DESTRUCTIVESave a reusable support reply on a project, with an optional slash-command shortcut and picker position.
Add a snippet to a project's saved replies. It appears in the thread composer's picker straight away, and a creator can pull it in by typing its shortcut. The text is validated against the same rules the dashboard form applies, so a snippet accepted here renders in the composer exactly as one saved from the inbox.
Synchronous — the new row is returned, and support.canned_reply.created emits once.
Not idempotent
Two calls with the same title and body save two snippets. Only shortcut
is unique within a project, so a snippet without one can be duplicated freely.
Check list_canned_replies before creating.
Requires ability
The token behind the MCP session must hold it, or the call is refused with TOKEN_MISSING_ABILITY.
Runs the same action as
The REST endpoint and this tool share one action, so validation, permissions and events are identical.
Fires one event
Delivered to every endpoint subscribed to it once the change is made.
Annotations
A client that honours annotations asks a person before running it. It reaches beyond Subscriby: a connector, a provider or a member.
Arguments
project_id*stringUUID of the project the snippet belongs to.
title*stringShort label shown in the picker, 2 to 80 characters.
body*stringThe reply text, 2 to 4000 characters.
shortcutstringoptionalSlash-command a creator types to insert the snippet: letters, numbers, dashes and underscores, up to 30 characters, unique within the project.
sort_orderintegeroptionalPosition in the picker, 0 to 999. Defaults to 0.
0max999What it returns
{ "data": { "id": "5d2f8a71-3c9e-4b06-a8f4-1e7c9d2b6a35", "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13", "title": "Refund policy", "body": "Refunds are available within 14 days of your first payment. Reply here with the email you paid with and we'll sort it.", "shortcut": "refund", "sort_order": 0, "created_at": "2026-09-06T10:05:00+00:00", "updated_at": "2026-09-06T10:05:00+00:00" }}title comes back trimmed. body is stored as sent, whitespace included, because it reaches members verbatim. An omitted or empty shortcut is stored as null.
How it fails
VALIDATION_FAILEDtitle outside 2–80 characters, body outside 2–4000, shortcut longer than 30 characters, containing anything but letters, numbers, dashes and underscores, or already used by another snippet in this project, or sort_order outside 0–999. The envelope names the offending field. Also returned when the token's owner is on the project's team but their role lacks the support permission on it.
RESOURCE_NOT_FOUNDproject_id names a project the token cannot see: unknown, another team's, or outside the token's scope:project: allow-list.
AUTHENTICATION_REQUIREDno authenticated user on the request.
TOKEN_MISSING_ABILITYtoken lacks support-canned-reply:create.
delete_canned_reply
DESTRUCTIVERemove a saved support reply from a project's picker. Replies already sent with it are untouched.
Take a snippet out of the picker for good. Messages that were sent using it are ordinary messages on their threads and are not affected — a snippet is a template, not a link.
Confirm before calling
There is no undo and no soft delete. Confirm the target canned_reply_id with
a human — read it back with get_canned_reply
so they see the text they are losing. The tool is annotated destructive so a
client can prompt for confirmation.
Emits support.canned_reply.deleted with a snapshot of the snippet taken before it went. Idempotent in the only sense a delete can be: a second call for the same id is RESOURCE_NOT_FOUND, indistinguishable from an id that never existed.
Requires ability
The token behind the MCP session must hold it, or the call is refused with TOKEN_MISSING_ABILITY.
Runs the same action as
The REST endpoint and this tool share one action, so validation, permissions and events are identical.
Fires one event
Delivered to every endpoint subscribed to it once the change is made.
Annotations
A client that honours annotations asks a person before running it. Sending the same arguments twice changes nothing the second time.
Arguments
project_id*stringUUID of the project the snippet belongs to.
canned_reply_id*stringUUID of the saved reply to remove.
What it returns
{ "data": { "canned_reply_id": "5d2f8a71-3c9e-4b06-a8f4-1e7c9d2b6a35", "deleted": true }}The id is echoed as sent. Nothing else about the snippet is returned, so read it first if the text matters.
How it fails
VALIDATION_FAILEDthe token's owner is on the project's team but their role lacks the support permission on it.
RESOURCE_NOT_FOUNDproject_id names a project the token cannot see, or canned_reply_id is unknown, already deleted, or belongs to another project.
AUTHENTICATION_REQUIREDno authenticated user on the request.
TOKEN_MISSING_ABILITYtoken lacks support-canned-reply:delete.
get_canned_reply
READFetch one saved support reply by UUID, looked up within its project.
Read a single snippet — the full body, its shortcut and its position — when you already know which one. Same row list_canned_replies returns, so reading one and reading all agree field for field.
Saved replies exist only beneath a project, so the tool takes both ids and
resolves the snippet within that project. A snippet id that belongs to a
different project is RESOURCE_NOT_FOUND here even if the token could see
that other project.
Requires ability
The token behind the MCP session must hold it, or the call is refused with TOKEN_MISSING_ABILITY.
Runs the same action as
The REST endpoint and this tool share one action, so validation, permissions and events are identical.
Annotations
It reads and never changes anything.
Arguments
project_id*stringUUID of the project the snippet belongs to.
canned_reply_id*stringUUID of the saved reply to fetch.
What it returns
{ "data": { "id": "5d2f8a71-3c9e-4b06-a8f4-1e7c9d2b6a35", "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13", "title": "Opening hours", "body": "We answer between 9 and 5, Monday to Friday. Anything sent outside that gets a reply the next working morning.", "shortcut": "hours", "sort_order": 1, "created_at": "2026-06-02T09:14:02+00:00", "updated_at": "2026-06-02T09:14:02+00:00" }}updated_at equal to created_at means the snippet has never been edited.
How it fails
RESOURCE_NOT_FOUNDproject_id names a project the token cannot see, or canned_reply_id is unknown, deleted, or belongs to another project.
AUTHENTICATION_REQUIREDno authenticated user on the request.
TOKEN_MISSING_ABILITYtoken lacks support-canned-reply:view-any.
Read one support conversation with its message history and the member context a reply needs.
Open a single conversation. Returns the thread's state, its message history, and a flattened snapshot of who the member is — subscription status, current plan, member-since date, how many messages they have sent — so a reply can be written without a second round of lookups.
Names, emails and message bodies are returned verbatim. This is the most PII-dense tool in the set. Do not forward its output anywhere outside the conversation with the creator.
Requires ability
The token behind the MCP session must hold it, or the call is refused with TOKEN_MISSING_ABILITY.
Runs the same action as
The REST endpoint and this tool share one action, so validation, permissions and events are identical.
Annotations
It reads and never changes anything.
Arguments
conversation_id*stringUUID of the support conversation to read.
message_limitintegeroptionalHow many of the most recent messages to return (1..200, default 50). Returned oldest-first.
1max200include_internalbooleanoptionalInclude creator-only internal notes. Requires the support-conversation:update ability.
What it returns
{ "data": { "conversation": { "id": "9e042b6f-5d81-4c37-a920-7b3e18cf6d45", "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13", "channel": "telegram", "status": "open", "assigned_to_user_id": null, "unread_count": 2, "blocked": false, "first_response_at": null, "resolved_at": null }, "member": { "project_user_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80", "name": "Jane Doe", "email": "[email protected]", "status": "active", "member_since": "2026-03-02T09:00:00Z", "plan_name": "Premium Monthly", "subscription_status": "active", "subscription_ends_at": "2026-09-02T09:00:00Z", "subscription_count": 1, "inbound_message_count": 4, "first_contact_at": "2026-08-20T10:05:00Z" }, "messages": [ { "id": "6c18f7a3-2e95-4d60-b47a-c093e5182b7f", "direction": "inbound", "author_kind": "contact", "type": "text", "delivery_status": "sent", "internal": false, "body": "My invite link expired before I could join", "attachment_kinds": [], "created_at": "2026-08-20T10:05:00Z" } ] }, "meta": { "message_count": 1, "message_limit": 50, "internal_included": false }}How it fails
TOKEN_MISSING_ABILITYtoken lacks support-conversation:view.
No support conversation found with that id. — unknown id, or the conversation belongs to a project outside the token's scope.
Reading internal notes requires the support-conversation:update ability. — include_internal was true on a read-only token.
Caveats
- Internal notes are gated behind a write ability on purpose. Reading a private remark about a member takes the same permission as writing one, so a read-only token cannot see them.
- Attachments are described by kind only (
attachment_kinds: ["photo"]). Platformfile_idvalues are effectively download credentials and are never returned. Fetch files through the dashboard or the REST API. messagesis the newestmessage_limitmessages, returned oldest-first so it reads as a transcript. A long thread is truncated at the start, not the end.member.statusis the project-scoped member status — it can beleadfor someone who has never paid. Anyone who can reach the bot can open a conversation.first_response_at: nullmeans nobody has replied yet. It is stamped once, on the first human reply ever, and is not reset by a reopen.
Read a project's support inbox settings — enabled, relay mode, agent name, auto-reply and email notifications.
Read how a project's member support is configured: whether members can open threads at all, where new threads are relayed besides the dashboard inbox, the name members see on replies, the acknowledgement sent when a thread opens, and whether the creator is emailed about new threads.
The settings are columns on the project, so reading them takes only the project view ability — no support ability is needed to see how support is set up.
The connector relay chat id is never part of the row. It is an identifier the bot handshake writes when the creator links their account, not a setting a client should read or set.
Requires ability
The token behind the MCP session must hold it, or the call is refused with TOKEN_MISSING_ABILITY.
Runs the same action as
The REST endpoint and this tool share one action, so validation, permissions and events are identical.
Annotations
It reads and never changes anything.
Arguments
project_id*stringUUID of the project whose support settings to read.
What it returns
{ "data": { "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13", "enabled": true, "relay_mode": "owner_dm", "agent_name": "Team Subscriby", "auto_reply": "Thanks — we usually reply within a few hours.", "notify_email": false, "updated_at": "2026-08-11T15:40:19+00:00" }}relay_mode is owner_dm (each new thread is forwarded to the creator on their connector) or none (dashboard inbox only). agent_name: null means replies carry the project name; auto_reply: null means no acknowledgement is sent. updated_at is the project's timestamp — it moves whenever anything on the project changes, not only these settings.
How it fails
RESOURCE_NOT_FOUNDproject_id names a project the token cannot see: unknown, another team's, or outside the token's scope:project: allow-list.
AUTHENTICATION_REQUIREDno authenticated user on the request.
TOKEN_MISSING_ABILITYtoken lacks project:view.
List a project's saved support replies in the order the creator arranged them, shortcut and body included.
Read the snippets a creator has saved for the questions they answer constantly. Each row carries the full body, the shortcut a creator types in the thread composer to pull the snippet in, and its sort_order — the position in the picker.
Call it before reply_support_conversation so an answer goes out in the creator's own wording rather than a paraphrase. Rows come back sorted by sort_order, then title, exactly as the picker shows them.
Saved replies are authorised with the support-conversation permissions, not permissions of their own: a team member who can read the inbox can read the snippets used to answer it.
Requires ability
The token behind the MCP session must hold it, or the call is refused with TOKEN_MISSING_ABILITY.
Runs the same action as
The REST endpoint and this tool share one action, so validation, permissions and events are identical.
Annotations
It reads and never changes anything.
Arguments
project_id*stringUUID of the project whose saved replies to list.
What it returns
{ "data": [ { "id": "5d2f8a71-3c9e-4b06-a8f4-1e7c9d2b6a35", "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13", "title": "Refund policy", "body": "Refunds are available within 14 days of your first payment. Reply here with the email you paid with and we'll sort it.", "shortcut": "refund", "sort_order": 0, "created_at": "2026-06-02T09:14:02+00:00", "updated_at": "2026-08-11T15:40:19+00:00" } ], "meta": { "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13", "total": 4 }}shortcut is null for a snippet saved without one. The list is not paginated — total is the whole set, and a project with no saved replies returns an empty data array, not an error.
How it fails
RESOURCE_NOT_FOUNDproject_id names a project the token cannot see: unknown, another team's, or outside the token's scope:project: allow-list.
AUTHENTICATION_REQUIREDno authenticated user on the request.
TOKEN_MISSING_ABILITYtoken lacks support-canned-reply:view-any.
List member support conversations, newest activity first, with optional status / assignee / unread filters.
Triage the support inbox. Returns one row per conversation, newest activity first, each carrying the member's name, unread count and a preview of the last message — enough to decide what needs answering without a follow-up call per row.
Use get_support_conversation once you know which thread to open.
Member names and message previews are returned verbatim. Scrub them before forwarding anywhere outside the conversation with the creator.
Requires ability
The token behind the MCP session must hold it, or the call is refused with TOKEN_MISSING_ABILITY.
Runs the same action as
The REST endpoint and this tool share one action, so validation, permissions and events are identical.
Annotations
It reads and never changes anything.
Arguments
project_idstringoptionalOptional project UUID to narrow the result.
statusstringoptionalConversation status filter. One of: open, pending, snoozed, resolved
openpendingsnoozedresolvedassigned_tostringoptionalOnly conversations assigned to this team-member user UUID.
unread_onlybooleanoptionalOnly conversations with messages the creator has not opened.
limitintegeroptionalMaximum conversations to return per page (1..100).
1max100pageintegeroptional1-indexed page number.
1What it returns
{ "data": [ { "id": "9e042b6f-5d81-4c37-a920-7b3e18cf6d45", "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13", "subscriber_id": "2a91c4e7-6f38-4b52-8e0d-9c1a7b3f5d80", "member_name": "Jane Doe", "channel": "telegram", "status": "open", "assigned_to_user_id": null, "unread_count": 2, "blocked": false, "last_message_at": "2026-08-20T10:05:00Z", "last_message_preview": "My invite link expired before I could join" } ], "meta": { "page": 1, "limit": 25, "total": 7, "has_more": false }}How it fails
TOKEN_MISSING_ABILITYtoken lacks support-conversation:view-any.
An empty data array is not an error. It means nothing matched, most often because status defaulted the caller's expectation — resolved threads are excluded only if you filter for open.
Caveats
last_message_previewis the raw last message body, which isnullfor a media message with no caption. Anullpreview does not mean an empty conversation.- Results span every project the token can reach unless you pass
project_id. blocked: truemeans inbound messages from that member are being dropped. The thread is history only.
reopen_support_conversation
DESTRUCTIVEPut a resolved support thread back in the creator's open queue so it shows in the triage list again.
Reopen a thread by hand. It goes back to open, resolved_at is cleared, and it competes for the creator's attention again. The reverse of resolve_support_conversation.
A member writing again reopens their own thread without this, so call it only when the creator wants to follow up first — a refund that turned out to be wrong, an answer that needs a correction. It is also the only way back for a thread whose member is blocked: their messages are dropped, so they can never reopen it themselves.
The row is left alone when the thread is already open, but
support.conversation.reopened
fires on every call — the same event the member's own message would raise, so
a consumer cannot tell a manual reopen from an inbound one. Deduplicate on the
event id if you post notifications downstream.
Requires ability
The token behind the MCP session must hold it, or the call is refused with TOKEN_MISSING_ABILITY.
Runs the same action as
The REST endpoint and this tool share one action, so validation, permissions and events are identical.
Fires one event
Delivered to every endpoint subscribed to it once the change is made.
Annotations
A client that honours annotations asks a person before running it. Sending the same arguments twice changes nothing the second time.
Arguments
conversation_id*stringUUID of the support conversation to reopen.
What it returns
{ "data": { "id": "9e042b6f-5d81-4c37-a920-7b3e18cf6d45", "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13", "channel": "telegram", "status": "open", "assigned_to_user_id": null, "unread_count": 0, "blocked": false, "first_response_at": "2026-08-20T10:12:00+00:00", "resolved_at": null }}first_response_at survives the reopen — it is stamped once, on the first human reply ever, and never reset. unread_count is not touched either: reopening does not pretend the member wrote something new.
How it fails
VALIDATION_FAILEDthe token's owner is on the project's team but their role lacks the support permission on it.
RESOURCE_NOT_FOUNDunknown conversation_id, another creator's thread, or a project outside the token's scope:project: allow-list.
AUTHENTICATION_REQUIREDno authenticated user on the request.
TOKEN_MISSING_ABILITYtoken lacks support-conversation:update.
Related
reply_support_conversation
DESTRUCTIVESend a reply to a member in a support conversation, or record a private internal note.
Reply to a member. The message is recorded against the conversation and queued for delivery on the member's channel, prefixed with the project's support name so it reads as coming from a person rather than from the bot.
Set internal to record a private note for the creator's team instead. Internal notes are never delivered, never appear to the member, and raise no webhook event.
Requires ability
The token behind the MCP session must hold it, or the call is refused with TOKEN_MISSING_ABILITY.
Runs the same action as
The REST endpoint and this tool share one action, so validation, permissions and events are identical.
Fires one event
Delivered to every endpoint subscribed to it once the change is made.
Annotations
A client that honours annotations asks a person before running it.
Arguments
conversation_id*stringUUID of the support conversation to reply in.
body*stringThe reply text, max 4000 characters. Reaches the member verbatim.
internalbooleanoptionalRecord a creator-only note instead of sending to the member.
reply_to_message_idstringoptionalOptional. UUID of a message in this same conversation to quote above the reply, the way a chat client shows a threaded reply.
What it returns
{ "data": { "message_id": "6c18f7a3-2e95-4d60-b47a-c093e5182b7f", "conversation_id": "9e042b6f-5d81-4c37-a920-7b3e18cf6d45", "internal": false, "delivery_status": "pending" }}How it fails
TOKEN_MISSING_ABILITYtoken lacks support-conversation:update.
No support conversation found with that id. — unknown id, or outside the token's project scope.
A reply needs a body. — body was empty or whitespace only.
A reply may not be longer than 4000 characters. — the connector's message ceiling.
Caveats
delivery_status: "pending"means queued, not delivered. Delivery runs on a queue and can still fail — a member who has blocked the bot comes back asunreachable. Read the message back withget_support_conversationif the outcome matters.- Replying to a resolved conversation does not reopen it. Only an inbound member message does that.
- A reply does not clear the unread count or resolve the thread. Call
resolve_support_conversationseparately when the matter is closed. - Only text is supported here. Sending media takes the dashboard inbox.
reply_to_message_idmust name a message in the same conversation. Anything else is refused rather than silently dropped, so a quote can never surface one member's words in another member's thread.- The reply is attributed to the token's owner. On a token minted for automation, that is the account the token belongs to — not the AI.
resolve_support_conversation
DESTRUCTIVEMark a support conversation resolved, clearing it from the creator's open queue.
Mark a conversation resolved. It leaves the open triage queue and stops competing for the creator's attention.
Not destructive. The thread and its full history are kept, and it reopens by itself the moment the member writes again. Resolve only what has actually been answered — a resolved thread stops showing in the creator's triage list.
Requires ability
The token behind the MCP session must hold it, or the call is refused with TOKEN_MISSING_ABILITY.
Runs the same action as
The REST endpoint and this tool share one action, so validation, permissions and events are identical.
Fires one event
Delivered to every endpoint subscribed to it once the change is made.
Annotations
A client that honours annotations asks a person before running it.
Arguments
conversation_id*stringUUID of the support conversation to resolve.
What it returns
{ "data": { "conversation_id": "9e042b6f-5d81-4c37-a920-7b3e18cf6d45", "status": "resolved", "resolved_at": "2026-08-20T10:12:00Z" }}How it fails
TOKEN_MISSING_ABILITYtoken lacks support-conversation:update.
No support conversation found with that id. — unknown id, or outside the token's project scope.
Caveats
- Resolving does not notify the member. Send a reply first if they should know the matter is closed.
- Resolving an already-resolved conversation succeeds and emits the event again. Harmless, but deduplicate if you are posting notifications downstream.
- The member's next message reopens the thread automatically and raises
support.conversation.reopened. A blocked member's message does not — their thread stays resolved.
unblock_support_contact
DESTRUCTIVELet the member behind a support thread write in again after block_support_contact. Messages dropped while blocked are gone.
Lift a block placed with block_support_contact. From this moment the member's messages reach the inbox again, and their next message can reopen a resolved thread as anyone else's would.
Nothing is recovered. Messages sent while the block was in place were dropped at ingestion, not held, so there is no backlog to release. Only what the member writes after this call arrives.
Emits support.conversation.unblocked when the block is lifted. Idempotent: unblocking a member who was not blocked changes nothing and emits nothing.
Requires ability
The token behind the MCP session must hold it, or the call is refused with TOKEN_MISSING_ABILITY.
Runs the same action as
The REST endpoint and this tool share one action, so validation, permissions and events are identical.
Fires one event
Delivered to every endpoint subscribed to it once the change is made.
Annotations
A client that honours annotations asks a person before running it. Sending the same arguments twice changes nothing the second time.
Arguments
conversation_id*stringUUID of the support conversation whose member to unblock.
What it returns
{ "data": { "id": "9e042b6f-5d81-4c37-a920-7b3e18cf6d45", "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13", "channel": "telegram", "status": "resolved", "assigned_to_user_id": null, "unread_count": 0, "blocked": false, "first_response_at": "2026-08-20T10:12:00+00:00", "resolved_at": "2026-08-21T09:30:00+00:00" }}status is whatever it was before — unblocking does not reopen the thread. The member's next message will, or reopen_support_conversation can.
How it fails
VALIDATION_FAILEDthe token's owner is on the project's team but their role lacks the support permission on it.
RESOURCE_NOT_FOUNDunknown conversation_id, another creator's thread, or a project outside the token's scope:project: allow-list.
AUTHENTICATION_REQUIREDno authenticated user on the request.
TOKEN_MISSING_ABILITYtoken lacks support-conversation:update.
update_canned_reply
DESTRUCTIVEChange one or more fields of a saved support reply. Anything omitted keeps its stored value.
Edit a snippet in place — reword the body, rename it, give it a shortcut or move it in the picker. The change is partial by design: only the arguments present in the call are written, and every other field is filled from the stored row.
Emits support.canned_reply.updated with the fields that changed, and only when something did. Idempotent: sending the stored values again writes nothing and emits nothing.
Omitted is not the same as null
Leaving shortcut out keeps the current shortcut; passing shortcut: null
clears it. sort_order is the exception — null there is treated like an
omission and the stored position stays.
Requires ability
The token behind the MCP session must hold it, or the call is refused with TOKEN_MISSING_ABILITY.
Runs the same action as
The REST endpoint and this tool share one action, so validation, permissions and events are identical.
Fires one event
Delivered to every endpoint subscribed to it once the change is made.
Annotations
A client that honours annotations asks a person before running it. Sending the same arguments twice changes nothing the second time. It reaches beyond Subscriby: a connector, a provider or a member.
Arguments
project_id*stringUUID of the project the snippet belongs to.
canned_reply_id*stringUUID of the saved reply to change.
titlestringoptionalNew label, 2 to 80 characters.
bodystringoptionalNew reply text, 2 to 4000 characters.
shortcutstringoptionalNew slash-command, unique within the project. Pass null to clear it.
sort_orderintegeroptionalNew position in the picker, 0 to 999.
0max999What it returns
{ "data": { "id": "5d2f8a71-3c9e-4b06-a8f4-1e7c9d2b6a35", "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13", "title": "Refund policy (2026)", "body": "Refunds are available within 14 days of your first payment. Reply here with the email you paid with and we'll sort it.", "shortcut": "refund", "sort_order": 0, "created_at": "2026-06-02T09:14:02+00:00", "updated_at": "2026-09-06T10:05:00+00:00" }}The full row after the change, not just the fields sent — so the response is what a creator now sees in the picker.
How it fails
VALIDATION_FAILEDa title or body that is present but empty or outside its length limits, a shortcut over 30 characters, with disallowed characters, or already used by a different snippet in this project, or sort_order outside 0–999. Also returned when the token's owner is on the project's team but their role lacks the support permission on it.
RESOURCE_NOT_FOUNDproject_id names a project the token cannot see, or canned_reply_id is unknown, deleted, or belongs to another project.
AUTHENTICATION_REQUIREDno authenticated user on the request.
TOKEN_MISSING_ABILITYtoken lacks support-canned-reply:update.
update_support_settings
DESTRUCTIVEChange a project's support inbox settings. Anything omitted keeps its stored value.
Switch member support on or off, choose where new threads are relayed, set the name members see on replies, set or clear the automatic acknowledgement, and toggle email notifications. Partial by design: only the settings present in the call change, and the rest is assembled from the stored row before the write.
Emits support.settings.updated with the settings as they now stand and what changed — and only when something did. Idempotent: sending the stored values again writes nothing and emits nothing.
Turning support off
With enabled: false, member messages stop reaching the inbox and go back to
the bot's "I can't understand" fallback. Existing threads are kept, nothing is
deleted, and switching it back on resumes intake — but messages sent in
between are not recovered.
relay_mode accepts owner_dm, forum_group and none. forum_group
starts relaying once the creator has added the project bot to a group with
Topics enabled as an administrator; the bot links the group itself and
confirms by DM, so switching the mode alone does not connect anything.
Requires ability
The token behind the MCP session must hold it, or the call is refused with TOKEN_MISSING_ABILITY.
Runs the same action as
The REST endpoint and this tool share one action, so validation, permissions and events are identical.
Fires one event
Delivered to every endpoint subscribed to it once the change is made.
Annotations
A client that honours annotations asks a person before running it. Sending the same arguments twice changes nothing the second time. It reaches beyond Subscriby: a connector, a provider or a member.
Arguments
project_id*stringUUID of the project whose support settings to change.
enabledbooleanoptionalWhether members can open support threads with the bot.
relay_modestringoptionalWhere new threads go besides the dashboard inbox: "owner_dm" forwards them to the creator on their connector, "forum_group" opens each thread as a topic in the group the project bot administers, "none" keeps them in the inbox only.
agent_namestringoptionalThe name members see on replies, up to 60 characters. Pass null to use the project name.
auto_replystringoptionalThe message sent automatically when a member opens a thread, up to 1000 characters. Pass null for none.
notify_emailbooleanoptionalWhether the creator is emailed about new threads.
What it returns
{ "data": { "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13", "enabled": true, "relay_mode": "owner_dm", "agent_name": "Team Subscriby", "auto_reply": "Thanks, we will reply within a day.", "notify_email": true, "updated_at": "2026-09-06T10:05:00+00:00" }}The same row get_support_settings returns, after the change. agent_name and auto_reply come back trimmed; a blank string is stored as null, the same as passing null.
How it fails
VALIDATION_FAILEDrelay_mode is anything but owner_dm or none, agent_name longer than 60 characters, auto_reply longer than 1000, or enabled / notify_email not a boolean. The envelope names the offending field. Also returned when the token's owner is on the project's team but their role may not update the project.
RESOURCE_NOT_FOUNDproject_id names a project the token cannot see: unknown, another team's, or outside the token's scope:project: allow-list.
AUTHENTICATION_REQUIREDno authenticated user on the request.
TOKEN_MISSING_ABILITYtoken lacks project:update.
How is this guide?