Skip to main content
This guide maps Fin (formerly Intercom) concepts to Courier, covers transactional and marketing sends, and lays out a phased plan. It says “Intercom” throughout, because the product surfaces and the API still call themselves Intercom. Intercom is a support platform, and doubling down on that. The company renamed itself Fin in May 2026, after its AI support agent. Salesforce has signed a definitive agreement to acquire it and fold that agent technology into Agentforce. Outbound messaging sits beside that focus, and the API shows where the investment went. Sends are modeled as support conversations owned by an agent seat. Push and SMS have no send endpoint. Campaign definitions can be exported but never created in code. Reasonable tradeoffs for a help desk, poor ones for the messages your product sends. A password reset, receipt, usage alert, or onboarding sequence needs a send API, per-channel routing, provider failover, preference enforcement, and delivery logs. Threading a conversation between a customer and an agent needs almost none of that. Most teams land on a split. Intercom keeps the help desk, and Courier takes over what your product sends. Courier’s UI and API are at full parity, so every Template, Journey, Audience, and Topic can be created programmatically. A coding agent with can do most of the mechanical translation, using the ready-made prompt below.

Map Intercom concepts to Courier

Series and Journeys

Intercom Series is the multi-step campaign builder: contacts enter on a rule or an event, then move through waits, splits, and sends. It requires the Proactive Support Plus add-on. Courier fill the same role, with : API invoke, inbound webhook, Segment event, and audience membership. Two node types have no Series equivalent:
  • and nodes collapse many events into one message. In Intercom, you precompute roll-ups in your own backend before firing the triggering event.
  • call an external API mid-journey and use the response in later steps.
Journeys are also . Intercom has no Series endpoint, so a Series exists only in the UI. Its one workflow endpoint, GET /export/workflows/{id}, is read-only, documented as an EU Data Act compliance export, and covers Workflows rather than Series. Either way, campaign definitions can’t be versioned as code.

Event-triggered messages and the Send API

This is the biggest change in the migration. Plan it first. Intercom’s POST /messages endpoint accepts message_type values of in_app, email, or whatsapp. There is no push or SMS send endpoint. Its template field is a message style (plain or personal), not a reference to content you built in the composer. So sending a designed message from your backend is indirect: post an event, and let a message you configured in the UI match on it.
That returns 202 Accepted with an empty body. Your code learns the event was accepted, not that a message was created. Intercom exposes no delivery status endpoint for email, push, or in-app. In Courier, the same send is explicit. You name the template, the recipient, and the data, and the response carries a requestId:
For a single-recipient send, that requestId is also the message’s ID. Use it to , , or . Sends to a list or audience derive a separate ID per recipient, which you look up through the . Several Intercom event constraints disappear with the switch. Check each against your setup:
  • Intercom caps a workspace at 120 active event names, and each event can drive at most 50 live proactive support messages. Courier templates are addressed by ID, so there is no shared namespace to run out of.
  • Intercom events are flat. Its API docs state that nested JSON is not supported. Courier data and both take arbitrary nested JSON, so an order with line items goes through as-is.
  • Intercom de-duplicates events on workspace, contact, event name, and created_at at second granularity, and drops duplicates with a 202. Two legitimate identical sends in the same second collapse into one. Courier treats every send request as its own message.
  • New Intercom event metadata can take up to 24 hours to become available in the message composer and filters. Courier templates reference variables directly, so a new field is usable on the next send.
  • An Intercom outbound message can carry only one event-based rule, and event-triggered messages are not eligible for re-notification.

Transactional sending

Intercom supports transactional messaging on email, in-product messages, and push, and transactional email can reach unsubscribed contacts. Two things usually drive the migration: It is an add-on, not a mode. Transactional and event-triggered messaging require the Proactive Support Plus add-on. Courier has no transactional subsystem to enable. Every send goes through the same pipeline, and you control preference enforcement per topic by marking a as required. Sending is on shared infrastructure. Intercom’s docs state that dedicated IP addresses aren’t available and that all email goes over shared IPs. There is no option to send through your own email provider. Intercom also documents activity-based sending restrictions. When triggered, these limit email to contacts seen, heard from, or engaged within the last 180 days. Event-driven email usually delivers in seconds, but can be delayed up to 30 minutes under load. Courier sends through . Your SendGrid, SES, Postmark, Twilio, or FCM credentials, your domains, your reputation, your dedicated IP if you have one. Courier adds orchestration on top: , , and . If a provider degrades, you swap it in Courier without redeploying.

Contacts, custom attributes, and user profiles

Intercom contacts carry standard fields plus custom attributes defined through data attributes. Courier are JSON documents keyed by user_id. The translation is direct: the contact’s external_id becomes the Courier user_id, channel addresses (email, phone_number, push tokens) become profile addresses, and custom attributes become profile attributes. Because profiles accept nested JSON, attribute structures you had to flatten for Intercom can keep their shape. Load contacts with the , or create them inline: sending to an unknown user_id with profile data creates the user. Intercom segments become , which recalculate automatically as profile attributes change. Push tokens are the one item to plan around. Intercom collects device tokens through its mobile SDK, so they live inside Intercom rather than in your data. Register tokens with Courier’s from your app, and run both in parallel until coverage is high enough to cut over.

Keeping Intercom for support

This migration does not touch the help desk. Messenger, the Intercom Inbox, tickets, Workflows, Help Center, and Fin all stay where they are. One sync keeps the two in step:
  1. Your application is the source of truth for who the user is and what they did.
  2. Into Courier: upsert with identifiers, channel addresses, and the attributes you segment or personalize on.
  3. Into Intercom: keep sending the contact updates and events your support team reads for context in the Intercom Inbox.
Events you fired only to trigger outbound messages can stop. Events your agents read in the contact timeline keep going.

Subscription Types and preferences

Intercom Subscription Types support opt-in and opt-out consent, and their content_types field accepts email or sms_message, so consent covers only those two channels. Courier cover every channel, including push and in-app, and Courier enforces them at send time. Each topic can be opt-in or opt-out, required, or channel-specific, so a user can keep receipts on email while turning off push for the same topic. Map each Subscription Type to a preference topic and import the opt-out state before your first send. Intercom’s GET /contacts/{id}/subscriptions returns only the subscriptions a contact explicitly set. Contacts sitting on a default are absent from the response, so decide each topic’s default in Courier deliberately rather than inferring it. Courier gives you a , or to build the preference center into your product.

Frequency capping

Intercom controls volume per message: you set how often a message can send and cap total occurrences per contact. Courier has two mechanisms that work across messages. cap volume globally, per user, per subscription topic, or per tenant. The window is an hour, day, week, month, or billing period. A blocked message shows THROTTLED in the logs. cap how many times a user or the whole population passes a point in a journey.

In-product messages

The Intercom Messenger renders Intercom’s in-product surfaces: Posts, Banners, Carousels, Tooltips, Checklists, and News items. Coverage varies by surface. Banners, for example, run on desktop and mobile web but not inside iOS and Android apps. The closest Courier equivalent is , a notification feed with read and unread state, , and . It ships as components for , , and mobile. A feed is not a Messenger replacement, so the mapping is not one to one:
  • Posts and News items map cleanly to Courier Inbox messages.
  • Banners are on the Courier roadmap as a first-class in-app surface. Until they ship, either keep banners in Intercom or render one in your own UI over Courier Inbox data. If banners are load-bearing for you, scope them separately rather than blocking the cutover on them.
  • Tooltips, Checklists, Product Tours, and Carousels are in-product guidance and onboarding UI. Those stay in Intercom or move to a product-adoption tool. Courier does not replace them.
Billing works differently here too. Intercom meters Posts, Mobile Push, Product Tours, Carousels, and Surveys under a single “Messages Sent” metric. The allowance comes with the Proactive Support Plus add-on, so in-product messages and push draw down the same pool.

Personalization and localization

Intercom personalizes with attribute insertion and fallbacks in the composer. Event-triggered messages can also use event metadata, limited to the first metadata keys on the event. The attribute has to exist on the contact, or the value has to arrive as flat event metadata. Courier templates use in single curly brackets. They resolve from four sources rather than one: Anything not prefixed resolves against data, so {orderId} and {data.orderId} are the same. Nested paths work, so {order.shipping.carrier} renders without flattening the payload first. The tenant source has no Intercom equivalent. If you send on behalf of customer accounts, per-account values live on the . Company name, support address, and logo stop being copied onto every user profile or passed on every send. For localization, Intercom’s documented pattern is one message per language, targeted with an audience rule on the contact’s language. Courier keeps locales on a single template: set locale on the profile or the send request, and Courier renders the matching version. Manage translations through or the .

Authentication

Intercom authenticates with a workspace access token. Its rate limit is 10,000 API calls per minute per app and 25,000 per workspace, enforced in ten-second buckets. Courier uses : a bearer token per workspace, with separate keys for test and production. Client-side surfaces like Courier Inbox use short-lived scoped to a single user.

Plan the migration

Do transactional first. Those sends are already API-driven and carry the most risk if they break. They are also the ones Intercom’s shared sending and 30-minute delay ceiling serve least well. Marketing sends are less urgent and take longer to rebuild.

