Skip to content

Intercom Integration

Receive and route Intercom webhooks for conversations, contacts, companies, and user events.

Setup

1. Create a Source in Hookbase

bash
curl -X POST https://api.hookbase.app/api/sources \
  -H "Authorization: Bearer whr_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Intercom Production",
    "slug": "intercom",
    "verificationConfig": {
      "type": "hmac",
      "secret": "your-intercom-client-secret",
      "algorithm": "sha1",
      "header": "X-Hub-Signature",
      "signaturePrefix": "sha1=",
      "encoding": "hex"
    }
  }'

Save your webhook URL:

https://api.hookbase.app/ingest/{orgSlug}/intercom

2. Configure Intercom Webhook

  1. Go to the Intercom Developer Hub
  2. Select your app (or create one)
  3. Navigate to Webhooks in the left sidebar
  4. Enter your Hookbase webhook URL in the Webhook URL field
  5. Select the topics you want to receive (e.g., conversation.user.created, contact.created)
  6. Click Save
  7. Copy your app's Client Secret from the Basic Information page
  8. Update your Hookbase source with this secret

TIP

Your Client Secret is found under Basic Information in the Intercom Developer Hub. This is the secret used to sign webhook payloads, not your access token.

3. Create Routes

bash
# Create destination for your conversation handler
curl -X POST https://api.hookbase.app/api/destinations \
  -H "Authorization: Bearer whr_your_api_key" \
  -d '{"name": "Support Service", "url": "https://api.myapp.com/webhooks/intercom"}'

# Create route
curl -X POST https://api.hookbase.app/api/routes \
  -H "Authorization: Bearer whr_your_api_key" \
  -d '{"name": "Intercom to Support Service", "sourceId": "src_...", "destinationIds": ["dst_..."]}'

Signature Verification

Intercom signs webhooks with HMAC-SHA1 using your app's client secret. The signature is sent in the X-Hub-Signature header with a sha1= prefix:

X-Hub-Signature: sha1=d3b07384d113edec49eaa6238ad5ff00b8d257e5

Hookbase automatically verifies this signature when configured:

json
{
  "verificationConfig": {
    "type": "hmac",
    "secret": "your-intercom-client-secret",
    "algorithm": "sha1",
    "header": "X-Hub-Signature",
    "signaturePrefix": "sha1=",
    "encoding": "hex"
  }
}

WARNING

Make sure you use the Client Secret from your Intercom app's Basic Information page, not the access token. The client secret is the key used to compute the HMAC signature.

Common Events

conversation.user.created

Triggered when a user starts a new conversation.

json
{
  "type": "notification_event",
  "app_id": "abc123de",
  "topic": "conversation.user.created",
  "id": "notif_12345-67890",
  "created_at": 1710432000,
  "delivery_status": "pending",
  "data": {
    "type": "notification_event_data",
    "item": {
      "type": "conversation",
      "id": "12345678901",
      "created_at": 1710432000,
      "updated_at": 1710432000,
      "source": {
        "type": "conversation",
        "id": "12345678901",
        "delivered_as": "customer_initiated",
        "body": "<p>Hi, I need help with my account settings.</p>",
        "author": {
          "type": "user",
          "id": "6543210abc",
          "name": "Jane Smith",
          "email": "[email protected]"
        }
      },
      "contacts": {
        "type": "contact.list",
        "contacts": [
          {
            "type": "contact",
            "id": "6543210abc",
            "external_id": "user_98765"
          }
        ]
      },
      "state": "open",
      "open": true,
      "read": false,
      "tags": {
        "type": "tag.list",
        "tags": []
      }
    }
  }
}

conversation.admin.replied

Triggered when an admin or bot replies to a conversation.

json
{
  "type": "notification_event",
  "app_id": "abc123de",
  "topic": "conversation.admin.replied",
  "id": "notif_12345-67891",
  "created_at": 1710432600,
  "data": {
    "type": "notification_event_data",
    "item": {
      "type": "conversation",
      "id": "12345678901",
      "created_at": 1710432000,
      "updated_at": 1710432600,
      "conversation_parts": {
        "type": "conversation_part.list",
        "conversation_parts": [
          {
            "type": "conversation_part",
            "id": "98765432",
            "part_type": "comment",
            "body": "<p>Hi Jane, I'd be happy to help with your account settings!</p>",
            "author": {
              "type": "admin",
              "id": "1234567",
              "name": "Support Agent",
              "email": "[email protected]"
            },
            "created_at": 1710432600
          }
        ]
      },
      "state": "open",
      "open": true
    }
  }
}

conversation.admin.closed

Triggered when an admin closes a conversation.

