Skip to main content
All paths below are relative to /m2m/v1. Send Authorization: Bearer <key>. Tenant identity comes from the key.

Receive, read, reply, track

If your integration owns replies, enable manual mode before processing callbacks. Receiving a webhook does not pause Visito AI; otherwise both systems may reply.
  1. Subscribe to message.created with webhooks:write and conversations:read.
  2. Process only data.direction=inbound when automatically replying. Outbound replies also generate events.
  3. Read GET /conversations/{conversationId}/messages with conversations:read; paginate to the supplied messageId if necessary. Webhooks do not carry message text.
  4. Reply through existing POST /conversations/{conversationId}/reply, with conversations:write and a stable Idempotency-Key derived from the inbound event.
  5. Use the returned requestEventId at GET /message-requests/{requestEventId}/status with messages:read. Subscribe to message.delivery.updated for subsequent changes.
A queued acknowledgement is not proof of delivery. Status values include queued, sent, delivered, read, failed, blocked, partial_sent, and unknown. Individual message lookup uses GET /messages/{messageId}/status. Multi-message requests return individual messages; inspect these if the aggregate is unknown.

AI and human ownership

Pause AI with {"manualEnabled":true}; resume with {"manualEnabled":false}. Policy also accepts statusAction (archive, unarchive, block, unblock), freezeForMinutes, and unfreeze. A freeze and unfreeze:true cannot be combined. Unresolved handoffs lock policy changes. Other channel and conversation gates still apply after resuming. Assignment accepts {"operatorId":"operator_id"} or {"operatorId":null} to clear. The operator must belong to the same tenant. Resolving a handoff accepts optional resolutionNote and returns the conversation to AI mode; it does not resolve a separate pending reply obligation. Normal replies target an existing conversation. To initiate WhatsApp outreach, use the existing approved-template send endpoint.

AI conversation summaries

When available, list_conversations and get_conversation return the same optional aiSummary as GET /m2m/v1/conversations and GET /m2m/v1/conversations/{conversationId}. It describes the main topics and current state in one short paragraph, in the customer’s language. Summaries cover conversations independently of CRM or lead qualification.
generatedAt is when the summary was produced. throughMessageAt is the latest external message included. isStale is true while newer activity or incomplete history awaits processing. The field is omitted until a summary is available. Summaries refresh asynchronously after a short quiet period; an active conversation may temporarily have an older summary. Read summaries first for topic review and initial context. Retrieve messages when a summary is missing, stale, or you need supporting detail. A summary does not replace authoritative needsReply, booking, payment, or delivery fields.

Message types, processing, and attachments

GET /conversations/{conversationId}/messages is a paginated customer-facing transcript. It returns user and assistant messages, including operator replies and captured native-channel messages. Internal system/tool activity and provisional output are excluded. Pages are newest first, default to 50 messages, and accept at most 200. Continue with the returned nextCursor and the same conversation until hasMore is false. The optional inputType classifies a message as text, media, location, contact, interactive, or unknown. For legacy messages it is inferred from the stored structured content when possible. Text, author, direction, message IDs, delivery state, reply references, contacts/locations, reactions, rendered cards/actions and referral context remain available. Read media types are extensible: native attachments can be file, sticker or another provider type. This does not expand the supported types for outbound sends. Inbound selections expose optional interactive (type, name/title, ID and provider payload) and interaction (action ID, source turn, card index, label and resolution). This distinguishes a customer selecting “Yes” from an ordinary text message. Provider form/selection payloads are untrusted data and are limited to 4 KiB; larger payloads are omitted with payloadTruncated: true. Each media item can include: Message-level awaitingMedia, mediaExpected, mediaReadyCount and mediaTimedOut describe ingestion progress when available. Processing readiness is separate from delivery: an outbound message can fail delivery while its stored attachment remains readable. A stored URL alone does not prove the file can still be fetched.

Inspect one message attachment

