Skills Product & Business Intercom Contact Management Workflow

Intercom Contact Management Workflow

v20260423
intercom-core-workflow-a
This workflow provides comprehensive methods to manage Intercom contacts, covering the full lifecycle from anonymous leads to identified users. Users can create, search, update, merge leads into users, and manage custom attributes and segments. Ideal for building robust CRM features, synchronizing user data, or implementing advanced contact search capabilities in a SaaS application.
Get Skill
286 downloads
Overview

Intercom Contacts & Contact Management

Overview

Primary workflow for managing Intercom contacts. Covers creating users and leads, searching with filters, updating custom attributes, merging leads into users, and managing tags and segments.

Prerequisites

  • Completed intercom-install-auth setup
  • Understanding of Intercom contact model (users vs leads)
  • Valid API credentials with contacts read/write scope

Instructions

Step 1: Create Contacts

import { IntercomClient } from "intercom-client";

const client = new IntercomClient({
  token: process.env.INTERCOM_ACCESS_TOKEN!,
});

// Create an identified user (has external_id)
const user = await client.contacts.create({
  role: "user",
  externalId: "customer-9001",
  email: "alice@acme.com",
  name: "Alice Johnson",
  phone: "+1-555-0100",
  customAttributes: {
    plan: "enterprise",
    company_size: 500,
    signed_up_at: Math.floor(Date.now() / 1000),
  },
});
// Response: { type: "contact", id: "6657add46abd...", role: "user", ... }

// Create an anonymous lead (no external_id required)
const lead = await client.contacts.create({
  role: "lead",
  email: "visitor@example.com",
  name: "Website Visitor",
  customAttributes: {
    landing_page: "/pricing",
    utm_source: "google",
  },
});

Step 2: Search Contacts

POST to https://api.intercom.io/contacts/search with query filters.

// Simple search by email
const byEmail = await client.contacts.search({
  query: {
    field: "email",
    operator: "=",
    value: "alice@acme.com",
  },
});

// Compound search: users on enterprise plan who signed up recently
const filtered = await client.contacts.search({
  query: {
    operator: "AND",
    value: [
      { field: "role", operator: "=", value: "user" },
      { field: "custom_attributes.plan", operator: "=", value: "enterprise" },
      { field: "signed_up_at", operator: ">", value: Math.floor(Date.now() / 1000) - 86400 * 30 },
    ],
  },
  pagination: { per_page: 50 },
  sort: { field: "created_at", order: "descending" },
});

console.log(`Found ${filtered.totalCount} contacts`);
for (const contact of filtered.data) {
  console.log(`  ${contact.name} (${contact.email}) - plan: ${contact.customAttributes?.plan}`);
}

Step 3: Update a Contact

const updated = await client.contacts.update({
  contactId: user.id,
  name: "Alice Johnson-Smith",
  customAttributes: {
    plan: "enterprise_plus",
    upgraded_at: Math.floor(Date.now() / 1000),
  },
});

Step 4: Merge a Lead into a User

When an anonymous lead is identified, merge them into a user contact. The lead's conversation history transfers to the user.

// Lead must have role "lead", user must have role "user"
const merged = await client.contacts.merge({
  from: lead.id,  // Lead ID (will be deleted)
  into: user.id,  // User ID (will absorb lead data)
});

console.log(`Merged lead into user: ${merged.id}`);
// The lead's conversations, events, and tags are now on the user

Step 5: List Segments for a Contact

const segments = await client.contacts.listSegments({
  contactId: user.id,
});

for (const segment of segments.data) {
  console.log(`Segment: ${segment.name} (${segment.id})`);
}

Step 6: Paginate All Contacts

async function* allContacts(client: IntercomClient) {
  let startingAfter: string | undefined;

  do {
    const page = await client.contacts.list({
      perPage: 50,
      startingAfter,
    });

    for (const contact of page.data) {
      yield contact;
    }

    startingAfter = page.pages?.next?.startingAfter ?? undefined;
  } while (startingAfter);
}

// Stream all contacts
let count = 0;
for await (const contact of allContacts(client)) {
  count++;
  if (count % 100 === 0) console.log(`Processed ${count} contacts`);
}

Contact Data Model

FieldTypeDescription
idstringIntercom-generated unique ID
external_idstringYour system's user ID
role"user" or "lead"Contact type
emailstringEmail address
namestringFull name
phonestringPhone number
custom_attributesobjectCustom key-value data
created_atnumberUnix timestamp
last_seen_atnumberLast activity timestamp
signed_up_atnumberSignup timestamp
tagsobjectApplied tags list
companiesobjectAssociated companies
locationobjectGeoIP location data

Error Handling

ErrorHTTP CodeCauseSolution
not_found404Contact ID doesn't existVerify with search first
conflict409Duplicate external_id or emailSearch before creating
parameter_invalid422Bad field value or missing required fieldCheck field types and names
rate_limit_exceeded429Over 10,000 req/min (private apps)Add backoff, batch operations
merge_not_possible400Merging user into lead (reversed)from must be lead, into must be user

Resources

Next Steps

For conversation management, see intercom-core-workflow-b.

Info
Name intercom-core-workflow-a
Version v20260423
Size 6.09KB
Updated At 2026-04-26
Language