json
{
  "type": "notification_event",
  "app_id": "abc123de",
  "topic": "conversation.admin.closed",
  "id": "notif_12345-67892",
  "created_at": 1710435000,
  "data": {
    "type": "notification_event_data",
    "item": {
      "type": "conversation",
      "id": "12345678901",
      "created_at": 1710432000,
      "updated_at": 1710435000,
      "state": "closed",
      "open": false,
      "tags": {
        "type": "tag.list",
        "tags": [
          { "type": "tag", "id": "456", "name": "resolved" }
        ]
      }
    }
  }
}

contact.created

Triggered when a new contact is created.

json
{
  "type": "notification_event",
  "app_id": "abc123de",
  "topic": "contact.created",
  "id": "notif_12345-67893",
  "created_at": 1710436000,
  "data": {
    "type": "notification_event_data",
    "item": {
      "type": "contact",
      "id": "6543210def",
      "role": "user",
      "external_id": "user_11111",
      "email": "[email protected]",
      "name": "Alex Johnson",
      "phone": "+1-555-0123",
      "avatar": "https://example.com/avatar.jpg",
      "signed_up_at": 1710436000,
      "created_at": 1710436000,
      "updated_at": 1710436000,
      "custom_attributes": {
        "plan": "pro",
        "company_size": "50-100"
      },
      "companies": {
        "type": "company.list",
        "companies": [
          {
            "type": "company",
            "id": "comp_98765",
            "name": "Acme Corp"
          }
        ]
      },
      "location": {
        "city": "San Francisco",
        "country": "United States",
        "region": "California"
      },
      "tags": {
        "type": "tag.list",
        "tags": [
          { "type": "tag", "id": "789", "name": "trial-user" }
        ]
      }
    }
  }
}

user.tag.created

Triggered when a tag is added to a user.

json
{
  "type": "notification_event",
  "app_id": "abc123de",
  "topic": "user.tag.created",
  "id": "notif_12345-67894",
  "created_at": 1710437000,
  "data": {
    "type": "notification_event_data",
    "item": {
      "type": "tag",
      "id": "321",
      "name": "vip-customer"
    },
    "user": {
      "type": "user",
      "id": "6543210abc",
      "email": "[email protected]",
      "name": "Jane Smith",
      "user_id": "user_98765"
    }
  }
}

Intercom Webhook Topics

CategoryTopics
Conversationsconversation.user.created, conversation.user.replied, conversation.admin.replied, conversation.admin.closed, conversation.admin.opened, conversation.admin.snoozed, conversation.admin.unsnoozed, conversation.admin.assigned, conversation.admin.noted, conversation.admin.single.created, conversation.rating.added, conversation.rating.remarked
Contactscontact.created, contact.updated, contact.deleted, contact.signed_up, contact.tag.created, contact.tag.deleted
Usersuser.created, user.deleted, user.email.updated, user.tag.created, user.tag.deleted
Companiescompany.created
Visitorsvisitor.signed_up

Transform Examples

Slack Alert for New Conversations

javascript
function transform(payload) {
  const conversation = payload.data.item;
  const author = conversation.source?.author || {};
  const body = (conversation.source?.body || '')
    .replace(/<[^>]*>/g, '');

  return {
    blocks: [
      {
        type: "header",
        text: {
          type: "plain_text",
          text: "New Intercom Conversation"
        }
      },
      {
        type: "section",
        fields: [
          {
            type: "mrkdwn",
            text: `*From:*\n${author.name || 'Unknown'} (${author.email || 'no email'})`
          },
          {
            type: "mrkdwn",
            text: `*Conversation ID:*\n${conversation.id}`
          }
        ]
      },
      {
        type: "section",
        text: {
          type: "mrkdwn",
          text: `*Message:*\n${body.substring(0, 500)}`
        }
      },
      {
        type: "actions",
        elements: [
          {
            type: "button",
            text: {
              type: "plain_text",
              text: "Open in Intercom"
            },
            url: `https://app.intercom.com/a/apps/${payload.app_id}/conversations/${conversation.id}`
          }
        ]
      }
    ]
  };
}

Database Format

