Skip to main content
RapidDev - Software Development Agency
lovable-integrationsEdge Function Integration

How to Integrate Lovable with Intercom

To integrate Intercom with Lovable, generate an access token from your Intercom Developer Hub app, store it in Cloud → Secrets, then build Edge Functions that proxy calls to the Intercom REST API for conversations, contacts, companies, and articles. Intercom's conversational-first approach makes it ideal for building in-app messaging features, user onboarding flows, and help center widgets inside Lovable apps.

What you'll learn

  • How to create an Intercom app in Developer Hub and generate an access token with the correct API scopes
  • How to store Intercom credentials securely in Lovable Cloud → Secrets
  • How to create Edge Functions that create and update contacts, send messages, and fetch conversations
  • How to embed the Intercom Messenger widget in a Lovable React app for live in-app chat
  • When to choose Intercom versus Zendesk for customer support integration with a Lovable app
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate14 min read30 minutesCRMMarch 2026RapidDev Engineering Team
TL;DR

To integrate Intercom with Lovable, generate an access token from your Intercom Developer Hub app, store it in Cloud → Secrets, then build Edge Functions that proxy calls to the Intercom REST API for conversations, contacts, companies, and articles. Intercom's conversational-first approach makes it ideal for building in-app messaging features, user onboarding flows, and help center widgets inside Lovable apps.

Add conversational messaging and help center features to Lovable with Intercom's API

Intercom pioneered the in-app messaging bubble that has become standard in modern SaaS products. Unlike Zendesk's ticket-queue approach, Intercom is designed for conversations — real-time messaging between users and support teams, triggered onboarding flows, and proactive outreach based on user behavior. For Lovable apps targeting paying SaaS customers, Intercom integration creates a native-feeling support experience directly embedded in your product.

Intercom's integration approach has two distinct layers. The first is the Messenger widget — a JavaScript-based chat bubble embedded in your app that handles real-time conversation UI natively. The second is the REST API — used for creating and updating contacts (Intercom's term for users), managing companies, fetching conversation history, and accessing the help center knowledge base. For Lovable apps, the Messenger widget handles real-time chat while Edge Functions handle the API operations that require server-side credentials.

The Intercom REST API v2 uses Bearer token authentication from a custom Developer Hub application. Unlike HubSpot's Private Apps, Intercom access tokens do not expire — they are permanent until you regenerate them. API scopes determine what the token can access: reading contacts, writing messages, managing companies, and so on. All API calls include the header 'Intercom-Version: 2.11' to target the current stable API version.

The most common Lovable + Intercom pattern is a hybrid: embed the Messenger widget for real-time chat, use Edge Functions to create or update Intercom contact records when users sign up or perform key actions, and query the Intercom Articles API to render help center content inside your app without redirecting users to a separate help site.

Integration method

Edge Function Integration

Intercom has no native Lovable connector. All messaging and CRM operations are proxied through Lovable Edge Functions that call the Intercom REST API v2. The access token from a custom Intercom app is stored in Cloud → Secrets and accessed via Deno.env.get(), keeping credentials server-side and avoiding CORS restrictions on direct browser calls to Intercom's API.

Prerequisites

  • A Lovable project with Lovable Cloud enabled (Edge Functions require a deployed app)
  • An Intercom workspace (free trial available at intercom.com — note that API access requires a paid plan for production use)
  • Access to create apps in Intercom Developer Hub (developer.intercom.com)
  • Basic familiarity with Intercom concepts: contacts (users), companies, conversations, and the Messenger widget

Step-by-step guide

1

Create an Intercom app in Developer Hub and get an access token

Intercom uses app-based authentication via its Developer Hub. Each integration requires creating a custom app in Developer Hub, which provides an access token scoped to the permissions you configure. Go to developer.intercom.com and sign in with your Intercom account. Click 'New App' in the top right. Give your app a name (e.g., 'Lovable Integration') and select the workspace it should connect to. If you have multiple workspaces (e.g., development and production), create separate apps for each. After creation, go to the 'Authentication' section of your new app. You will see an 'Access Token' — copy this immediately. Intercom access tokens are long strings starting with 'dG9r...' (base64 encoded). Unlike many OAuth2 services, Intercom access tokens do not expire automatically, so you do not need to implement token refresh logic. Configure the appropriate API scopes for your integration. Click 'Permissions' in the left sidebar of your app settings. Enable: - Read contacts (for fetching user data) - Write contacts (for creating/updating contacts) - Read conversations (for fetching support conversations) - Write conversations (for sending messages) - Read articles (for help center content) Enable only the scopes you actually need. Overly permissive tokens create unnecessary security exposure. Also note your Intercom App ID — a short alphanumeric string visible in your workspace URL or in the app settings. This is used for configuring the Messenger widget (not the API), but you will need it when adding the chat widget to your Lovable app. Store it as INTERCOM_APP_ID in secrets alongside the access token.

