S
SalesInt.
/Docs
Get API Key

Webhooks

SalesInt sends HTTP POST callbacks to your endpoint when events occur — lead captured, message received, post published, and more. Subscribe only to the events you actually handle.

Best Practices

  • Subscribe only to the events you actually handle.
  • Treat each delivery as an event notification, not a full sync.
  • Use the webhook event ID as your deduplication key.
  • Verify the X-SalesInt-Signature header when a webhook secret is configured.
  • Acknowledge fast — return a 2xx immediately, then process async.

Delivery Flow

  1. Create a webhook endpoint in Dashboard → Webhooks.
  2. Choose the events you want to subscribe to.
  3. Receive a POST request from SalesInt whenever one of those events occurs.
  4. Return a 2xx response after accepting the payload.
  5. Use Test Webhook and Webhook Logs to validate your integration.

Delivery Retries

A delivery is successful when your endpoint returns a 2xx within 5 seconds. Any other outcome triggers a retry on an exponential backoff schedule capped at 24 hours. Up to 7 attempts are made per event.

AttemptDelay BeforeCumulative Time
1Immediate0
210s~10s
31m 40s~1m 50s
416m 40s~18m 30s
52h 46m~3h 5m
624h (capped)~27h 5m
724h (capped)~51h 5m
⚠️After the 7th attempt fails, the event is moved to a dead-letter queue and no longer retried automatically. Keep your handler fast — acknowledge immediately, process in background.

Idempotency

Webhook deliveries use at-least-once semantics — the same event may arrive more than once. Your handler must be idempotent. Use the payload.id field (also sent as X-SalesInt-Event-Id header) as your deduplication key.

Signature Verification

When a webhook secret is configured, every delivery includes an X-SalesInt-Signature header — the lowercase hex HMAC-SHA256 of the raw request body keyed by your secret.

javascript
import crypto from 'crypto';

export const POST = async (req) => {
  const sig = req.headers.get('X-SalesInt-Signature');
  if (!sig) return new Response('No signature', { status: 401 });

  const secret = process.env.SALESINT_WEBHOOK_SECRET;
  const rawBody = await req.text();

  const computed = crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex');

  if (sig !== computed) {
    return new Response('Invalid signature', { status: 400 });
  }

  const payload = JSON.parse(rawBody);

  // Handle the event
  switch (payload.event) {
    case 'lead.captured':
      await handleNewLead(payload.lead);
      break;
    case 'message.received':
      await handleInboundMessage(payload.message);
      break;
    case 'post.published':
      await handlePostPublished(payload.post);
      break;
  }

  return new Response('OK', { status: 200 });
};

Available Events

EventDescription
lead.capturedFired when a new lead is captured by the AI chatbot on any channel.
lead.qualifiedFired when a lead crosses your intent score threshold.
conversation.startedFired once when a new conversation begins between your account and a contact.
message.receivedFired when a new inbound message is received across any channel.
message.sentFired when an outgoing message is sent from the inbox.
message.deliveredFired when an outgoing message is delivered (WhatsApp, Messenger).
message.readFired when an outgoing message is read (WhatsApp, Messenger, Instagram).
message.failedFired when an outgoing message fails to deliver (WhatsApp only).
comment.receivedFired when a new comment is received on a tracked post.
post.publishedFired when a scheduled post is successfully published.
post.failedFired when a post fails to publish on all target platforms.
post.partialFired when a post publishes on some platforms and fails on others.
post.scheduledFired when a post is scheduled for future publishing.
account.connectedFired when a social account is successfully connected.
account.disconnectedFired when a connected social account becomes disconnected.
broadcast.sentFired when a broadcast is sent to all recipients.
campaign.sentFired when an email campaign delivery completes.
review.newFired when a new review is posted on a connected Google Business account.
review.updatedFired when a review is edited or a reply is added.
webhook.testFired when sending a test webhook to verify endpoint configuration.

Sample Payload — lead.captured

json
{
  "id": "evt_01j9xyz...",
  "event": "lead.captured",
  "timestamp": "2026-06-05T10:22:00Z",
  "lead": {
    "id": "lead_abc123",
    "name": "Jane Smith",
    "email": "jane@company.com",
    "phone": "+1-555-0100",
    "channel": "website",
    "websiteId": "web_xyz",
    "intentScore": 82,
    "stage": "hot"
  }
}

Sample Payload — message.received

json
{
  "id": "evt_02k9abc...",
  "event": "message.received",
  "timestamp": "2026-06-05T10:23:15Z",
  "message": {
    "id": "msg_def456",
    "text": "Hi, I'd like to know more about your pricing",
    "platform": "whatsapp",
    "from": "+1-555-0200"
  },
  "conversation": {
    "id": "conv_ghi789",
    "contactId": "contact_jkl012"
  },
  "account": {
    "id": "acc_mno345",
    "platform": "whatsapp"
  }
}