The account is fixed by the connection
Every MCP call must carry theX-Sapot-Account-Id header. It is set once, on the connection, and Rails independently enforces that your token is bound to that exact account — a mismatch is rejected with “Access token is not valid for this account”.
Display id vs database id
Sapot Chat uses two different id spaces, and mixing them is the most common mistake. Conversations and campaigns are addressed by their per-account display id (the number you see in the dashboard URL); contacts are addressed by their database id.Labels: two separate gotchas
1. Setting labels REPLACES the whole set.add_conversation_labels and add_contact_labels are not additive despite the name — they overwrite the record’s entire label list with exactly what you send. To add one label, read the current labels first and send the union.
2. Titles here, numeric ids there. The two paths take different label representations:
Passing a title string where a numeric id is expected (
preview_campaign_audience, draft_campaign, update_campaign_draft) silently yields a zero-reach audience — always resolve ids with list_labels first.
Reports use UNIX epoch seconds
Thesince / until arguments on report tools are UNIX epoch seconds as strings (e.g. "1719792000"), not ISO date strings. This applies to get_report_summary, get_report_timeseries, and get_entity_summary.
Pagination differs by domain
Page size is fixed per domain — there is noper_page argument. Advance with the page argument (1-based) except on messages, which are cursor-paginated by message id.
custom_attributes are MERGED on update
update_contact merges the custom_attributes you send into the existing ones — keys you omit are preserved, not wiped. Send only the keys you want to change; you do not need to read-modify-write the whole object. (This is the opposite of the label tools above, which replace.)
The same “only the fields you pass are changed” rule holds for
update_contact, update_knowledge_entry, update_knowledge_profile, and update_campaign_draft. custom_attributes is the one field that deep-merges rather than replaces.See also
Authentication & Scopes
Default-deny scopes, the 401 scope hint, and the 429 quota response.
REST API
Call the same endpoints directly with the same scoped key.