Pro tip: Intercom Developer Hub apps exist per workspace — if you want to test with a sandbox workspace and deploy with your production workspace, you need two separate apps with two separate access tokens. Store them as INTERCOM_ACCESS_TOKEN_DEV and INTERCOM_ACCESS_TOKEN_PROD and switch based on your deployment environment.

Expected result: An Intercom Developer Hub app is created with the appropriate API scopes. You have copied the access token and noted the App ID. Both are ready to be stored in Lovable Cloud → Secrets.

2

Store credentials in Cloud Secrets and configure the Messenger widget

Add Intercom credentials to Lovable's Cloud Secrets panel. In Lovable, click the '+' icon at the top to open the Cloud panel, navigate to Secrets, and add: - INTERCOM_ACCESS_TOKEN — the access token from Developer Hub (the long dG9r... string) - INTERCOM_APP_ID — your workspace App ID (short alphanumeric, used for the Messenger widget) The App ID is different from the access token. It is the public identifier used to initialize the Messenger widget in your frontend code. It is safe to include in client-side code (it is not a secret) but storing it in secrets makes it easy to switch workspaces without code changes. For the Messenger widget (the live chat bubble), Intercom provides a JavaScript snippet that initializes in the browser. In Lovable, you can initialize the Messenger by adding the Intercom script to your React app's main component. The Intercom object is added to window and initialized with your App ID. You can also pass user identity information (user_id, email, name) when initializing, which associates the conversation with the correct Intercom contact. For user identity verification (a security feature that prevents users from impersonating each other in the Messenger), Intercom requires you to generate an HMAC signature server-side using your Identity Verification Secret. This signature is computed in an Edge Function and passed to the frontend at runtime — it should never be computed client-side.

Lovable Prompt

Add the Intercom Messenger widget to my Lovable app. Initialize window.Intercom with the INTERCOM_APP_ID from environment config (not secrets — it is a public value). When a user is logged in, pass their userId, email, and name to the Intercom initialization to associate conversations with their contact record. Show the Messenger on all pages by calling window.Intercom('show') when the help button is clicked.

Paste this in Lovable chat

src/components/IntercomProvider.tsx
1// src/components/IntercomProvider.tsx
2import { useEffect } from 'react'
3import { useAuth } from '@/hooks/useAuth'
4
5declare global {
6 interface Window {
7 Intercom: (...args: unknown[]) => void
8 intercomSettings: Record<string, unknown>
9 }
10}
11
12export function IntercomProvider({ children }: { children: React.ReactNode }) {
13 const { user } = useAuth()
14 const appId = import.meta.env.VITE_INTERCOM_APP_ID
15
16 useEffect(() => {
17 if (!appId) return
18
19 // Load Intercom script
20 const script = document.createElement('script')
21 script.innerHTML = `
22 (function(){var w=window;var ic=w.Intercom;
23 if(typeof ic==="function"){ic('reattach_activator');ic('update',w.intercomSettings);}
24 else{var d=document;var i=function(){i.c(arguments);};i.q=[];i.c=function(args){i.q.push(args);};
25 w.Intercom=i;var l=function(){var s=d.createElement('script');
26 s.type='text/javascript';s.async=true;
27 s.src='https://widget.intercom.io/widget/${appId}';
28 var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s,x);};
29 if(document.readyState==='complete'){l();}else if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}}})();
30 `
31 document.head.appendChild(script)
32
33 return () => { document.head.removeChild(script) }
34 }, [appId])
35
36 useEffect(() => {
37 if (!window.Intercom || !appId) return
38 if (user) {
39 window.Intercom('boot', {
40 app_id: appId,
41 user_id: user.id,
42 email: user.email,
43 name: user.user_metadata?.full_name || user.email,
44 })
45 } else {
46 window.Intercom('boot', { app_id: appId })
47 }
48 }, [user, appId])
49
50 return <>{children}</>
51}