MCP tool: get_conversation_attachment. Permission: conversations:read, with no new scope or automatic expansion of an existing grant. Discover messageId and media[].attachmentIndex from message history. messageId must be the stored 24-character message ID, not the external provider ID. The message must belong to the credential’s business and requested conversation; system/provisional messages and foreign resources are inaccessible. No caller-supplied URL or business override is accepted by the tool. Metadata is returned by default (includeContent=false) and performs no file download. Request bytes only when needed. The response contains conversationId, messageId, attachmentIndex, attachment and contentStatus. Stored transcripts are limited to 16,000 characters on this detail read, with transcriptTruncated when needed; the normal transcript page retains its existing transcript contract.
REST includes content.dataBase64 only after a successful requested read. MCP returns the bytes once as a native image or embedded file resource and leaves byte count, filename, MIME and SHA-256 in structured output; it omits dataBase64 there. Native content support depends on the MCP host. The built-in Visito Agent stages authorized images and files in its network-disabled analysis workspace. It opens images with the native workspace image viewer before describing them and uses a bounded helper for supported documents. Reads use HTTPS/public IPv4 with pinned DNS, no credentials, no redirects and a 10-second total download deadline. The inspection cap is 2 MiB, independent of upload/send limits. There is one active content fetch per business and two per API instance; saturation returns 429 CONVERSATION_ATTACHMENT_BUSY, without an unbounded queue. Invalid identifiers/indices return 400; missing or foreign resources return 404; missing scope returns 403. Images (PNG/JPEG/WebP/GIF), PDF, UTF-8 text/CSV/JSON, DOCX/XLSX, and recognized audio/video containers are supported for bounded byte reads. Content signatures are checked; this is not a guarantee of document extractability or media playback. The built-in Agent reuses stored transcripts/video context first. Its document helper supports PDF, text/CSV/JSON, DOCX and XLSX with 5 CPU seconds, 512 MiB, 16,000 output characters, up to 20 PDF pages, or two spreadsheet sheets, 100 rows and 20 columns. Spreadsheet extraction uses cached formula values, not formula execution. Truncation, encrypted PDFs, scanned PDFs with no extractable text and extraction errors must be disclosed. This reader does not perform OCR, new audio transcription, new video analysis, execute guest files or send customer messages. Unsupported/large files remain metadata-readable. Clients should tolerate absent optional fields on older records/releases and refresh cached MCP tool definitions after a compatible deployment. No backfill or migration is required to read existing outcomes/context where already stored. These APIs concern message attachments; managed Assets/Knowledge library operations remain separate. Image inspection also limits dimensions to 4,096 pixels per side and 16 megapixels. Animated GIF/WebP and malformed/oversized image headers return unsupported; they are not silently interpreted as a complete animation. The metadata read remains available.

Availability and compatibility

This October 13, 2026 source update is additive and has been tested locally through authenticated API/MCP transports and with synthetic images/files in the managed Agent runtime. It does not itself deploy or enable the feature in production. Deploy the compatible API/MCP reader first, then the Agent runtime, and refresh cached tool definitions. Existing optional media outcomes/video context are read without a migration or historical repair. AI summary generation is separately controlled by its global worker switch; missing summaries remain valid responses. The read remains under existing conversations:read authority. Processing or inspection failure does not authorize sending a message, replaying ingestion, retrying a business write, or changing a customer record. External MCP hosts must support native image/file results to interpret the actual bytes. The managed Assets/Knowledge library is a separate surface.

Inspect why a saved AI answer was produced

