{
  "schema": "aaes/capability-pack/1",
  "provider": "intercom",
  "version": "1.0.0",
  "description": "Read Intercom contacts, companies, and conversations; reply to a conversation as an admin. Comment replies reach the contact in Messenger and by email.",
  "notes": "Every endpoint here is on api.intercom.io, the shared Intercom production API host named in Intercom's REST API reference, so there is no per-customer host to substitute. Intercom also operates regional hosts (api.eu.intercom.io, api.au.intercom.io); a deployment whose workspace lives in a regional data host must substitute that host in the endpoints, resource locators and egress allowlists — the allowlist matches exactly, so all three move together.\n\nCallers must send the Intercom-Version header (the reference documents version 2.16 as current); the version is a request header, not part of the registered endpoint. This pack registers only endpoints the official Intercom REST API reference documents: the contacts, companies and conversations collection reads, and replying to a conversation.\n\nAll read capabilities cover the collection read only: single-record reads (GET /contacts/{id}, GET /companies/{id}, GET /conversations/{id}), search, scroll and per-contact sub-resource listings (notes, tags, segments, subscriptions) are not registered by this pack — separate navigation and sub-resource endpoints are not registered unless named.\n\nNote on the companies collection read: it is verified against Intercom's retrievecompany reference itself, which documents the collection operation — GET /companies returns a paginated list of all companies, filterable by segment_id or tag_id, and fetches a single company by the name or company_id query parameters on the same path; the retrieval reference does document the general collection listing on this path.\n\nThe POST /companies/list variant named in older documentation does not appear in the current reference (its page returns not-found), POST /companies is the create-or-update operation (not registered), and the scroll API is deliberately not registered.\n\nConsequential effects: POST /conversations/{conversation_id}/reply with message_type 'comment' is an admin reply delivered to the contact in the Messenger and by email — the unrestricted effect of the endpoint includes transmitting to the customer, so the capability declares send at the minimum R3 tier alongside create. send is one of the designated actions requiring human approval: a reply cannot be recalled after delivery once the contact has it.\n\nAn internal-note-only variant (message_type 'note') is not registered: message_type is a request-body property of the same endpoint, and a pack registers an endpoint, not a body value, so nothing in the registration would enforce the note-only restriction.\n\nDocumented exclusions: this pack does not register contact create/update/delete, contact merge, archive or block, note creation, company create/update/delete, the Messages API (admin-initiated outbound messages, which are send at R3), conversation assignment or snooze, tags, and data-export endpoints.\n\nData-class rationale: contacts identify individuals (names, emails, phones, custom attributes) and conversations carry their messages, so both are pii; companies describe organizations and are registered internal. The endpoints are verified against the provider documents named in the review block, and the custody review that docs/gtm/CAPABILITY-LIBRARY-PLAN.md §4 gates authentication modes on was completed on 2026-09-21 against this pack's custody model (a workspace access token held in the customer's vault), with these findings, one per gated property.\n\nIssuance authority and delegation: a workspace admin creates an app in the Intercom Developer Hub and the workspace's access token is issued from the app's Authentication section, so issuance authority sits with the workspace's own admin. Scope: Intercom scopes app permissions per resource in the Developer Hub; the app is built for the exact registered surface — read access to contacts, companies and conversations, plus conversation reply — and no other permission.\n\nAudience: no audience mechanism is documented — the bearer value authorizes against api.intercom.io (or the workspace's regional host), and audience binding beyond that is not established. TTL: the retrieved authentication documentation states no expiry terms, corroborated by Intercom's own support channel — private-app access tokens do not expire unless manually revoked — so this pack treats the token as live until revoked.\n\nRefresh ownership: there is no refresh — the token is the credential and no tokens are derived from it; the executor injects the stored value verbatim and performs no token lifecycle itself.\n\nRevocation: the token is revoked by deleting or rotating it in the Developer Hub or by uninstalling the app, and a revoked value fails closed; because no derived tokens exist, deletion revokes exactly this value. Executor access and replay/exposure: the executor reads only the vault reference; the token is a bearer credential replayable with no TTL bound until revoked, so the vault reference is the only place the value may live.\n\nAlternate access paths: the Intercom UI and other apps retain access outside this pack, and deleting or rotating this token closes only this path. The credential review is complete. Assign accountable owners before deployment.",
  "credential": {
    "secret_ref_id": "secret-ref-intercom-access-token",
    "custody": "customer_vault",
    "inject": "header",
    "inject_name": "Authorization",
    "note": "An Intercom access token (bearerAuth in the REST API reference), held in the client's own secret manager. The stored material must be the complete Authorization header value: the scheme 'Bearer', one separating space, then the token — 'Bearer <token>'. Token issuance is an external process: a workspace admin creates an app in the Intercom Developer Hub, and the workspace's access token is issued from the app's Authentication section; the executor performs no token lifecycle itself and injects the stored value verbatim.\n\nLeast privilege: build the app for the exact registered surface — read access to contacts, companies and conversations, plus conversation reply — and no other permission; Intercom scopes app permissions per resource in the Developer Hub.\n\nExpiry and revocation: Intercom access tokens do not expire on their own; the token is revoked by deleting or rotating it in the Developer Hub (or by uninstalling the app), and a revoked value fails closed. Because the token is the credential (no separate tokens are issued from it), deletion revokes exactly this value. Review the workspace's app inventory and token age before enabling.\n\nExecutor hygiene: the value must live only in executor memory for the lifetime of a call, must never be written to logs, traces or diagnostics, and must not appear in crash dumps; a deployment that cannot meet that bar must not enable the pack."
  },
  "capabilities": [
    {
      "capability_id": "intercom.contacts.read",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R0",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "pii",
      "egress_allowlist": [
        "api.intercom.io"
      ],
      "endpoint": "https://api.intercom.io/contacts",
      "method": "GET",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-intercom-access-token",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "read"
      ],
      "resource_id": "intercom-workspace-contacts",
      "description": "List all contacts (users and leads) in the workspace: names, email addresses, phones and custom attributes, which are personal data. The registered path covers the collection read only — single-contact reads (GET /contacts/{id}), contact search and per-contact sub-resource listings (notes, tags, segments, subscriptions, companies) are not registered by this pack.",
      "requires_review": true
    },
    {
      "capability_id": "intercom.companies.read",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R0",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "internal",
      "egress_allowlist": [
        "api.intercom.io"
      ],
      "endpoint": "https://api.intercom.io/companies",
      "method": "GET",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-intercom-access-token",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "read"
      ],
      "resource_id": "intercom-workspace-companies",
      "description": "List companies in the workspace: names, plans, sizes and custom attributes, which describe organizations and are registered internal (a deployment storing monthly spend or other commercial terms on company records should review the class before enabling).\n\nThe registered path is verified against Intercom's retrievecompany reference, which documents GET /companies returning a paginated list of all companies (filterable by segment_id or tag_id) and also fetching a single company by the name or company_id query parameters on the same path — query-parameter filtering is a caller choice on the registered path, not a separate registration.\n\nSingle-company reads by id (GET /companies/{id}) and the scroll API are not registered by this pack; the POST /companies/list variant named in older materials does not appear in the current reference, and POST /companies is the create-or-update operation, which is deliberately not registered.",
      "requires_review": true
    },
    {
      "capability_id": "intercom.conversations.read",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R0",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "pii",
      "egress_allowlist": [
        "api.intercom.io"
      ],
      "endpoint": "https://api.intercom.io/conversations",
      "method": "GET",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-intercom-access-token",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "read"
      ],
      "resource_id": "intercom-workspace-conversations",
      "description": "List all conversations in the workspace: message bodies, authors, contacts and state — customer correspondence, which identifies individuals and is classified as pii (personal data). The registered path covers the collection read only — single-conversation reads (GET /conversations/{id}) and conversation search are not registered by this pack.",
      "requires_review": true
    },
    {
      "capability_id": "intercom.conversations.reply",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R3",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "pii",
      "egress_allowlist": [
        "api.intercom.io"
      ],
      "endpoint": "https://api.intercom.io/conversations/CONVERSATION_ID/reply",
      "method": "POST",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-intercom-access-token",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "create",
        "send"
      ],
      "resource_id": "intercom-workspace-conversations",
      "description": "Reply to one conversation as an admin (message_type 'comment' with a text body and optional attachment URLs). The declared effect includes send at the minimum R3 tier: a comment reply is delivered to the contact in the Messenger and by email, so the operation transmits to the customer and a delivered message cannot be recalled after delivery. send is one of the designated actions requiring human approval.\n\nOn supported AAES-mediated execution paths, irreversible actions require approval by an authorized person; this does not prevent calls through bypass or observation-only paths. An internal-note-only variant (message_type 'note') is deliberately not registered: message_type is a request-body property of this same endpoint, so the registration cannot enforce it. CONVERSATION_ID is a placeholder the deployment binds to a concrete conversation before enabling.",
      "requires_review": true
    }
  ],
  "resources": [
    {
      "resource_id": "intercom-workspace-contacts",
      "kind": "api",
      "locator": "https://api.intercom.io/contacts",
      "data_class": "pii",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN"
    },
    {
      "resource_id": "intercom-workspace-companies",
      "kind": "api",
      "locator": "https://api.intercom.io/companies",
      "data_class": "internal",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN"
    },
    {
      "resource_id": "intercom-workspace-conversations",
      "kind": "api",
      "locator": "https://api.intercom.io/conversations",
      "data_class": "pii",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN"
    }
  ],
  "review": {
    "state": "library",
    "date": "2026-09-22",
    "sources": [
      "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/contacts/listcontacts (retrieved 2026-09-21)",
      "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/companies/retrievecompany (retrieved 2026-09-21)",
      "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/companies/ (retrieved 2026-09-21)",
      "https://developers.intercom.com/docs/build-an-integration/learn-more/authentication (retrieved 2026-09-21)",
      "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/conversations/listconversations (retrieved 2026-09-21)",
      "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/conversations/replyconversation (retrieved 2026-09-21)",
      "https://developers.intercom.com/docs/build-an-integration/learn-more/rest-apis (retrieved 2026-09-21)"
    ],
    "reviewer_id": "aaes-eng"
  }
}
