Skip to content
Back to skills

Salesforce Webhooks Events

ASecurity

'Implement Salesforce Platform Events, Change Data Capture (CDC), and Outbound Messages. Use when building real-time integrations, listening for record changes, or implementing event-driven architecture with Salesforce. Trigger with phrases like \"salesforce events\", \"salesforce CDC\", \"salesforce platform events\", \"salesforce streaming\", \"salesforce outbound message\", \"salesforce real-time\". '

  • 3 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 12, 2026
ai-agentstypescriptgobashexpressgitapisecurityperformance

Works with

  • cli
  • api

Security analysis

A100/100

Scanned September 12, 2026

npx -y skills add thedixitjain/the-mega-skill-library --skill salesforce-webhooks-events --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Salesforce Webhooks Events?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Salesforce Webhooks Events
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/thedixitjain-salesforce-webhooks-events/badge)](https://www.skillsdirectory.com/skills/thedixitjain-salesforce-webhooks-events)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: salesforce-webhooks-events
description: "'Implement Salesforce Platform Events, Change Data Capture (CDC), and Outbound Messages. Use when building real-time integrations, listening for record changes, or implementing event-driven architecture with Salesforce. Trigger with phrases like \"salesforce events\", \"salesforce CDC\", \"salesforce platform events\", \"salesforce streaming\", \"salesforce outbound message\", \"salesforce real-time\". '"
allowed-tools: "Read, Write, Edit, Bash(curl:*), Bash(sf:*)"
category: engineering-core
source_repo: jeremylongshore/claude-code-plugins-plus-skills
source_path: "plugins/saas-packs/salesforce-pack/skills/salesforce-webhooks-events/SKILL.md"
source_url: https://github.com/jeremylongshore/claude-code-plugins-plus-skills/blob/HEAD/plugins/saas-packs/salesforce-pack/skills/salesforce-webhooks-events/SKILL.md
---

# Salesforce Webhooks & Events

## Overview

Salesforce doesn't use traditional webhooks. Instead, it offers Platform Events, Change Data Capture (CDC), and Outbound Messages for real-time data flow. All use the CometD (Bayeux) streaming protocol via jsforce.

## Prerequisites

- jsforce installed with connection configured
- Platform Events or CDC enabled in your org
- Understanding of publish/subscribe patterns
- Express.js for Outbound Message endpoints

## Event Mechanism Comparison

| Mechanism | Direction | Use Case | Retention |
|-----------|-----------|----------|-----------|
| Platform Events | Bi-directional | Custom event bus | 72 hours |
| Change Data Capture (CDC) | Salesforce → External | Record change notifications | 3 days |
| Outbound Messages | Salesforce → External | Workflow-triggered HTTP POST | Until confirmed |
| Streaming API (PushTopics) | Salesforce → External | SOQL-based subscriptions | No replay |

## Instructions

### Step 1: Subscribe to Change Data Capture (CDC)

```typescript
import jsforce from 'jsforce';

const conn = new jsforce.Connection({
  loginUrl: process.env.SF_LOGIN_URL,
});
await conn.login(process.env.SF_USERNAME!, process.env.SF_PASSWORD! + process.env.SF_SECURITY_TOKEN!);

// Subscribe to Account changes
// CDC channel format: /data/AccountChangeEvent
const subscription = conn.streaming.topic('/data/AccountChangeEvent').subscribe((message) => {
  const header = message.payload.ChangeEventHeader;
  console.log('Change Type:', header.changeType);       // CREATE, UPDATE, DELETE, UNDELETE
  console.log('Record IDs:', header.recordIds);
  console.log('Changed Fields:', header.changedFields);
  console.log('User ID:', header.commitUser);

  // Access changed field values
  if (header.changeType === 'UPDATE') {
    console.log('New values:', message.payload);
    // Only changed fields are populated in the payload
  }
});

// Enable CDC for objects in Setup:
// Setup > Integrations > Change Data Capture > Select Objects
```

### Step 2: Publish and Subscribe to Platform Events

```typescript
// Define a Platform Event in Salesforce:
// Setup > Platform Events > New Platform Event
// Example: Order_Status__e with fields:
//   - Order_Id__c (Text)
//   - Status__c (Text)
//   - Amount__c (Number)

// Publish a Platform Event via API
await conn.sobject('Order_Status__e').create({
  Order_Id__c: 'ORD-12345',
  Status__c: 'Shipped',
  Amount__c: 499.99,
});

// Subscribe to Platform Events
const eventSub = conn.streaming.topic('/event/Order_Status__e').subscribe((message) => {
  console.log('Event received:', {
    orderId: message.payload.Order_Id__c,
    status: message.payload.Status__c,
    amount: message.payload.Amount__c,
    replayId: message.event.replayId,
  });
});

// Use replayId to resume from a specific point (-1 = new only, -2 = all available)
conn.streaming.topic('/event/Order_Status__e', { replayId: -2 }).subscribe((message) => {
  // Receives all stored events (up to 72 hours)
});
```

### Step 3: Handle Outbound Messages (SOAP-based)

```typescript
// Outbound Messages are sent by Salesforce Workflow Rules or Flows
// They are SOAP XML posts to your endpoint

import express from 'express';
import { parseString } from 'xml2js';

const app = express();
app.use(express.text({ type: 'text/xml' }));

app.post('/salesforce/outbound-message', (req, res) => {
  parseString(req.body, (err, result) => {
    if (err) {
      console.error('XML parse error:', err);
      return res.status(400).send('Invalid XML');
    }

    // Extract notification data
    const notification = result['soapenv:Envelope']['soapenv:Body'][0]
      ['notifications'][0]['Notification'][0];

    const sobject = notification['sObject'][0];
    console.log('Record ID:', sobject['sf:Id'][0]);
    console.log('Object Type:', sobject.$['xsi:type']);

    // Respond with acknowledgment (required!)
    res.type('text/xml').send(`<?xml version="1.0" encoding="UTF-8"?>
      <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
        xmlns:out="http://soap.sforce.com/2005/09/outbound">
        <soapenv:Body>
          <out:notificationsResponse>
            <out:Ack>true</out:Ack>
          </out:notificationsResponse>
        </soapenv:Body>
      </soapenv:Envelope>`);
  });
});
```

### Step 4: Robust Event Processing

```typescript
// Idempotent event handler with replay ID tracking
import { Redis } from 'ioredis';
const redis = new Redis(process.env.REDIS_URL);

async function processEvent(message: any): Promise<void> {
  const replayId = message.event.replayId;
  const eventKey = `sf:event:${replayId}`;

  // Check if already processed (idempotency)
  if (await redis.exists(eventKey)) {
    console.log(`Event ${replayId} already processed, skipping`);
    return;
  }

  try {
    // Process the event
    const changeType = message.payload.ChangeEventHeader?.changeType;
    const recordIds = message.payload.ChangeEventHeader?.recordIds || [];

    switch (changeType) {
      case 'CREATE':
        await handleRecordCreated(recordIds, message.payload);
        break;
      case 'UPDATE':
        await handleRecordUpdated(recordIds, message.payload);
        break;
      case 'DELETE':
        await handleRecordDeleted(recordIds);
        break;
    }

    // Mark as processed with 7-day TTL
    await redis.set(eventKey, '1', 'EX', 86400 * 7);

    // Save replay ID for resume on restart
    await redis.set('sf:last-replay-id', replayId.toString());
  } catch (error) {
    console.error(`Failed to process event ${replayId}:`, error);
    throw error; // Let retry logic handle it
  }
}
```

## Output

- CDC subscription for real-time record change notifications
- Platform Event publishing and subscribing
- Outbound Message endpoint with SOAP acknowledgment
- Idempotent event processing with replay ID tracking

## Error Handling

| Issue | Cause | Solution |
|-------|-------|----------|
| `403: CDC not enabled` | Object not selected for CDC | Setup > Change Data Capture > select objects |
| `EVENT_OR_PUSHTTOPIC_NOT_FOUND` | Platform Event doesn't exist | Create in Setup > Platform Events |
| Missed events | Client disconnected | Use `replayId` to resume from last position |
| Duplicate processing | No idempotency check | Track processed `replayId` values in Redis |
| Outbound Message retry | Ack not sent | Return `<Ack>true</Ack>` XML response |

## Resources

- [Change Data Capture Developer Guide](https://developer.salesforce.com/docs/atlas.en-us.change_data_capture.meta/change_data_capture/)
- [Platform Events Developer Guide](https://developer.salesforce.com/docs/atlas.en-us.platform_events.meta/platform_events/)
- [Streaming API](https://developer.salesforce.com/docs/atlas.en-us.api_streaming.meta/api_streaming/)
- [Outbound Messaging](https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_om_outboundmessaging.htm)

## Next Steps

For performance optimization, see `salesforce-performance-tuning`.

---

**Source:** [`jeremylongshore/claude-code-plugins-plus-skills`](https://github.com/jeremylongshore/claude-code-plugins-plus-skills) → `plugins/saas-packs/salesforce-pack/skills/salesforce-webhooks-events/SKILL.md`

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.