Intercom
www.intercom.com ↗Third-party OAuth exists and is self-serve for your own workspace, but any app reaching other customers' Intercom data — even unlisted — must pass Intercom review (7–14 days per docs, up to 7 business days per the console) with a recorded install/uninstall video and scope-by-scope justification.
01Pick your path
02Time & effort
- DEVCreate dev workspace, app, enable OAuth20–40 minutessourced[S3][S9]Free development workspace; tick 'Use OAuth' on the Authentication page; add HTTPS redirect URLs; pick scopes on the Authorization page.
- DEVBuild authorize → callback → token exchange1–3 hourssourced[S9]Agent writes the redirect builder with region routing and state, the callback handler, and the /me verification call.
- DEVTest install/uninstall in dev workspace30–90 minutesinferred[S4][S8]Duration is my estimate; the docs only say to keep a separate dev app and test there.
- PRODWrite listing copy, record end-to-end video, submit1–4 hourssourced[S8][S10]Video must show install with OAuth (full client_id + state), the whole feature, and uninstall.
- PRODIntercom review + possible resubmissionwait 7–14 dayssourced[S4][S8]Docs say 7–14 days; console banner says up to 7 business days; feedback arrives as an in-app Messenger conversation.
- PRODGo live unlisted, then optionally list1–2 daysinferred[S8]Approval makes the app public-unlisted; flipping 'List in App store' is a separate choice and later edits need re-approval.
03Steps
Get a working connection
Sign up for a free development workspace, create an app, and create a second app for production so the two never share URLs or scopes.
↗ developers.intercom.com/◆ prepared by agent · Intercom Developer Hub (app.intercom.com)https://app.intercom.com/
On the Authentication page tick 'Use OAuth'; under Redirect URLs add HTTPS callbacks (test + prod allowed, first is default). Private-app tokens are the alternative only for your own workspace.
↗ developers.intercom.com/docs/build-an-integration/learn-more/authentication/setting-up-oauth.mdPick only scopes that map to shipped features; document the mapping — over-privileged scopes are the top rejection cause and the reviewer checks the video against the scopes.
“Over-privileged scopes are the most common reason that apps are initially rejected in the approval process.” — [S7] verified verbatim
◆ prepared by agent · Scope justification draftFeature → scope map (draft for review) - Contact lookup card → Read one user and one company - Ticket sync → Read tickets, Write tickets - Agent replies/closes → Write conversations Not requested: Write users and companies, Delete conversations and metrics, Read admin activity logs. Each scope above maps to a shipped screen in the app; none are speculative.
Redirect the user to the regional /oauth endpoint with client_id and a random state; store state server-side to block CSRF. Match the host to the workspace region — Google sign-in fails on the wrong host.
“One exception: if the customer signs in with Google, the wrong regional host fails rather than prompting, so matching the region is required in that case.” — [S9] verified verbatim
◆ prepared by agent · Authorize URL builder (region-aware)https://app.intercom.com/oauth?client_id=$CLIENT_ID&state=$STATE # US https://app.eu.intercom.com/oauth?client_id=$CLIENT_ID&state=$STATE # EU https://app.au.intercom.com/oauth?client_id=$CLIENT_ID&state=$STATE # AU
Handle the callback (?code=&state=), verify state, then POST code + client_id + client_secret to https://api.intercom.io/auth/eagle/token. Keep the trailing '=' in the code or you get 401 'Unauthorized Code'.
“The code value in the redirect URL may contain a = at the end which needs to be included.” — [S9] verified verbatim
◆ prepared by agent · Server-side token exchangecurl -X POST https://api.intercom.io/auth/eagle/token \ -d code="$CODE" -d client_id="$CLIENT_ID" -d client_secret="$CLIENT_SECRET" # -> {"token_type":"Bearer","token":"...","access_token":"..."}Verify the token with GET https://api.intercom.io/me (Bearer auth, Intercom-Version header), then add 429/backoff handling using X-RateLimit-Remaining and X-RateLimit-Reset.
↗ developers.intercom.com/docs/references/1.0/rest-api/errors/rate-limiting.md
Make it production-ready
Record installation with OAuth working (show the full client_id and state in the URL), the end-to-end feature, and uninstallation. Missing any of the three means re-recording.
“Please show the full client_id and state parameter in the OAuth URL.” — [S8] verified verbatim
↗ developers.intercom.com/docs/publish-to-the-app-store/listing-your-app.mdSubmit from the Test and publish section; the app stays private during review, feedback arrives as a Messenger conversation, and requested scope changes mean resubmission.
“Our team will reach back out to you in an in-app conversation in the Messenger (find it at the bottom right of any Intercom pages you visit) to let you know about any changes that need to be made to your app.” — [S8] verified verbatim
↗ developers.intercom.com/docs/publish-to-the-app-store/review-publish-your-app.mdApproval yields a public-unlisted app you can beta-test; choosing 'List in App store' later is a separate step, and any post-approval edit must be re-approved.
“When your app is approved, it will become a public unlisted app.” — [S8] verified verbatim
04Requirements, scopes & nuances
You'll need
- ▸A Developer Hub app with client_id and client_secret (Basic Information page). sourced ❝[S9]
- ▸At least one HTTPS redirect URL registered under Redirect URLs; multiple allowed, first is default. sourced ❝[S9]
- ▸A server-side component that can hold the client_secret and perform the token POST (confidential client). sourced ❝[S9]
- ▸Published privacy policy and end-user agreement, GDPR-capable data handling, and Intercom audit permission if asked. inferred[S5][S10]
- ▸For public apps: app description, test account credentials if your product is paid, and an end-to-end video showing OAuth install + uninstall. inferred[S8]
- ▸Separate development and production apps in the Developer Hub (name the dev one [Dev]/[Staging]). sourced ❝[S4][S8]
Gotchas
- !Do not point your client at app.intercom.com/.well-known/openid-configuration — the 200 response is Intercom's own Okta staff SSO (issuer intercom.okta.com/oauth2/default, scopes okta.myAccount.*). There is no self-serve client registration there; a fake client_id gets a 400. inferred
- !Intercom's own OAuth has no published discovery document: api.intercom.io/.well-known/openid-configuration is 404 and /.well-known/oauth-authorization-server is 406. Hardcode authorize, token and /me endpoints. inferred
- !There are three authorization hosts (US app.intercom.com, EU app.eu.intercom.com, AU app.au.intercom.com); the wrong host is a wasted step for most users and a hard failure for Google sign-in. inferred[S9]
- !Token exchange is a confidential-client POST with client_id + client_secret to api.intercom.io/auth/eagle/token — so the flow must terminate on a server you control, never in the browser or in the agent runtime. inferred[S9]
- !If you use Canvas Kit (Messenger/Inbox apps), four scopes are auto-selected and cannot be deselected — 'Read and list users and companies', 'Read conversations', 'Read admins', 'Gather App data'. On the review form those must be justified like any other. sourced ❝[S7][S9]
- !Webhook topics are tied to scopes: a user-created webhook needs 'Read and write users', so webhook plans drive scope requests (and rejections). sourced ❝[S7]
- !Rate limits are 10,000 calls/min per app and 25,000/min per workspace, spread across 10-second windows (≈1,666 per 10s); over-limit returns 429 with X-RateLimit-* headers. sourced ❝[S6]
- !The two review-time claims disagree: the Developer Hub banner says up to 7 business days, 'Building Successful Apps' says 7–14 days. Plan for 2 weeks plus one resubmission. inferred[S4][S8]
| Scope / permission | Tier | Note | Evidence |
|---|---|---|---|
| Read one user and one company | basic | Narrowest contact lookup — prefer over 'Read and list users and companies' for a single-contact card. | sourced ❝[S7] |
| Read tags / Read counts / Read status of jobs | basic | Metadata-only reads; safe defaults. | sourced ❝[S7] |
| Read conversations | sensitive | Exposes customer message content — expect scrutiny in review. | sourced ❝[S7] |
| Write conversations | sensitive | Agent replies to and closes real customer conversations — the highest-risk write for an AI agent. | sourced ❝[S7] |
| Read tickets / Write tickets | sensitive | Write tickets is create-only per the table; still requires ticket scope justification in the video. | sourced ❝[S7] |
| Delete conversations and metrics | restricted | Irreversible; almost never justifiable for an assistant agent. | sourced ❝[S7] |
| Read admin activity logs | restricted | Teammate surveillance data — pairs badly with an agent's purpose. | sourced ❝[S7] |
| Canvas Kit default set (Read and list users and companies, Read conversations, Read admins, Gather App data) | gated | Auto-selected and cannot be deselected if the app uses Canvas Kit — you inherit four broad scopes whether or not your feature needs them. | sourced ❝[S7][S9] |
05If you get blocked
→ Ship the minimal feature→scope map; trim anything without a shipped feature, then resubmit on the Review changes tab.
→ Use a tunnel (ngrok/Cloudflare Tunnel) or a staging host with a real certificate; register the URL in the Redirect URLs section.
→ Host a privacy policy and end-user agreement before submitting; they are mandatory listing fields and platform requirements.
→ Detect region (or ask) and route EU→app.eu.intercom.com, AU→app.au.intercom.com; do not default everyone to the US host.
→ Pass the code verbatim, including the trailing '=', then retry the token POST.
→ Re-record showing the full client_id and state in the OAuth URL, the end-to-end feature, and uninstall.
06Evidence: what was tested, sourced, and still uncertain
Sources read
- [S1] Authentication | Intercom and Fin Developer Platform official
- [S2] Setting up OAuth | Intercom and Fin Developer Platform official
- [S3] Intercom Developers | Intercom and Fin Developer Platform official
- [S4] Building Successful Apps official
- [S5] Intercom Platform Guidelines official
- [S6] Rate Limiting official
- [S7] OAuth Scopes official
- [S8] App Review and Publishing official
- [S9] Setting up OAuth official
- [S10] Listing your App official
- [composio] Composio — Managed OAuth apps directory official
- [probe] Live HTTP probes run by the agent (dummy client_id, no credentials) probe
Still uncertain
- ? The fetched pages never state the access token's lifetime or whether a refresh token exists — the response shows only token_type/token/access_token. Assume re-authorization is required when a token dies; confirm before designing long-lived agent sessions.
- ? No PKCE, device flow, or dynamic client registration is documented; I infer it is a classic confidential-client authorization-code flow only. If your agent has no backend, that is a design blocker, not a documentation gap I can disprove.
- ? Sources [S1] and [S2] returned 404 — Intercom's docs moved; the live guidance is [S9] (setting-up-oauth.md). Old URLs may be in your bookmarks.
- ? The scope tier split in this guide (basic/sensitive/restricted/gated) is my judgement; Intercom publishes only a flat scope table plus the Canvas Kit forced set.
- ? Review duration conflicts between sources (up to 7 business days vs 7–14 days); neither states a rejection-resubmission turnaround.
- ? Whether App Partner Program details are required for unlisted apps is not stated — [S10] ties it to listing/appearing in the store, [S8] lists it as a sidebar form.
- ? Generated automatically; no app was registered and no review was submitted.