Connect Bubble to Intercom by adding the API Connector with your Intercom access token as a Private Bearer header and the required Intercom-Version header. Read conversation lists and contact data into Bubble repeating groups. Check your workspace region — EU and AU accounts use different base URLs, causing 401 errors that look like bad credentials. For webhook events, add a Backend Workflow endpoint (paid Bubble plan required).
| Fact | Value |
|---|---|
| Tool | Intercom |
| Category | Marketing |
| Method | Bubble API Connector |
| Difficulty | Intermediate |
| Time required | 45–75 minutes |
| Last updated | July 2026 |
Two integrations in one: Intercom REST API and Messenger embed in Bubble
Bubble founders searching for 'bubble intercom' are usually asking one of two different questions: How do I embed the Intercom chat widget on my Bubble pages? And how do I read or sync Intercom conversation data inside my Bubble app?
Both patterns work — but they are separate integrations with different technical approaches.
The REST API integration uses Bubble's API Connector to read Intercom data (conversations, contacts, events) into Bubble admin pages. Your access token lives in a Private Authorization header, so it never reaches the browser. Bubble proxies every call from its servers. The main configuration quirks: the Intercom-Version header is required on every request, and the base URL must match your workspace region — US, EU, or AU workspaces each have a different API hostname. Using the US URL for an EU account returns 401 errors that look exactly like bad credentials, wasting hours of debugging time.
The Messenger embed is a different approach entirely: a JavaScript snippet pasted into Bubble's page HTML header that loads Intercom's chat widget. This requires a paid Bubble plan (Starter or above) to access custom page header code. You pass your Intercom app ID and optionally user identity data so Intercom can link conversations to your Bubble users.
For event-driven workflows — like updating a Bubble record when an Intercom conversation is closed — you add a Backend Workflow exposed as an API endpoint to receive Intercom webhook payloads. This also requires a paid Bubble plan but is the recommended pattern for keeping Bubble data in sync with Intercom conversation state.
Integration method
Intercom's REST API accessed via Bubble's API Connector, with the workspace access token stored as a Private Bearer header. All calls run server-side — no CORS issues, no proxy functions. Inbound webhook events can additionally be received via a Bubble Backend Workflow endpoint.
Prerequisites
- An Intercom workspace (Starter plan at $39/seat/month or above — free trials are available)
- Access to Intercom's Developer Hub to create an app and generate a workspace access token
- Knowledge of your Intercom workspace region (US, EU, or AU) — visible in Intercom Settings → Workspace
- A Bubble app with the API Connector plugin installed (Plugins tab → Add plugins → API Connector by Bubble)
- A paid Bubble plan (Starter or above) if you plan to use Backend Workflows to receive webhook events or embed the Messenger widget via custom page header HTML
Step-by-step guide
Create an Intercom Developer Hub app and copy the workspace access token
Intercom uses a workspace access token for server-to-server API calls. This is different from OAuth — you generate it once in the Developer Hub and it remains valid until you regenerate it manually. Log into Intercom and click your workspace icon in the bottom left, then go to Settings. Scroll to the Integrations section and click 'Developer Hub'. If you have not used the Developer Hub before, click 'Build your first app'. Create a new app — name it something like 'Bubble Integration'. You do not need to fill in a redirect URL or set OAuth scopes for a server-side integration. Once the app is created, click on it and go to the Authentication section. You will see a workspace access token — this is a long string starting with 'dG9...' or similar. Click 'Copy' and store it securely. This token gives your Bubble app read and write access to your Intercom workspace data. It does not expire unless you click 'Regenerate' — treat it like a password. Never put it in client-side Bubble JavaScript or a visible field. Note your workspace region before moving on: go to Intercom Settings → Workspace → scroll to find your data region. US workspaces use api.intercom.io, EU workspaces use api.eu.intercom.io, and AU workspaces use api.au.intercom.io. This determines your API Connector base URL.
Pro tip: If you work with multiple Intercom workspaces (e.g., a staging and production workspace), create a separate Developer Hub app and access token for each. Use Bubble's development and live API Connector configurations to keep the tokens separate.
Expected result: You have an Intercom workspace access token copied and stored securely, and you know your workspace region (US, EU, or AU).
Add the API Connector in Bubble with Private Bearer header and Intercom-Version
In your Bubble editor, click the Plugins tab in the left sidebar. If you have not installed API Connector yet, click 'Add plugins', search for 'API Connector', and install the one published by Bubble. It is free. Click on the API Connector in your plugins list and click 'Add another API'. Name this API 'Intercom'. Set the root URL based on your workspace region: - US: https://api.intercom.io - EU: https://api.eu.intercom.io - AU: https://api.au.intercom.io Under 'Shared headers', add the first header: name = Authorization, value = Bearer [paste your token here]. Check the 'Private' checkbox — this keeps the token on Bubble's servers and out of browser network requests. Add a second shared header: name = Intercom-Version, value = 2.10. Do not mark this as Private (it is not a secret). The version header is required by Intercom's API — calls without it either fail or return an older, inconsistent response format that will not match your API Connector configuration. Add a third shared header: Content-Type with value application/json. This is required for POST calls. Save the API root configuration before adding any calls.
1// API Connector — Intercom root configuration2// US workspace example3{4 "API Name": "Intercom",5 "Root URL": "https://api.intercom.io",6 "Shared Headers": [7 {8 "name": "Authorization",9 "value": "Bearer dG9rOjxxxxxxxxxxxxxxxxxxxxxxxx",10 "private": true11 },12 {13 "name": "Intercom-Version",14 "value": "2.10",15 "private": false16 },17 {18 "name": "Content-Type",19 "value": "application/json",20 "private": false21 }22 ]23}Pro tip: If you are not sure of your workspace region, test both the US and EU URLs. A wrong region returns a 401 error even with a valid token — the error message looks identical to a bad token error, which is confusing. Go to Intercom Settings → Workspace to confirm the region before debugging.
Expected result: The Intercom API appears in the API Connector plugin with the correct region base URL, a Private Authorization header, and an Intercom-Version header set to 2.10.
Create a conversation search call and display results in a Bubble repeating group
The most common Bubble-Intercom API call is searching conversations. Intercom uses a POST endpoint for search — not a GET with query parameters — which surprises some founders. In the Intercom API inside the API Connector, click 'Add another call'. Name it 'Search Conversations'. Set the method to POST and the path to /conversations/search. Set 'Use as' to Data — this tells Bubble this call returns data to display, not an action with a side effect. In the Body section, set body type to JSON. The search body uses a query object with field, operator, and value. For a simple 'all open conversations' query, use the body shown in the code block. Click 'Initialize call'. Intercom returns a JSON object with a conversations array — each conversation has an id, title, state, created_at, updated_at, and a contacts section with the contact's name and email. Bubble auto-detects these fields after initialization. In your Bubble editor, create an admin page. Add a Repeating Group element. Set its Type of Content to the Intercom - Search Conversations data source. In the repeating group cells, add Text elements bound to the detected response fields: conversations[i] title, conversations[i] state, and a formatted date from conversations[i] updated_at. Note: Intercom timestamps are Unix timestamps in seconds, not milliseconds. Bubble's date functions expect milliseconds — you may need to handle timestamp formatting in a Backend Workflow or store them as text and display the raw timestamp.
1// POST /conversations/search — request body2// Returns all open conversations3{4 "query": {5 "field": "state",6 "operator": "=",7 "value": "open"8 },9 "pagination": {10 "per_page": 2511 }12}1314// Response shape (conversations array)15{16 "type": "conversation.list",17 "conversations": [18 {19 "id": "1234567890",20 "title": "Question about billing",21 "state": "open",22 "created_at": 1717200000,23 "updated_at": 1717285600,24 "contacts": {25 "contacts": [26 {27 "id": "64abc123",28 "type": "contact",29 "external_id": "user-001"30 }31 ]32 }33 }34 ],35 "total_count": 42,36 "pages": {37 "type": "pages",38 "page": 1,39 "per_page": 25,40 "total_pages": 241 }42}Pro tip: To search for conversations from a specific contact, change the query to use field 'contact_ids' with operator 'IN' and an array value. Chain multiple conditions using an 'AND' operator object wrapping two sub-queries. Test the query shape in Intercom's API documentation explorer before configuring it in Bubble.
Expected result: The Search Conversations call initializes successfully, Bubble detects the conversations array fields, and a repeating group on an admin page displays open conversations with their titles and timestamps.
Create a contact upsert action to sync Bubble users with Intercom
A common pattern is creating or updating Intercom contacts when users sign up or update their profile in Bubble. Intercom's API uses a POST /contacts endpoint that creates a contact if the email does not exist, or updates the existing contact if it does — effectively an upsert. In the API Connector, add another call to the Intercom API. Name it 'Upsert Contact'. Set the method to POST and the path to /contacts. Set 'Use as' to Action. In the Body section, use JSON body type with the contact fields you want to sync: email (required), name, phone, external_id (your Bubble User's unique ID), and custom_attributes (an object for any extra fields). Using external_id as your Bubble User ID is important — it lets you look up Intercom contacts by your Bubble user ID later without needing to store the Intercom contact ID. For Initialize call, use a real email address you own. Intercom returns the full contact object including its Intercom-assigned id field. Store this id in a Bubble database field on the User record so you can reference the Intercom contact in future API calls without another lookup. To wire this to user signup: in the Workflow editor, create a workflow triggered by 'When a User signs up'. Add the action Plugins → Intercom - Upsert Contact. Map Current User's Email to the email parameter, Current User's Name to name, and Current User's unique ID to external_id.
1// POST /contacts — upsert contact body2{3 "email": "<user_email>",4 "name": "<user_name>",5 "phone": "<user_phone>",6 "external_id": "<bubble_user_id>",7 "custom_attributes": {8 "plan": "<user_plan>",9 "signup_date": "<signup_date>"10 }11}1213// Response includes Intercom contact ID to store14{15 "type": "contact",16 "id": "64abc123def456",17 "email": "user@example.com",18 "name": "Jane Smith",19 "external_id": "bubble-user-001",20 "created_at": 1717200000,21 "updated_at": 171720000022}Pro tip: Store the Intercom contact id returned by this call in a dedicated field on your Bubble User record (e.g., 'intercom_contact_id'). Many subsequent API calls — replying to conversations, adding tags, updating attributes — require the Intercom contact ID, and looking it up via email on every call wastes Workload Units and adds latency.
Expected result: The Upsert Contact call initializes successfully with a 200 response. The action appears in Bubble workflow editor under Plugins, and wiring it to the user signup workflow creates or updates the corresponding Intercom contact.
Set up a Backend Workflow endpoint for receiving Intercom webhook events
Intercom can send webhook events to your Bubble app when things happen in Intercom — a conversation is closed, a new lead is created, a user attribute changes. This requires a Bubble Backend Workflow exposed as an API endpoint. Backend Workflows require a paid Bubble plan (Starter or above — not available on free). RapidDev's team has built hundreds of Bubble apps with webhook integrations like this — if you want help structuring the event processing logic, book a free scoping call at rapidevelopers.com/contact. To set up the endpoint: go to Bubble's backend workflows section (in the Workflow editor, switch to the Backend tab). Create a new API Workflow. Name it 'Intercom Webhook'. Check 'This workflow can be run without authentication' — Intercom cannot send your Bubble auth token, so the endpoint must be publicly accessible. Click 'Detect request data'. Intercom sends a JSON POST payload — click 'Detect data' and go to Intercom's Developer Hub to send a test event to the URL shown. Alternatively, paste a sample Intercom webhook payload manually. Bubble will detect the field types from the payload. Map the fields you need: type (the event name), data > item > id, data > item > state, data > item > contacts. Add workflow steps after detection: create or modify a Bubble database record based on the event type. Add a 'Return data from API' step at the end that returns {} with a 200 status — Intercom expects a 200 response within 5 seconds and will retry the webhook if it times out. In Intercom's Developer Hub, go to your app → Webhooks. Add the Bubble API endpoint URL as a webhook URL. Select the topics you want: conversation.closed, conversation.created, contact.created, etc. Save and send a test event to verify the connection. Note: The Backend Workflow URL shown in Bubble has an /initialize suffix for the schema detection step. Drop the /initialize suffix when registering the production webhook URL in Intercom — the production endpoint is the URL without /initialize.
1// Intercom webhook payload example (conversation.closed)2{3 "type": "notification_event",4 "app_id": "abc123",5 "data": {6 "type": "notification_event_data",7 "item": {8 "type": "conversation",9 "id": "1234567890",10 "state": "closed",11 "title": "Question about billing",12 "created_at": 1717200000,13 "updated_at": 1717285600,14 "contacts": {15 "contacts": [16 {17 "id": "64abc123",18 "external_id": "bubble-user-001"19 }20 ]21 }22 }23 },24 "delivery_attempts": 1,25 "delivered_at": 0,26 "first_sent_at": 1717285600,27 "notified_at": 1717285600,28 "created_at": 171728560029}Pro tip: Intercom retries webhook delivery if your endpoint does not respond with 200 within 5 seconds. Add a 'Return data from API' step as the FIRST workflow step in your Backend Workflow, returning an empty JSON object. Then process the payload in subsequent workflow steps. This ensures Intercom gets its acknowledgment quickly even if Bubble's processing takes longer.
Expected result: The Backend Workflow endpoint URL is registered in Intercom's webhook settings. Intercom sends a test event, Bubble receives it, the workflow runs and creates or updates a database record, and Intercom's webhook log shows a 200 response.
Common use cases
Support conversation dashboard inside Bubble admin
Build an internal admin page in Bubble that shows all open Intercom conversations assigned to your team. Use the API Connector to call Intercom's conversation search endpoint, filter by state 'open', and display results in a Bubble repeating group with columns for contact name, conversation subject, assigned admin, and last activity timestamp. Admins can click a row to see the full conversation URL or take action without switching to Intercom.
Create a Bubble admin page with a repeating group that fetches open Intercom conversations via POST /conversations/search. Display contact name, subject, assigned_to, and updated_at formatted as a date. Add a link to open the full conversation in Intercom.
Copy this prompt to try it in Bubble
Sync Intercom contact data to Bubble user records
When a new user registers in your Bubble app, create or update their Intercom contact via POST /contacts (upsert by email). Then use GET /contacts/{id} to retrieve any enrichment data Intercom has added — company, plan, last seen — and write it back to the Bubble User record. This keeps your Bubble database enriched with Intercom's CRM data without manual import/export.
On Bubble user signup, POST to Intercom /contacts with the user's email, name, and custom_attributes including plan and signup_date. Store the returned Intercom contact ID in the Bubble User record for future API calls.
Copy this prompt to try it in Bubble
Receive lead form submissions via Intercom webhook
If you use Intercom's lead generation forms or capture leads through Messenger conversations, set up a Bubble Backend Workflow as a webhook endpoint to receive the conversation_part_created or lead_created webhook. Parse the payload to extract contact email and message, then create a Lead record in Bubble's database and trigger a follow-up email via SendGrid — all automated, without anyone logging into Intercom.
Create a Bubble Backend Workflow endpoint that receives Intercom webhook events. On conversation_part_created events, extract the contact email and first message, create a Lead Thing in Bubble's database, and trigger a SendGrid welcome email.
Copy this prompt to try it in Bubble
Troubleshooting
Every API call returns 401 Unauthorized even though the access token appears correct
Cause: Most commonly caused by a workspace region mismatch. EU and AU Intercom workspaces use different base URLs than US workspaces. Using https://api.intercom.io (US) for an EU workspace returns 401 errors that are indistinguishable from a bad token error.
Solution: Go to Intercom Settings → Workspace and confirm your data region. If EU, change the API Connector base URL to https://api.eu.intercom.io. If AU, use https://api.au.intercom.io. Also verify that the access token is copied correctly with no trailing spaces — regenerate it in the Developer Hub if you are uncertain.
API calls return inconsistent or unexpected response fields compared to what the documentation shows
Cause: The Intercom-Version shared header is missing or set to an incorrect value. Without the version header, Intercom either rejects the request or serves a deprecated API version with a different response schema.
Solution: Open the API Connector in Bubble's Plugins tab, click on the Intercom API, and verify that the shared headers include Intercom-Version: 2.10. If the header is missing, add it and re-initialize all calls — the detected response fields may change. The version header must appear on every API call, not just one.
The Initialize call fails with 'There was an issue setting up your call' and the call cannot be saved
Cause: The Initialize call requires a real successful response from Intercom's API. If the body is empty, malformed, or uses placeholder values that fail validation, Bubble cannot detect the response shape and cannot save the call configuration.
Solution: During initialization, temporarily use static real values (a real conversation ID for search, a real email for contact upsert). Intercom must return a valid 200 or 201 response for Bubble to save the call. After successful initialization, change the static values back to dynamic <placeholders>. For the Search Conversations call, ensure the JSON query body is valid — a missing closing brace or unquoted string causes a 400 error that blocks initialization.
Intercom webhook events are received once but the same event is delivered again after a few minutes
Cause: Intercom retries webhook delivery when it does not receive a 200 HTTP response within 5 seconds. If your Bubble Backend Workflow has heavy processing steps that take more than 5 seconds, Intercom times out and retries — causing duplicate processing.
Solution: Add a 'Return data from API' step as the first action in the Backend Workflow with an empty JSON body and 200 status. Process the payload in subsequent steps after the return. This sends the 200 acknowledgment immediately while processing continues asynchronously. Also check the Bubble Logs tab to see if the workflow is erroring out, which would also prevent a 200 response from being returned.
The Intercom Messenger chat widget does not appear on Bubble pages after adding the embed code
Cause: Bubble's page HTML header injection requires a paid plan (Starter or above). On the free plan, custom HTML added to the page header is not rendered. Alternatively, the embed code is placed in Bubble's page body instead of the head, or the Intercom app_id in the script is incorrect.
Solution: Upgrade to a paid Bubble plan if on the free tier. In the Bubble editor, go to the page settings (click the page element in the editor), find 'SEO / metatags' section, and paste the Intercom snippet into the 'Script/meta tags in header' field — not in the page body. Verify that the app_id in the snippet matches your Intercom workspace's app ID (visible in Intercom Settings → Installation).
Best practices
- Always include the Intercom-Version shared header (2.10 or current stable) in the API Connector root configuration — without it, response formats are inconsistent and may not match your initialized call schema.
- Store the returned Intercom contact id in a dedicated field on your Bubble User record after the first upsert. Many subsequent API calls require the Intercom contact ID, and repeated email lookups waste Workload Units.
- Confirm your workspace region before building the integration. EU and AU workspaces use different base URLs — setting the wrong URL causes 401 errors identical to a bad token, which wastes debugging time.
- For Backend Workflow webhook endpoints, add the 'Return data from API' step first with an empty 200 response before any processing steps. Intercom's 5-second timeout is strict, and slow Bubble workflows will trigger unnecessary retries.
- Mark the Authorization header as Private in the API Connector. Never put the Intercom access token in a client-side Bubble JavaScript block or a visible page field.
- Apply Bubble's Privacy rules to any database Thing that stores Intercom conversation data or contact records — privacy rules control who can read this data in Bubble's Data API and from page elements.
- Use Intercom's external_id field (map to Bubble's User unique ID) for contact upserts rather than relying solely on email. This creates a stable cross-system identifier that survives email changes and prevents duplicate contacts.
- Monitor Workload Unit consumption if you display Intercom conversation data on pages loaded frequently by many users — each page load fires an API call. Consider caching conversation lists in Bubble's database (refreshed hourly via a scheduled Backend Workflow) rather than calling Intercom's API on every page load.
Alternatives
HubSpot is a CRM focused on contact management, deal pipelines, and marketing automation. Intercom is a customer messaging platform focused on conversations, live chat, and in-app messaging. Use HubSpot if you need to track leads through a sales pipeline and manage deals. Use Intercom if you need live chat support on your Bubble app and want to manage customer conversations.
SendGrid handles outbound transactional email — one email per user action like signup or order confirmation. Intercom handles inbound and outbound customer messaging including live chat, email sequences, and in-app messages. If you only need to send triggered emails, SendGrid is simpler to set up. If you need two-way customer communication and conversation management, Intercom is the right tool.
Mailchimp is an email marketing platform for batch campaigns to audience segments. Intercom is a customer messaging platform for real-time, personalized communication and support. Use Mailchimp for newsletters and segment-based email campaigns. Use Intercom for live support chat and behavior-triggered in-app messages that depend on what users do inside your Bubble app.
Frequently asked questions
Can I embed Intercom's live chat Messenger widget on Bubble pages?
Yes, but it requires a paid Bubble plan. The Intercom Messenger embed is a JavaScript snippet that goes in Bubble's page HTML header. In the Bubble editor, click on the page element, go to 'SEO / metatags', and paste the Intercom snippet into the 'Script/meta tags in header' field. On the free Bubble plan, custom header scripts are not rendered. You also need to include your Intercom app_id in the snippet and optionally pass user identity data (email, name, user_id) so Intercom can link chat conversations to your Bubble users.
Do I need a paid Bubble plan to integrate with Intercom's REST API?
No, for read-only API calls (fetching conversations, contacts) and action calls (creating contacts, sending messages), the free Bubble plan works — these use the API Connector which is available on all plans. However, if you want to receive inbound Intercom webhook events (e.g., conversation closed, lead created), you need a paid Bubble plan (Starter or above) because that requires a Backend Workflow exposed as an API endpoint, which is a paid feature.
Why does Intercom require a version header? What happens if I leave it out?
Intercom uses the Intercom-Version header to serve consistent API responses and to control which version of their API schema your app uses. Without it, Intercom may serve a deprecated API version with different field names and response structures, or reject the call entirely. Always set Intercom-Version: 2.10 (or the latest stable version listed in Intercom's API documentation) as a shared header in the API Connector root configuration.
How do I handle Intercom's Unix timestamps in Bubble date fields?
Intercom returns timestamps as Unix timestamps in seconds (e.g., 1717200000). Bubble's date display and calculations expect milliseconds. When displaying Intercom timestamps in text elements, either multiply the value by 1000 in a Bubble expression to convert to milliseconds, or store the raw timestamp as a number field and format it in a Backend Workflow. Alternatively, display the Unix timestamp as a relative date description (e.g., '3 days ago') using Bubble's date arithmetic.
What Intercom API scopes does my Developer Hub app need?
A basic workspace access token created in the Developer Hub automatically has access to your workspace's conversations, contacts, and events. For more granular control, you can create a custom OAuth app with specific scopes. For a typical Bubble integration (read conversations, upsert contacts, receive webhooks), the default workspace access token is sufficient without additional scope configuration.
Can I reply to Intercom conversations directly from Bubble using the API?
Yes. Use POST /conversations/{id}/reply with a body containing message_type set to 'comment', body with your reply text, and type set to 'admin'. You also need to provide admin_id — the numeric ID of the Intercom admin sending the reply. Fetch your admin ID first via GET /me and store it as a constant in your Bubble app. Note that admin_id must be a numeric ID, not an email address — using an email causes a 422 error.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation