Connect Intercom to Fondoo

Live4 min readUpdated

Intercom in Fondoo: what your AI agent can do with it, what to set up first, the permissions it needs and its limits.

In the Intercom Developer Hub create (or open) a private app for your workspace and copy its access token from Configure > Authentication; enable the permissions Read conversations, Write conversations, Read and list users and companies, Write users and companies, Read tags, Write tags and Read admins. Optionally set adminId (the teammate who authors replies; otherwise the token owner from GET /me is used) and region us, eu or au to match your workspace data hosting. For signed webhooks paste the app client secret from Basic Info as webhookSecret. The REST API requires a paid Intercom workspace.

Official documentation: https://developers.intercom.com/docs/references/2.16/rest-api/api.intercom.io/conversations/retrieveconversation

Use add_connection_key without fields for a signed, one-use secure paste page. Then call test_connection and inspect confirmed versus unknown permissions. Direct tool credentials carry a chat-log warning. list_connections never returns credentials.

Auth: api_key (Authorization: Bearer <access token>, Intercom-Version: 2.16; credential fields apiKey (secret), region, adminId, webhookSecret (secret)). Category: support. Required provider scopes: Read conversations, Write conversations, Read and list users and companies, Write users and companies, Read tags, Write tags, Read admins.

Capabilities are discoverable with list_connector_manifests; invoke them through connector_action. Writes retain shared Fondoo scopes, approvals, dry runs, audit, events and metering. Use rotate_connection_key before expiry and delete_connection to remove stored credentials; revoke upstream credentials separately.

What Fondoo does with Intercom

Intercom is a helpdesk provider for the M15 support switch: set_provider({siteId, capability:'support', provider:'intercom'}) routes the shared support ticket operations to this connection. A Fondoo "ticket" is an Intercom conversation and its ID is the conversation ID.

Normalized capabilities (all through connector_action or the support operations):

  • tickets.list (read): GET /conversations (or POST /conversations/search on state when a status is requested). cursor is Intercom's starting_after; limit is 1..100. Status mapping: open → open, snoozed → pending, closed → closed (new and solved are written as open and closed). Priority priority maps to high; other values to normal.
  • tickets.get (read): description is the first customer message with HTML stripped to plain text; requester is the first customer author; assignee_id is admin_assignee_id (0 means unassigned).
  • tickets.comments (read): the source message plus conversation parts, oldest first. Notes are public:false; users/leads/contacts are customer, admins agent, bots and AI agent parts bot. Intercom returns at most the 500 most recent parts and offers no part pagination, so a truncated thread returns next_page:"truncated" and core routes it to a human.
  • tickets.create (write): finds or creates a lead by email, starts the conversation as that contact, then sets the title and applies tags. Failures after the conversation exists are returned as warnings (title_not_set, tags_not_applied) instead of failing, so the ID is never lost. Priority is validated and ignored (ignored:["priority"]).
  • tickets.update (write): a public reply is message_type:"comment" and an internal note message_type:"note" (note text is HTML-escaped), authored by adminId (or the token owner from GET /me). assignee_id posts an assignment part (0 unassigns). tags is the full desired set: missing tags are created and attached, extra tags are detached. A requested close, snooze (one week) or reopen is sent last because replies and assignments can reopen a conversation.

Webhooks

Call get_helpdesk_webhook({connectionId}) for the URL (/webhooks/helpdesk/<connectionId>) and setup facts; it never returns the secret. In the Developer Hub open your app, go to Webhooks, add that URL, and subscribe to conversation.user.created (and optionally other conversation.* topics). Paste the app's client secret (Basic info) as webhookSecret. Fondoo verifies X-Hub-Signature: sha1=<hex>, the HMAC-SHA1 of the raw body keyed with the client secret, in constant time. conversation.user.created becomes a new conversation event; other conversation.* topics except conversation.deleted become updates. Only the conversation ID is read from the payload; content is re-read through the API and never stored from the webhook. Intercom does not include a timestamp in the signature, so there is no replay window and handling is idempotent per conversation.

Human-only topics

Complaints, refunds and legal requests stay human-only: Fondoo classifies new conversations with the site's protected-category rules, raises complaint.opened or refund.requested, alerts a human and requires owner approval for agent replies. This connector has no refund, payment or delete capability.

API endpoints used

Limits and uncertainties

  • Rate limit: Intercom allows 10,000 calls per minute per app (25,000 per workspace) over 10-second windows; one execute may issue up to 25 requests, so Fondoo budgets 60 executes per minute. 429 surfaces as rate_limited.
  • The Intercom developer site was unreachable from this environment when this guide was written, so these endpoints were not re-verified against the live pages; URLs follow Intercom's published 2.16 reference layout and should be rechecked.
  • Uncertain: Intercom conversations have no subject, so title is a custom attribute set by PUT /conversations/{id}; if that call is rejected the title falls back to the first message excerpt.
  • Uncertain: the snooze duration is fixed at seven days because Intercom requires snoozed_until.
  • Priority is not supported on conversations (it belongs to Tickets), so priority writes are validated and ignored.
  • Intercom does not paginate conversation parts; threads over 500 parts are incomplete.
  • Webhook signatures carry no timestamp, so replay cannot be rejected by age.