Pro tip: Add VITE_INTERCOM_APP_ID to your Lovable project's environment config (not Cloud Secrets — it is a public value safe for the frontend). The access token (INTERCOM_ACCESS_TOKEN) remains in Cloud Secrets and is only used by Edge Functions.

Expected result: The Intercom Messenger bubble appears in the bottom-right corner of your deployed Lovable app. When clicked, it opens a conversation window. Logged-in users are identified by their email in the Intercom inbox.

3

Create the Intercom REST API proxy Edge Function

Build the Edge Function that handles Intercom REST API operations: creating and updating contacts, fetching conversations, and querying help center articles. These server-side operations require the access token and cannot be performed from the browser. Intercom API v2 uses consistent REST patterns. All requests include the 'Intercom-Version: 2.11' header to target a stable API version. Contacts are created via POST /contacts with a 'role' field ('user' for customers, 'lead' for anonymous visitors). The upsert pattern for contacts uses POST /contacts with an external_id that matches your app's user ID — if a contact with that external_id exists, it is updated; otherwise, a new contact is created. Companies are created separately via POST /companies and linked to contacts via POST /contacts/{id}/companies. For SaaS products with account-based pricing, maintaining company records in Intercom enables segment-based messaging and company-level analytics. For article search, the Articles API is at GET /articles with a ?phrase= search parameter. Articles can also be browsed by collection via GET /help_center/collections/{id}/articles. Intercom uses cursor-based pagination with a 'pages' object in list responses containing 'next' and 'total_pages'. For small result sets (under 50 items), one page is usually sufficient. For larger datasets, implement cursor pagination by passing the 'starting_after' query parameter.

Lovable Prompt

Create an Edge Function called intercom-api at supabase/functions/intercom-api/index.ts. Accept POST with { action, params }. Support actions: upsert_contact, get_contact, search_articles, send_message, list_conversations. Use INTERCOM_ACCESS_TOKEN from secrets. Include 'Intercom-Version: 2.11' header on all requests. Return the Intercom API response. Include CORS headers.

Paste this in Lovable chat

supabase/functions/intercom-api/index.ts
1import { serve } from 'https://deno.land/std@0.168.0/http/server.ts'
2
3const corsHeaders = {
4 'Access-Control-Allow-Origin': '*',
5 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
6}
7
8const INTERCOM_BASE = 'https://api.intercom.io'
9
10function intercomHeaders() {
11 const token = Deno.env.get('INTERCOM_ACCESS_TOKEN')
12 if (!token) throw new Error('INTERCOM_ACCESS_TOKEN not configured')
13 return {
14 Authorization: `Bearer ${token}`,
15 'Content-Type': 'application/json',
16 'Intercom-Version': '2.11',
17 }
18}
19
20serve(async (req) => {
21 if (req.method === 'OPTIONS') return new Response('ok', { headers: corsHeaders })
22
23 try {
24 const { action, params = {} } = await req.json()
25 const headers = intercomHeaders()
26 let resp: Response
27
28 switch (action) {
29 case 'upsert_contact':
30 resp = await fetch(`${INTERCOM_BASE}/contacts`, {
31 method: 'POST',
32 headers,
33 body: JSON.stringify({
34 role: params.role || 'user',
35 external_id: params.userId,
36 email: params.email,
37 name: params.name,
38 custom_attributes: params.customAttributes || {},
39 }),
40 })
41 break
42
43 case 'get_contact':
44 resp = await fetch(`${INTERCOM_BASE}/contacts/${params.contactId}`, { headers })
45 break
46
47 case 'search_articles':
48 resp = await fetch(`${INTERCOM_BASE}/articles?phrase=${encodeURIComponent(params.query || '')}&state=published`, { headers })
49 break
50
51 case 'send_message':
52 resp = await fetch(`${INTERCOM_BASE}/messages`, {
53 method: 'POST',
54 headers,
55 body: JSON.stringify({
56 message_type: params.messageType || 'inapp',
57 subject: params.subject || '',
58 body: params.body,
59 template: 'plain',
60 from: { type: 'admin', id: params.adminId },
61 to: { type: 'user', id: params.contactId },
62 }),
63 })
64 break
65
66 case 'list_conversations':
67 resp = await fetch(`${INTERCOM_BASE}/conversations?contact_id=${params.contactId}&display_as=plaintext`, { headers })
68 break
69
70 default:
71 return new Response(JSON.stringify({ error: 'Unknown action' }), {
72 status: 400, headers: { ...corsHeaders, 'Content-Type': 'application/json' },
73 })
74 }
75
76 const data = await resp.json()
77 return new Response(JSON.stringify(data), {
78 status: resp.ok ? 200 : resp.status,
79 headers: { ...corsHeaders, 'Content-Type': 'application/json' },
80 })
81 } catch (error) {
82 return new Response(JSON.stringify({ error: error.message }), {
83 status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' },
84 })
85 }
86})