javascript
function transform(payload) {
  const topic = payload.topic;
  const item = payload.data.item;

  // Handle conversation events
  if (topic.startsWith('conversation.')) {
    const author = item.source?.author || {};
    return {
      intercom_event_id: payload.id,
      event_type: topic,
      conversation_id: item.id,
      state: item.state,
      author_type: author.type,
      author_id: author.id,
      author_email: author.email,
      author_name: author.name,
      app_id: payload.app_id,
      created_at: new Date(payload.created_at * 1000).toISOString()
    };
  }

  // Handle contact/user events
  if (topic.startsWith('contact.') || topic.startsWith('user.')) {
    return {
      intercom_event_id: payload.id,
      event_type: topic,
      contact_id: item.id,
      external_id: item.external_id || item.user_id,
      email: item.email,
      name: item.name,
      role: item.role,
      custom_attributes: item.custom_attributes || {},
      app_id: payload.app_id,
      created_at: new Date(payload.created_at * 1000).toISOString()
    };
  }

  // Fallback for other events
  return {
    intercom_event_id: payload.id,
    event_type: topic,
    item_type: item.type,
    item_id: item.id,
    app_id: payload.app_id,
    created_at: new Date(payload.created_at * 1000).toISOString()
  };
}

Alert for Closed Conversations

javascript
function transform(payload) {
  const conversation = payload.data.item;
  const tags = (conversation.tags?.tags || [])
    .map(t => t.name)
    .join(', ');

  return {
    channel: "#support-resolved",
    username: "Intercom Bot",
    icon_emoji: ":white_check_mark:",
    attachments: [{
      color: "good",
      title: "Conversation Closed",
      fields: [
        { title: "Conversation ID", value: conversation.id, short: true },
        { title: "State", value: conversation.state, short: true },
        { title: "Tags", value: tags || "None", short: false }
      ],
      footer: `App ${payload.app_id}`,
      ts: payload.created_at
    }]
  };
}

Filter Examples

Conversation Events Only

json
{
  "name": "Conversation Events",
  "logic": "and",
  "conditions": [
    {
      "field": "topic",
      "operator": "starts_with",
      "value": "conversation."
    }
  ]
}

New Conversations from Users

json
{
  "name": "User-Created Conversations",
  "logic": "and",
  "conditions": [
    {
      "field": "topic",
      "operator": "equals",
      "value": "conversation.user.created"
    }
  ]
}

Contact Events

json
{
  "name": "Contact Events",
  "logic": "or",
  "conditions": [
    {
      "field": "topic",
      "operator": "starts_with",
      "value": "contact."
    },
    {
      "field": "topic",
      "operator": "starts_with",
      "value": "user."
    }
  ]
}

Closed Conversations with Tags

json
{
  "name": "Tagged Closures",
  "logic": "and",
  "conditions": [
    {
      "field": "topic",
      "operator": "equals",
      "value": "conversation.admin.closed"
    },
    {
      "field": "data.item.tags.tags",
      "operator": "not_empty",
      "value": ""
    }
  ]
}

Headers

Intercom sends these headers with webhooks:

HeaderDescription
X-Hub-SignatureHMAC-SHA1 signature with sha1= prefix
Content-TypeAlways application/json
X-Intercom-App-IdYour Intercom app ID
User-AgentIntercom user agent string

Troubleshooting

Signature Verification Failed

  1. Verify you're using the Client Secret from your Intercom app's Basic Information page
  2. Do not use the access token or API key — only the client secret is used for signing
  3. Ensure the verification config uses algorithm: "sha1" and signaturePrefix: "sha1="
  4. Check that the secret has no leading or trailing whitespace

Webhooks Not Arriving

  1. Check the Intercom Developer Hub for webhook delivery logs
  2. Verify the webhook URL is correct and publicly accessible
  3. Ensure you have selected the correct topics in Intercom's webhook settings
  4. Check that your Intercom app has the required permissions for the subscribed topics

Missing Events

  1. Verify the specific topics are enabled in your Intercom webhook configuration
  2. Check that filters aren't blocking expected events
  3. Some events require specific Intercom plans — verify your plan supports the topic
  4. Intercom may batch or delay certain low-priority events

Duplicate Events

  1. Intercom may retry failed webhook deliveries
  2. Implement idempotency using the notification id field
  3. Enable deduplication using the event ID:
bash
curl -X PATCH .../sources/src_intercom \
  -d '{"dedupEnabled": true, "dedupStrategy": "provider_id"}'

Best Practices

  1. Verify signatures: Always configure HMAC-SHA1 verification to ensure webhooks are from Intercom
  2. Handle HTML content: Conversation bodies contain HTML — strip tags when forwarding to plain-text destinations
  3. Use deduplication: Intercom retries failed deliveries, so enable dedup to prevent duplicates
  4. Subscribe selectively: Only subscribe to topics you need to reduce noise and processing overhead
  5. Handle idempotently: Use the notification id to detect and skip already-processed events
  6. Monitor rate limits: High-volume Intercom workspaces may generate significant webhook traffic — monitor delivery queues

Released under the MIT License.