Phase 1: Inventory

  1. List every live outbound message and Series. Note the trigger, channels, and audience for each. No endpoint returns Series definitions, so take these from the Outbound list filtered to live messages. For per-message volume, POST /export/content/data exports delivery and engagement data for outbound content, Series included, over a date range. One active job per workspace.
  2. Split the list into transactional, marketing, and in-product. Transactional is anything a user action must produce: password resets, receipts, confirmations, alerts. In-product is banners, tours, tooltips, and checklists. Those stay in Intercom or move elsewhere.
  3. List the events you fire. Mark which ones exist only to trigger a message and which ones your support team reads in the Intercom Inbox. The first group retires. The second stays.

Phase 2: Transactional

  1. Connect your providers. Add your email, SMS, and push provider credentials in Courier and verify your sending domains. You are moving off shared IPs, so check domain authentication before the first production send.
  2. Set up the profile sync. Upsert user_id, channel addresses, and the attributes your templates need. Start registering push tokens with Courier from your app now, in parallel with the Intercom SDK, so tokens accumulate ahead of the push cutover.
  3. Rebuild the highest-volume transactional templates in , with content for each channel the message sends on.
  4. Replace event posts with send calls. Each POST /events that existed only to trigger a message becomes a naming the template and passing data. Usually a small diff, and it removes an indirection: the call now returns an ID you can trace to delivery status.
  5. Run in parallel and compare. Send to a test audience through both systems, diff the rendered output, then cut over one message type at a time. Watch the rather than the calendar.

Phase 3: Preferences

  1. Map Subscription Types to preference topics, decide the default for each, and import opt-outs before any marketing send. Do this before Phase 4, not during it.

Phase 4: Marketing

  1. Rebuild Series as journeys, starting with onboarding. Recreate the trigger, then the nodes. Where a Series precomputed a roll-up in your backend, replace that with a or node.
  2. Convert segments to audiences. Segment rules become audience filters on profile attributes, and membership updates itself as profiles change.
  3. Move one-off sends to : pick a template, pick an audience, send now or schedule it.
  4. Add frequency caps. Per-message rules in Intercom become that hold across every journey and broadcast.

Phase 5: Decommission

  1. Pause the Intercom message, don’t delete it, once its Courier replacement has run clean for a full cycle.
  2. Drop the Proactive Support Plus add-on when no live message needs it, and stop firing the events that existed only to trigger sends.

Migrate with an AI agent

Most of this migration is mechanical: read a message definition, create the equivalent template, rewrite the call site. That suits a coding agent well. Three things to set up first:
  • teaches the agent Courier’s real APIs and patterns, so it stops guessing at endpoints:
    In Claude Code you can install it as a plugin instead, which self-updates and ships the Courier docs MCP server.
  • gives the agent direct access to your workspace. It can create templates, build journeys, upsert users, and read send logs as it works. See for setup in Claude Code, Cursor, Codex, and VS Code.
  • Docs for agents. Point it at llms-full.txt when it needs API detail beyond this page.
Then start it with a prompt like this one. Fill in the bracketed parts.
Review the classification in step 2 closely. Whether a message counts as transactional decides whether its preference topic is marked required. Getting it backwards means a receipt users can unsubscribe from, or a marketing email they cannot.

FAQ

Most teams keep both. Intercom keeps the help desk: Messenger, the Intercom Inbox, tickets, Help Center, Workflows, and Fin. Courier takes over the notifications your product sends. Keep sending Intercom the contact updates and events your agents read for context, and retire only the events that existed to trigger outbound messages.
. Entry rules become : API invoke, inbound webhook, Segment event, or audience membership. Series nodes map across too. Waits become , rules branches become , and messages become . Journeys add , , , and nodes, and they can be .
Call the with the template and recipient. Intercom has no push send endpoint. Triggering push from code meant posting an event and matching it against a message configured in the UI. In Courier the send is explicit and returns an ID you can trace through to .
Tokens collected by Intercom’s mobile SDK live in Intercom. Start registering tokens with Courier’s from your app while Intercom is still live. Let coverage build across a release cycle or two, then cut push over. Plan this early, since it moves at the speed of app adoption rather than your backend deploys.
You improve your control over it. Intercom sends over shared IPs and does not support bringing your own email provider. Courier sends through , so your domains, reputation, and dedicated IP if you have one carry over. Authenticate your sending domain with your provider before the first production send.
The help desk (Messenger, the Intercom Inbox, tickets, Workflows), the Help Center and Articles, and Fin with the AI agent surfaces. Also in-product guidance UI such as Tooltips, Product Tours, Checklists, and Carousels. In-app banners are on the Courier roadmap. Courier replaces message delivery and orchestration: transactional sends, campaigns, journeys, templates, preferences, and the in-app notification feed.