Pro tip: When upserting contacts, use your app's internal user ID as the external_id. This ensures Intercom correctly identifies returning users and merges contact data rather than creating duplicates. The external_id is the bridge between your Supabase user records and Intercom contacts.

Expected result: The intercom-api Edge Function deploys in Cloud → Edge Functions. Test with action 'search_articles' and a query term — published articles from your Intercom help center should appear in the response.

Common use cases

Sync new user signups to Intercom as contacts with custom attributes

When a new user registers in your Lovable app, create or update their Intercom contact record with custom attributes like plan, signup source, company size, and feature flags. This gives your Intercom inbox rich context about each user, enabling personalized support messages and automated onboarding sequences triggered by contact attributes. Contacts created via API are immediately visible to your support team in the Intercom inbox.

Lovable Prompt

Create an Edge Function called intercom-contact that accepts { userId, email, name, company, plan, signupSource } and creates or updates an Intercom contact using INTERCOM_ACCESS_TOKEN from secrets. Set custom attributes for plan and signupSource. Use the upsert pattern (POST to contacts with role: 'user'). Return the contact ID. Call this from my registration success handler alongside the Supabase user creation.

Copy this prompt to try it in Lovable

Render Intercom help center articles inside your Lovable app

Instead of redirecting users to a separate help.yourcompany.com site, fetch Intercom Articles directly into your Lovable app. An Edge Function queries the Intercom Articles API for articles matching a search term or category, and a React component renders the content inline. Users get contextual help without leaving your product, and you maintain one source of truth in Intercom for all help content.

Lovable Prompt

Create an Edge Function called intercom-articles that accepts { query, collectionId } and searches Intercom help center articles using INTERCOM_ACCESS_TOKEN from secrets. Return article id, title, body (HTML), and url. Then build a Help Center component in Lovable with a search bar and article list. When a user clicks an article, render the body content in a modal with the article title as the heading.

Copy this prompt to try it in Lovable

Proactive in-app message when users hit a usage limit

When a user hits a usage limit in your Lovable app (API quota, storage full, feature gated), automatically send them a proactive Intercom message via the API offering to upgrade or explaining next steps. The Edge Function creates an in-app message directed at the user's contact ID with a call-to-action linking to your pricing page or upgrade flow.

Lovable Prompt

Create an Edge Function called intercom-message that accepts { contactId, messageType, body, ctaText, ctaUrl } and sends an in-app message to an Intercom contact using INTERCOM_ACCESS_TOKEN from secrets. Use the admin-initiated conversation endpoint. Return the conversation ID. Call this function when a user's storage hits 90% capacity, sending a message about upgrading their plan.

Copy this prompt to try it in Lovable

Troubleshooting

Intercom API returns 401 Unauthorized on all requests

Cause: The access token is missing, expired, or was created for a different Intercom workspace than the one you are targeting.

Solution: In Cloud → Secrets, verify INTERCOM_ACCESS_TOKEN is present and correct. In Intercom Developer Hub, check the app's 'Authentication' section to confirm the token matches. Also verify the app is connected to the correct workspace — if you have multiple Intercom workspaces, each requires its own Developer Hub app and token.

Intercom Messenger widget does not appear on the page after adding the script

Cause: The Intercom app is not correctly initialized, or the VITE_INTERCOM_APP_ID environment variable is not available in the browser bundle.