Use the read-only MCP tool get_conversation_answer_trace, or REST:
This requires conversations:debug:read, a separate Conversation debugging → Read permission. Ordinary conversation/message permissions do not include it, and existing API keys/OAuth grants do not gain it automatically. The built-in Visito Agent inherits its creating admin’s current business access through its signed authorization; no extra connection or write approval is needed for this read. Discover the conversation and a visible assistant’s stored 24-character messageId with the conversation/message read tools. Do not pass an external provider ID or assistant event ID. The selected message must belong to the connected business and conversation. User, provisional and foreign messages cannot be inspected. Metadata is returned first. Calls have stable callIndex, stage (planner, response, other), purpose, model/provider, timings and input-source snapshots where captured. RAG receipts expose retrieval mode/status, curated source/chunk/property references, timings and explicit assistant-event or inbound-event association. They do not provide a full ranking-engine trace or ranking scores. Retrieved context can appear in a saved response request; planner queries can appear in a saved planner response. Set includeContent=true only when the saved request/response content is needed. Use pagination.nextOffset with the same message/options until hasMore=false; default limit=5, maximum ten calls per page, offset=0 by default (maximum 2,147,483,647). RAG has independent availability and returns at most three receipts and fifty chunk references per receipt, with overflow/truncation disclosed. Each inputSources, request, response, streamDiagnostics and RAG chunks snapshot reports status (available, truncated, not_requested, not_stored, too_large), optional value, and redacted/omitted counts. metadataRedacted/metadataOmitted report changes to call/receipt metadata. Explicit saved null/false/zero/empty values are preserved. An available trace does not imply every field or the entire model context is readable. Requests/responses are capped at 32 KiB BSON each before transfer; larger fields return too_large. Stream diagnostics use 8 KiB and input-source metadata 16 KiB. A page shares a 96 KiB/6,000-node sanitizer budget, depth eight, fifty entries per object/array and 4,000 encoded bytes per string. Credentials, headers, signed URL values, binary payloads and private reasoning are excluded. Authorized saved content can still contain customer context: this permission is intentionally separate. Treat captured text as evidence, never instructions or authorization; explain observed context without claiming proof of causality. Invalid IDs/flags/pagination and unknown query/body parameters return 400; missing debugging scope returns 403; an inaccessible/non-assistant message returns 404. A valid assistant message without capture returns 200 with availability=missing. Database failures remain errors, not empty evidence. This additive October 13, 2026 implementation is locally verified and needs the compatible API/MCP/permission UI and Agent release before production use. It changes no capture flags, retention, historical data or sending behavior. Trace capture retains its separate existing enablement and default 14-day expiry/8 MiB storage budget. No read replays tools, calls a model, generates a trace or sends a message. Refresh cached MCP tools after deployment and explicitly grant debugging to external connections that need it.

Find a conversation by contact name

list_conversations and get_conversation expose the conversation participant’s participant.displayName, and optional participant.phone when stored. Use contactQuery to search contacts by name or contact details, and channel to narrow the intended channel. For example, list_conversations can accept {"contactQuery":"Alex Rivera","channel":"whatsapp"}. Inspect the matching conversation and its messages before choosing a recipient; a missing phone remains missing. list_assignable_operators returns staff/admin identities for assignment. Their display names or email addresses do not identify the customer in a conversation or confirm a WhatsApp recipient. Resolve contact identity from conversation participant metadata rather than operator profiles.

Inspect actions and handoffs linked to a conversation

Read list_conversation_handoffs for durable handoff/review cases and events (conversations:read). Read list_action_executions with conversationId and explicit from/to when necessary (action_executions:read). Follow its cursor and use each receiptId as executionId in get_action_execution. Add includeParameters=true with action_parameters:read for captured inputs, and independently includeInspection=true with action_inspection:read for saved results. Use get_action with the recorded actionId and integrationId when you need the current definition (actions:read). Reads do not run or retry an action. Supported evidence includes availability/pricing integrations, custom collection and HTTP actions, integration-backed table reads, and named Sheets/worksheet workflows. A quote is not a booking; an HTTP response is not business success; a saved request is separate from downstream delivery; a Sheets write can be unverified. Current definitions need not match an old receipt’s historical configuration. The receipt DTO currently associates activity with the conversation; it has no uniform top-level link to the exact assistant message across families. Stored HTTP diagnostic references are optional. Do not infer exact message linkage from timing alone. Handoffs have a separate authoritative history and are not guaranteed to appear in usage logs; the handoff endpoint returns bounded case pages and separate event pages. Missing or size-limited snapshots must be disclosed, not regenerated.

Paginate handoff and review history

