intercom-webhooks-events
Implement Intercom webhook handling and data event tracking. Use when setting up webhook endpoints, processing Intercom notifications, or submitting custom data events for contact activity tracking. Trigger with phrases like "intercom webhook", "intercom events", "intercom webhook signature", "handle intercom events", "intercom data events", "track intercom events".
Best use case
intercom-webhooks-events is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Implement Intercom webhook handling and data event tracking. Use when setting up webhook endpoints, processing Intercom notifications, or submitting custom data events for contact activity tracking. Trigger with phrases like "intercom webhook", "intercom events", "intercom webhook signature", "handle intercom events", "intercom data events", "track intercom events".
Teams using intercom-webhooks-events should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/intercom-webhooks-events/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How intercom-webhooks-events Compares
| Feature / Agent | intercom-webhooks-events | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Implement Intercom webhook handling and data event tracking. Use when setting up webhook endpoints, processing Intercom notifications, or submitting custom data events for contact activity tracking. Trigger with phrases like "intercom webhook", "intercom events", "intercom webhook signature", "handle intercom events", "intercom data events", "track intercom events".
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
Related Guides
Best AI Skills for Claude
Explore the best AI skills for Claude and Claude Code across coding, research, workflow automation, documentation, and agent operations.
ChatGPT vs Claude for Agent Skills
Compare ChatGPT and Claude for AI agent skills across coding, writing, research, and reusable workflow execution.
SKILL.md Source
# Intercom Webhooks & Events
## Overview
Handle incoming Intercom webhooks (notifications) with signature verification and implement outbound data event tracking via the Events API.
## Prerequisites
- HTTPS endpoint accessible from internet
- Webhook secret from Intercom Developer Hub
- `intercom-client` SDK installed
- Redis or database for idempotency (recommended)
## Part 1: Incoming Webhooks (Notifications)
### Step 1: Webhook Endpoint with Signature Verification
Intercom signs webhooks with HMAC-SHA1 via the `X-Hub-Signature` header.
```typescript
import express from "express";
import crypto from "crypto";
const app = express();
// IMPORTANT: Use raw body for signature verification
app.post(
"/webhooks/intercom",
express.raw({ type: "application/json" }),
async (req, res) => {
const signature = req.headers["x-hub-signature"] as string;
const secret = process.env.INTERCOM_WEBHOOK_SECRET!;
if (!signature) {
return res.status(401).json({ error: "Missing X-Hub-Signature" });
}
// Verify HMAC-SHA1 signature
const expected = "sha1=" + crypto
.createHmac("sha1", secret)
.update(req.body)
.digest("hex");
if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
console.error("Webhook signature verification failed");
return res.status(401).json({ error: "Invalid signature" });
}
// MUST respond within 5 seconds or Intercom treats as failure
// Parse and queue for async processing
const notification = JSON.parse(req.body.toString());
res.status(200).json({ received: true });
// Process asynchronously after responding
processWebhookAsync(notification).catch(console.error);
}
);
```
### Step 2: Notification Payload Shape
```typescript
// Every Intercom webhook notification follows this structure
interface IntercomNotification {
type: "notification_event";
id: string; // Unique notification ID
topic: string; // e.g., "conversation.user.created"
app_id: string; // Your app ID
created_at: number; // Unix timestamp
delivery_attempts: number; // 1 on first try, 2 on retry
data: {
type: "notification_event_data";
item: any; // The actual resource (conversation, contact, etc.)
};
}
// Example: conversation.user.created
// {
// "type": "notification_event",
// "id": "notif_abc123",
// "topic": "conversation.user.created",
// "created_at": 1711100000,
// "data": {
// "type": "notification_event_data",
// "item": {
// "type": "conversation",
// "id": "123",
// "state": "open",
// "source": { "body": "Hi, I need help!" },
// "contacts": { "contacts": [{ "id": "contact-1", "type": "contact" }] }
// }
// }
// }
```
### Step 3: Topic-Based Event Router
```typescript
type WebhookHandler = (data: any) => Promise<void>;
const handlers: Record<string, WebhookHandler> = {
"conversation.user.created": async (data) => {
const conversation = data.item;
console.log(`New conversation: ${conversation.id}`);
// Notify support channel, auto-assign, etc.
},
"conversation.user.replied": async (data) => {
const conversation = data.item;
console.log(`Customer replied to: ${conversation.id}`);
// Update ticket system, escalate if needed
},
"conversation.admin.closed": async (data) => {
const conversation = data.item;
console.log(`Conversation closed: ${conversation.id}`);
// Send satisfaction survey, update CRM
},
"contact.created": async (data) => {
const contact = data.item;
console.log(`New contact: ${contact.id} (${contact.email})`);
// Sync to CRM, enrich data, trigger welcome flow
},
"contact.tag.created": async (data) => {
const contact = data.item;
console.log(`Contact tagged: ${contact.id}`);
// Trigger automation based on tag
},
};
async function processWebhookAsync(notification: IntercomNotification): Promise<void> {
const handler = handlers[notification.topic];
if (!handler) {
console.log(`Unhandled topic: ${notification.topic}`);
return;
}
try {
await handler(notification.data);
console.log(`Processed ${notification.topic}: ${notification.id}`);
} catch (error) {
console.error(`Failed ${notification.topic}: ${notification.id}`, error);
// Dead-letter queue for failed events
}
}
```
### Step 4: Idempotency (Prevent Duplicate Processing)
Intercom retries failed webhooks once after 1 minute. Guard against duplicates:
```typescript
import { Redis } from "ioredis";
const redis = new Redis(process.env.REDIS_URL);
async function processIdempotent(
notification: IntercomNotification,
handler: () => Promise<void>
): Promise<void> {
const key = `intercom:webhook:${notification.id}`;
// SET NX: only succeeds if key doesn't exist
const acquired = await redis.set(key, "processing", "EX", 86400 * 7, "NX");
if (!acquired) {
console.log(`Duplicate webhook skipped: ${notification.id}`);
return;
}
try {
await handler();
await redis.set(key, "completed", "EX", 86400 * 7);
} catch (error) {
await redis.del(key); // Allow retry on failure
throw error;
}
}
```
## Part 2: Outbound Data Events
Submit custom events to track contact activity in Intercom.
### Step 5: Track Data Events
```typescript
import { IntercomClient } from "intercom-client";
const client = new IntercomClient({
token: process.env.INTERCOM_ACCESS_TOKEN!,
});
// Submit a data event
await client.dataEvents.create({
eventName: "completed-onboarding",
createdAt: Math.floor(Date.now() / 1000),
userId: "user-12345", // External ID of the contact
metadata: {
steps_completed: 5,
time_to_complete_minutes: 12,
plan: "pro",
},
});
// Event naming convention: past-tense verb-noun
// Good: "placed-order", "upgraded-plan", "invited-teammate"
// Bad: "order", "click", "page_view"
```
### Step 6: Bulk Event Submission
```typescript
// Submit events for multiple users efficiently
async function trackBulkEvents(
client: IntercomClient,
events: Array<{ userId: string; eventName: string; metadata?: Record<string, any> }>
): Promise<{ succeeded: number; failed: number }> {
let succeeded = 0;
let failed = 0;
// Intercom doesn't have a batch events endpoint; throttle individual calls
for (const event of events) {
try {
await client.dataEvents.create({
eventName: event.eventName,
createdAt: Math.floor(Date.now() / 1000),
userId: event.userId,
metadata: event.metadata,
});
succeeded++;
// Rate limit: slight delay between calls
if (succeeded % 50 === 0) {
await new Promise(r => setTimeout(r, 500));
}
} catch (error) {
failed++;
console.error(`Failed to track event for ${event.userId}:`, error);
}
}
return { succeeded, failed };
}
```
## Available Webhook Topics
| Topic | Description |
|-------|-------------|
| `conversation.user.created` | New conversation from contact |
| `conversation.user.replied` | Contact replies to conversation |
| `conversation.admin.replied` | Admin replies to conversation |
| `conversation.admin.closed` | Conversation closed by admin |
| `conversation.admin.opened` | Conversation reopened |
| `conversation.admin.snoozed` | Conversation snoozed |
| `conversation.admin.assigned` | Conversation reassigned |
| `contact.created` | New contact created |
| `contact.signed_up` | Lead converts to user |
| `contact.tag.created` | Tag applied to contact |
| `contact.tag.deleted` | Tag removed from contact |
| `visitor.signed_up` | Visitor becomes lead |
## Error Handling
| Issue | Cause | Solution |
|-------|-------|----------|
| Invalid signature | Secret mismatch | Verify secret matches Developer Hub |
| Timeout (5s) | Slow processing | Queue events, respond immediately |
| Duplicate events | Retry delivery | Implement idempotency with Redis |
| Missing topic handler | New topic added | Log unhandled topics, add handler |
| Event rejected (422) | Invalid user_id or event_name | Verify contact exists, use verb-noun naming |
## Resources
- [Webhook Setup](https://developers.intercom.com/docs/webhooks/setting-up-webhooks)
- [Webhook Topics](https://developers.intercom.com/docs/references/webhooks/webhook-models)
- [Webhook Notifications](https://developers.intercom.com/docs/webhooks/webhook-notifications)
- [Data Events API](https://developers.intercom.com/docs/references/rest-api/api.intercom.io/data-events)
## Next Steps
For performance optimization, see `intercom-performance-tuning`.Related Skills
workhuman-webhooks-events
Workhuman webhooks events for employee recognition and rewards API. Use when integrating Workhuman Social Recognition, or building recognition workflows with HRIS systems. Trigger: "workhuman webhooks events".
wispr-webhooks-events
Wispr Flow webhooks events for voice-to-text API integration. Use when integrating Wispr Flow dictation, WebSocket streaming, or building voice-powered applications. Trigger: "wispr webhooks events".
windsurf-webhooks-events
Build Windsurf extensions and integrate with VS Code extension API events. Use when building custom Windsurf extensions, tracking editor events, or integrating Windsurf with external tools via extension development. Trigger with phrases like "windsurf extension", "windsurf events", "windsurf plugin", "build windsurf extension", "windsurf API".
webflow-webhooks-events
Implement Webflow webhook registration, signature verification, and event handling for form_submission, site_publish, ecomm_new_order, page_created, and more. Use when setting up webhook endpoints, implementing event-driven workflows, or handling Webflow notifications. Trigger with phrases like "webflow webhook", "webflow events", "webflow webhook signature", "handle webflow events", "webflow notifications".
vercel-webhooks-events
Implement Vercel webhook handling with signature verification and event processing. Use when setting up webhook endpoints, processing deployment events, or building integrations that react to Vercel deployment lifecycle. Trigger with phrases like "vercel webhook", "vercel events", "vercel deployment.ready", "handle vercel events", "vercel webhook signature".
veeva-webhooks-events
Veeva Vault webhooks events for REST API and clinical operations. Use when working with Veeva Vault document management and CRM. Trigger: "veeva webhooks events".
vastai-webhooks-events
Build event-driven workflows around Vast.ai instance lifecycle events. Use when monitoring instance status changes, implementing auto-recovery, or building event-driven GPU orchestration. Trigger with phrases like "vastai events", "vastai instance monitoring", "vastai status changes", "vastai lifecycle events".
twinmind-webhooks-events
Handle TwinMind meeting events including transcription completion, action item extraction, and calendar sync notifications. Use when implementing webhooks events, or managing TwinMind meeting AI operations. Trigger with phrases like "twinmind webhooks events", "twinmind webhooks events".
together-webhooks-events
Together AI webhooks events for inference, fine-tuning, and model deployment. Use when working with Together AI's OpenAI-compatible API. Trigger: "together webhooks events".
techsmith-webhooks-events
TechSmith webhooks events for Snagit COM API and Camtasia automation. Use when working with TechSmith screen capture and video editing automation. Trigger: "techsmith webhooks events".
supabase-webhooks-events
Implement Supabase database webhooks, pg_net async HTTP, LISTEN/NOTIFY, and Edge Function event handlers with signature verification. Use when setting up database webhooks for INSERT/UPDATE/DELETE events, sending HTTP requests from PostgreSQL triggers, handling Realtime postgres_changes as an event source, or building event-driven architectures. Trigger with phrases like "supabase webhook", "database events", "pg_net trigger", "supabase LISTEN NOTIFY", "webhook signature verify", "supabase event-driven", "supabase_functions.http_request".
stackblitz-webhooks-events
WebContainer lifecycle events: server-ready, port changes, error handling. Use when working with WebContainers or StackBlitz SDK. Trigger: "webcontainer events".