Solution: Ensure VITE_INTERCOM_APP_ID is set as a build-time environment variable (not in Cloud Secrets, which are server-only). In Lovable, this should be configured as a regular environment variable accessible via import.meta.env.VITE_INTERCOM_APP_ID. Also verify the boot call includes the app_id field — Intercom will silently fail to show the widget if app_id is missing or undefined.

Intercom returns 'User not found' when trying to send a message or fetch conversations

Cause: The contact ID used in the request does not exist in the Intercom workspace, or the contact was created in a different workspace.

Solution: Contact IDs in Intercom are workspace-specific. Always upsert the contact using your app's user ID as external_id before performing operations, and use the Intercom contact ID from the upsert response for subsequent calls. Store the Intercom contact ID in your Supabase users table to avoid repeated lookups.

Duplicate contacts are being created in Intercom for the same user

Cause: Contacts are being created without a consistent external_id, so Intercom cannot match new contacts to existing ones.

Solution: Always include the external_id field in contact creation, set to your app's internal user ID. Intercom uses external_id as the deduplication key when upserting. Without it, each API call creates a new contact even for the same email address. If duplicates already exist, use the Intercom dashboard's 'Merge contacts' feature to consolidate them.

typescript
1// Always include external_id in contact creation:
2body: JSON.stringify({
3 role: 'user',
4 external_id: params.userId, // required for deduplication
5 email: params.email,
6 name: params.name,
7})

Best practices

  • Always set external_id to your app's user ID when creating Intercom contacts — this is the key to deduplication and ensures Intercom can match users across multiple touch points.
  • Use the Intercom Messenger widget for real-time conversations and the REST API via Edge Functions for programmatic operations — never try to do real-time messaging through API polling.
  • Store the Intercom contact ID in your Supabase users table after the first upsert so future operations use direct contact IDs instead of search queries.
  • Implement Intercom Identity Verification (HMAC signature) for production apps — it prevents users from impersonating each other in the Messenger by requiring a server-generated signature.
  • Use custom_attributes sparingly and name them clearly — Intercom limits the number of custom attributes and poorly named attributes clutter your contact records for your support team.
  • Trigger contact upserts on significant user events (signup, upgrade, feature activation) rather than on every page view to avoid unnecessary API calls and rate limiting.
  • Always include the 'Intercom-Version: 2.11' header in API requests — without it, Intercom uses an older default API version that may have different response shapes.

Alternatives

Frequently asked questions

Can I use Intercom for free with Lovable?

Intercom offers a 14-day free trial and a free plan for early-stage startups (less than $1M in funding with fewer than 5 team seats — apply at intercom.com/early-stage). The standard paid plans start at $74/month for the Essential plan. API access is available on all plans. For most Lovable integrations, the Messenger widget and basic contact management work within the free trial period while you evaluate fit.

What is the difference between Intercom contacts, leads, and users?

In Intercom's current data model (API v2), all individuals are 'contacts' with a 'role' property: 'user' for known, logged-in customers and 'lead' for anonymous visitors. Older Intercom documentation uses the terms 'users' and 'leads' as separate endpoints — these were merged in API v2. When creating contacts from your Lovable app for known users, always use role: 'user' with their email and external_id.

How do I prevent duplicate Intercom contacts from multiple sign-up paths?

The key is always passing an external_id set to your app's internal user ID when creating contacts. Intercom treats external_id as the deduplication key — if a contact with the same external_id exists, it is updated rather than duplicated. Never create contacts without external_id set, and use the upsert endpoint (POST /contacts) rather than checking for existence first.

Can I embed Intercom help center articles inside my Lovable app without iframes?

Yes — the Intercom Articles API returns article content as HTML body text, which you can render directly in your React components. Fetch articles via your Edge Function's search_articles action and render the HTML content using React's dangerouslySetInnerHTML, or use a sanitization library like DOMPurify to clean the HTML before rendering. This gives you fully embedded help content styled to match your app's design, with no iframe required.

How do I handle Intercom Identity Verification for security?

Intercom Identity Verification prevents users from changing their user_id or email in the browser to impersonate other users. Enable it in your Intercom app settings (Settings → Installation → Identity Verification). Then create an Edge Function that accepts your app's user ID and returns an HMAC-SHA256 signature computed using your Identity Verification Secret (stored in Cloud → Secrets). Pass this signature to the Intercom Messenger initialization as 'user_hash'. For complex security setups, RapidDev's team can help implement the full verification flow.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.