Claude-code-plugins-plus-skills intercom-core-workflow-a

install
source · Clone the upstream repo
git clone https://github.com/jeremylongshore/claude-code-plugins-plus-skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/jeremylongshore/claude-code-plugins-plus-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/saas-packs/intercom-pack/skills/intercom-core-workflow-a" ~/.claude/skills/jeremylongshore-claude-code-plugins-plus-skills-intercom-core-workflow-a && rm -rf "$T"
manifest: plugins/saas-packs/intercom-pack/skills/intercom-core-workflow-a/SKILL.md
source content

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
id
stringIntercom-generated unique ID
external_id
stringYour system's user ID
role
"user"
or
"lead"
Contact type
email
stringEmail address
name
stringFull name
phone
stringPhone number
custom_attributes
objectCustom key-value data
created_at
numberUnix timestamp
last_seen_at
numberLast activity timestamp
signed_up_at
numberSignup timestamp
tags
objectApplied tags list
companies
objectAssociated companies
location
objectGeoIP location data

Error Handling

ErrorHTTP CodeCauseSolution
not_found
404Contact ID doesn't existVerify with search first
conflict
409Duplicate
external_id
or
email
Search before creating
parameter_invalid
422Bad field value or missing required fieldCheck field types and names
rate_limit_exceeded
429Over 10,000 req/min (private apps)Add backoff, batch operations
merge_not_possible
400Merging user into lead (reversed)
from
must be lead,
into
must be user

Resources

Next Steps

For conversation management, see

intercom-core-workflow-b
.