# Salesloft Webhooks

## When to Use This Skill

* How do I receive Salesloft webhooks?
* How do I verify the Salesloft `x-salesloft-signature` header?
* Why is my Salesloft webhook signature verification failing?
* How do I handle `person_created`, `call_created`, `email_updated`, `meeting_booked`, or `cadence_membership_created` events?
* How do I create a Salesloft webhook subscription and choose a `callback_token`?

## Verification (core)

Salesloft sends `x-salesloft-signature`: the **hex-encoded HMAC-SHA1** of the request body, keyed with the subscription's `callback_token` (a string you choose when you create the subscription). No timestamp, no prefix. Verify against the **raw body**. The event name arrives in the `x-salesloft-event` header.

```javascript
const crypto = require('crypto');

function verifySalesloftSignature(rawBody, signature, callbackToken) {
  if (!signature || !callbackToken) return false;
  const expected = crypto.createHmac('sha1', callbackToken).update(rawBody).digest('hex');
  try {
    return crypto.timingSafeEqual(Buffer.from(signature.trim().toLowerCase()), Buffer.from(expected));
  } catch {
    return false; // length mismatch
  }
}

```

In Express read the body with `express.raw({ type: '*/*' })` so any content type verifies. Salesloft's schema says the `callback_token` is also in the payload, but the one published body (`link_swap`) doesn't show it, so don't rely on that; the header HMAC is the check.

> **For complete handlers with tests**, see [examples/express/](https://github.com/hookdeck/webhook-skills/tree/main/skills/salesloft-webhooks/examples/express/), [examples/nextjs/](https://github.com/hookdeck/webhook-skills/tree/main/skills/salesloft-webhooks/examples/nextjs/), [examples/fastapi/](https://github.com/hookdeck/webhook-skills/tree/main/skills/salesloft-webhooks/examples/fastapi/).

## Common Event Types

The event type is the `event_type` you subscribed to, delivered in the `x-salesloft-event` header.

| Event | Triggered When |
| --- | --- |
| `person_created` | A person is created |
| `person_updated` | A person is updated |
| `call_created` | A call is created |
| `email_updated` | An email is updated |
| `meeting_booked` | A meeting is created |
| `cadence_membership_created` | A person is added to a cadence |

Salesloft publishes more (accounts, cadences, notes, steps, tasks, users, conversations); see [references/overview.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/salesloft-webhooks/references/overview.md).

`link_swap` is different: Salesloft waits for your response and reads replacement links from it. See [references/overview.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/salesloft-webhooks/references/overview.md#link_swap).

## Important Headers

| Header | Description |
| --- | --- |
| `x-salesloft-signature` | HMAC-SHA1 hex digest of the body, keyed with `callback_token` |
| `x-salesloft-event` | Name of the event type that triggered the delivery |

## Environment Variables

```bash
SALESLOFT_CALLBACK_TOKEN=your_callback_token   # The callback_token set when creating the subscription

```

## Local Development

```bash
# Start tunnel (no account needed)
npx hookdeck-cli listen 3000 salesloft --path /webhooks/salesloft

```

## Reference Materials

* [references/overview.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/salesloft-webhooks/references/overview.md) - Salesloft webhooks, event types, retries
* [references/setup.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/salesloft-webhooks/references/setup.md) - Create a subscription through the API and choose a `callback_token`
* [references/verification.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/salesloft-webhooks/references/verification.md) - Signature details and debugging