Saaspocalypse
The migration runbook

Migrating off Intercom — phase by phase.

Intercom migrations have three quirks worth knowing: the conversations API uses cursor pagination and is rate-limited at ~1,000 requests/min, the Messenger widget identifies users via a signed `user_hash` you'll need to mint from your own backend, and Help Center articles live on an intercom.help subdomain whose URLs you'll want to mirror (or 301-redirect) to preserve SEO equity.

8-12 weeks end-to-endFixed priceParallel run before cutoverYou own the code

The phases, tuned to Intercom

Each phase below is the Intercom-specific version of our standard playbook. Same shape every engagement, different specifics per SaaS.

  1. Workflow & macro audit

    1-2 weeks

    We inventory every Trigger, Workflow, Macro, Series and Custom Bot before touching the data. Most teams find that 30+ rules accumulated over years collapse to 8-10 once you remove duplicates and dead branches.

    Export and read every Workflow + Custom Bot config (the JSON isn't reimportable but it's a good starting reference)
    List every Macro and tag the ones that haven't fired in 90 days
    Map the Inbox routing rules to a state machine on paper
    Identify which Fin AI Topics are doing real work vs. acting as fallbacks
    List the Help Center articles by URL path so we can plan 301s
    You walk away with

    A Workflow & Macro Inventory listing what we'll port, what we'll drop, and the URL list for the Help Center redirect map.

  2. Schema + Postgres model design

    1 week

    Conversations, contacts, companies, tags, and articles get a properly-normalised Postgres model. Intercom IDs get preserved as columns so any external system pointing at them keeps working.

    Design tables: conversations, conversation_parts, contacts, companies, tags, articles, collections
    Preserve `intercom_id` on every record (indexed) for backwards compatibility
    Plan a GIN index on conversation parts for full-text search
    Design the article schema as MDX-on-disk + a search index (Typesense or Postgres tsvector)
    Sign DPA + sub-processor list with your team
    You walk away with

    Schema migrations checked into git + a published sub-processor list.

  3. Extract via REST API

    1-2 weeks

    We pull conversations, contacts, companies, tags and Help Center content via the Intercom REST API. The conversations endpoint is the slow one — cursor pagination plus the rate limit means it's the long pole.

    Authenticate via Personal Access Token (or OAuth if multi-workspace)
    Iterate conversations with `?starting_after={cursor}` until exhausted
    Pull each conversation's `parts` (replies, notes, assignments) — that's where the real content lives
    Extract Help Center articles + collections + sections (preserving the slug for redirects)
    Throttle the extractor to stay under 1,000 req/min; the resumable cursor means it's restartable
    You walk away with

    A re-runnable extract script + a reconciliation report against your Intercom Reports totals.

  4. Build + weekly demos

    4-6 weeks

    Postgres-backed Inbox, a lean React Messenger widget shipped from your CDN, a Next.js Help Center on your own domain, and an LLM-backed AI assist that lives in your repo.

    Build the Inbox: assignment, threads, full-text search across closed tickets (a single GIN index)
    Build the Messenger widget: lazy-loaded, opens a WebSocket only on click, mint `user_hash` server-side for identity
    Migrate the Help Center to MDX articles served from your own domain (links no longer rel=nofollow by default)
    Wire Claude or GPT for AI assist — your prompts live in git, you pay your model provider directly
    Outbound runs on Inngest + Resend — no $99 add-on, no 500-message cap
    You walk away with

    A working chat + helpdesk + KB on a staging domain, with your team handling 10% of live tickets through it by end of phase.

  5. Parallel run + Messenger cutover

    2-3 weeks

    Both Messenger widgets coexist behind a feature flag while we ramp the rollout from 10% to 100% of visitors. Inbound emails go to both inboxes; replies sync via a webhook bridge.

    Dual-write inbound emails to both systems via a Cloudflare worker bridge
    Ramp the new Messenger widget from 10% → 50% → 100% over two weeks
    Disable Fin AI Triggers on the Intercom side to stop the per-resolution clock
    Daily reconciliation: tickets opened/closed, SLA breaches, CSAT averages
    Train your agents in two 60-minute sessions, recorded for the rest
    You walk away with

    A reconciliation dashboard + signed sign-off from the head of support.

  6. Cutover + Intercom read-only

    1 day + 90-day fallback

    We flip DNS for the Help Center subdomain, swap the Messenger script tag for the new widget, and lock Intercom to read-only. 301 redirects keep the SEO equity from the old /hc/ URLs.

    Deploy the 301 redirect map for every /hc/ article URL → new path
    Swap the Messenger snippet on the production site
    Cut email routing to the new Inbox
    Lock Intercom to read-only (revoke write permissions on the workspace)
    Cancel auto-renewal in writing the same day
    You walk away with

    Cutover Runbook + 301 redirect map + a quiet inbox where the renewal email used to land.

The Intercom APIs we'd actually hit

Concrete endpoints we use to extract your data during the parallel-run phase. We keep the extract scripts — they're useful at every renewal.

List conversations
GET https://api.intercom.io/conversations
Paginate every conversation via the `starting_after` cursor. The slow lane — plan for it.
Get conversation
GET https://api.intercom.io/conversations/{id}
Pull every part (reply / note / assignment) of a conversation in full detail
Search conversations
POST https://api.intercom.io/conversations/search
Targeted re-extraction during reconciliation (e.g. only conversations updated since timestamp X)
List contacts
GET https://api.intercom.io/contacts
Pull every contact + their custom attributes
List companies
GET https://api.intercom.io/companies
Pull every company / account record
List articles
GET https://api.intercom.io/articles
Extract every Help Center article (title, body, state, collection)
List collections
GET https://api.intercom.io/help_center/collections
Preserve the article taxonomy + URL hierarchy for the redirect map
List tags
GET https://api.intercom.io/tags
Migrate the tag taxonomy so search and segmentation keep working

The Intercom-specific gotchas

Things we've learnt the hard way (or that the documentation understates). We'll surface these on the kickoff call so nobody is surprised in week 6.

What stays where it is

Migrations work because they're scoped honestly. Here's what we don't move — by design.

  • ·Fin AI prompts and topics — replaced with Claude/GPT calls in your own code, with your help articles as the retrieval source
  • ·Custom Bots — rewritten as TypeScript flows you can read in a PR
  • ·Series outbound campaigns — rebuilt on Inngest + Resend with no 500-message cap
  • ·Marketplace / Connector apps — replaced by direct API calls to the underlying SaaS
  • ·Native mobile SDKs — most teams use email + web chat; if mobile push matters we scope it separately
  • ·Phone / Switch — telephony stays in your existing dialer (Aircall, Dialpad, Twilio)

Get a Intercom-shaped migration plan.

Tell us your seat count, contract end date, and the integrations you can't lose. We'll come back within a business day with a fixed-price scope and a timeline tuned to your renewal.

Scope a Intercom migration

One business day. NDA + DPA on request.