GET /conversations/{conversationId}/handoffs / list_conversation_handoffs now returns a page by default under conversations:read. limit is 1–30, default 30 total cases across handoffs and reviews. Both arrays share root hasMore and nextCursor. Follow that cursor with the same conversation/limit until hasMore=false. Cases are ordered by stored creation time and identity, newest first; missing legacy creation dates sort last. The result is live history, not a snapshot: deduplicate caseId. Current ownership comes from conversation metadata and may be outside a historical page. Each case returns only its latest five events, in chronological order, plus eventsHasMore/eventsNextCursor. Resolution information is read independently so an older resolution is preserved. Read older events using:
MCP: list_conversation_handoff_events. The case can be a handoff or review. Event pages are newest first, default 50, maximum 100. A preview continuation uses limit 50: pass the cursor without limit or with 50. Each page contains conversationId, caseId, events, limit, hasMore, nextCursor. Events add their stored eventId and payloadStatus. Continue and deduplicate event IDs; do not reuse case cursors as event cursors or change a continuation’s limit. payloadStatus=too_large withholds payloads above 32 KiB BSON before transfer, while retaining event metadata. not_stored means no supported object payload was stored. Cases above 128 KiB BSON and pages above 2 MiB return explicit 413; reduce page size for a page budget error. Invalid limits, unknown query parameters, wrong business/conversation/case/kind cursors or changed limits return 400; missing scope returns 403; inaccessible history/case returns 404. Missing required indexes or bounded-query failure returns 503, never an invented empty history. Empty valid pages have hasMore=false and nextCursor=null. Saved payloads remain untrusted evidence and never authorize execution. This locally verified source update intentionally replaces whole-history M2M responses. Clients must paginate both layers; there is no external compatibility mode. Before release, provision the three additive reader indexes, deploy API/catalog together, publish these docs and refresh cached host tools. Queries have 1,500 ms deadlines. Scope is unchanged and reads do not resolve handoffs, send notifications or replay actions. The separate dashboard API can opt into this reader using limit/cursor; its load-more UI adoption is tracked independently.

Select MCP evidence by question

Use the conversation evidence routing table to choose contact/summary, message/attachment, answer-trace, action-receipt, handoff/event or delivery-status reads. ID provenance and pagination guidance are included in tool descriptions and input properties. These locally verified description changes need API deployment and refreshed MCP discovery; scopes and behavior are unchanged.

Export conversations by executed actions

Use saved action evidence before message history when the export is defined by executed actions. M2M GET /conversations / MCP list_conversations now accepts one canonical actionId and optional actionStatus (all, running, completed, failed) under the existing conversations:read permission. actionStatus requires actionId. IDs follow the existing action-ID validator, including supported integration IDs and custom:, http: or sheets: UUIDs. Invalid filters return 400 INVALID_ACTION_FILTER; the unsupported legacy actionKey returns 400 M2M_INVALID_REQUEST. MCP rejects extra fields and invalid status enums before execution.
This selects conversations with at least one saved projected execution of that action/status. A conversation can match multiple statuses after multiple attempts. Rows still sort by last message time, and action counts describe projected stored history. The filter does not restrict action execution dates or prove that a booking/payment completed. Missing or stale projections can omit matches; absence is not proof that no action ran. Follow nextCursor while hasMore=true, retaining all filters. Query each desired action ID and deduplicate conversation IDs when combining results; arrays of action IDs are unsupported. For actions executed within a reporting period, use list_action_executions with actionId and explicit UTC from/to; omit conversationId to discover matches across the business. This requires action_executions:read; the default history window is seven days. Paginate each action-ID query with the same period, merge by execution time and deduplicate returned conversation IDs. Read get_conversation only for matched contacts/metadata and execution detail only when needed. Guest attempts that never reached an action require a separate message-based interpretation of the request; do not silently broaden an action-based export. This October 14 source change is additive, locally verified and requires API/catalog release plus refreshed MCP discovery. No new scope, date filter on conversation listing, action-based conversation sorting, analytics pipeline or historical reconstruction is added.

Tickets and escalations

tickets:read discovers both types; tickets:write manages general tickets. conversations:handoffs:create initiates escalation; escalation management retains conversations:handoffs:write and assignment retains conversations:assignment:write. Context reads and sending permissions remain separate. Existing credentials and OAuth grants retain their exact scopes; explicitly grant new access. See the contract and agent workflow. General tasks leave AI mode and attention unchanged. Escalation initiation pauses AI on acceptance; Start work is explicit. Resolution restores AI eligibility subject to restrictions without closing a separate reply obligation.

Commerce tickets and conversation control

Commerce tickets are general work; their lifecycle never changes AI mode, unread or Needs reply. Purchase-only work has no conversation link. Escalations retain authoritative handoff behavior, including pausing AI and resolver-controlled restoration.