Webhooks
Webhooks let SalesOS send HTTP POST requests to your server when specific events occur. Use them to sync data in real time, trigger external workflows, or build custom notifications.
How Webhooks Work
- You register a webhook URL and select which events to listen for
- When a matching event occurs in SalesOS, it sends a POST request to your URL
- Your server processes the payload and returns a
200 response
- If your server does not respond, SalesOS retries with exponential backoff
Managing Webhooks
Create a Webhook
| Field | Type | Required | Description |
|---|
url | string | Yes | The HTTPS URL to receive events |
events | array | Yes | List of event types to subscribe to |
secret | string | No | A secret key for payload verification (recommended) |
description | string | No | Friendly name for this webhook |
active | boolean | No | Whether the webhook is active (default: true) |
Example
curl -X POST "https://api.play2sell.com/v1/webhooks" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-server.com/webhooks/salesos",
"events": ["deal.won", "deal.lost", "lead.created"],
"secret": "whsec_your_secret_key_here",
"description": "CRM sync webhook"
}'
List Webhooks
Update a Webhook
Delete a Webhook
Event Types
Deal Events
| Event | Fires When |
|---|
deal.created | A new deal is created |
deal.updated | Any deal field is updated |
deal.stage_changed | A deal moves to a different stage |
deal.won | A deal is closed as won |
deal.lost | A deal is closed as lost |
deal.deleted | A deal is deleted |
Lead Events
| Event | Fires When |
|---|
lead.created | A new lead is created |
lead.updated | Any lead field is updated |
lead.status_changed | Lead status changes |
lead.converted | A lead is converted to a deal |
lead.deleted | A lead is deleted |
User Events
| Event | Fires When |
|---|
user.created | A new user is invited |
user.activated | A user accepts their invitation |
user.updated | User profile or role changes |
user.deactivated | A user is deactivated |
Gamification Events
| Event | Fires When |
|---|
badge.earned | A user earns a badge |
ranking.changed | A user’s ranking position changes |
challenge.completed | A user completes a challenge goal |
All webhook payloads follow the same structure:
{
"id": "evt_abc123def456",
"type": "deal.won",
"created_at": "2026-03-15T14:30:00Z",
"data": {
"id": "880e8400-e29b-41d4-a716-446655440000",
"name": "Tech Corp - Enterprise License",
"value": 82000,
"stage": "Closed Won",
"owner_id": "660e8400-e29b-41d4-a716-446655440001",
"previous_stage": "Negotiation"
}
}
Payload Fields
| Field | Description |
|---|
id | Unique event ID (for deduplication) |
type | The event type |
created_at | When the event occurred |
data | The event payload (varies by event type) |
Verifying Webhook Signatures
If you set a secret when creating the webhook, SalesOS includes a signature header for verification:
X-SalesOS-Signature: sha256=abc123...
Verify the signature on your server:
const crypto = require('crypto');
function verifyWebhook(payload, signature, secret) {
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
Always verify webhook signatures in production. Without verification, anyone who knows your webhook URL could send fake events to your server.
Retry Policy
If your server does not return a 2xx response, SalesOS retries the webhook:
| Attempt | Delay |
|---|
| 1st retry | 1 minute |
| 2nd retry | 5 minutes |
| 3rd retry | 30 minutes |
| 4th retry | 2 hours |
| 5th retry | 12 hours |
After 5 failed retries, the event is marked as failed. You can view failed deliveries in Admin > Integrations > Webhooks > Delivery Log.
If a webhook consistently fails (10 consecutive failures), it is automatically deactivated. You receive an email notification when this happens.
Webhook Logs
View delivery history for each webhook:
GET /v1/webhooks/:id/deliveries
Each delivery log entry includes:
- Event type and payload
- HTTP response code from your server
- Response time
- Success or failure status
- Retry count
Use the delivery log to debug webhook issues. You can also replay any failed delivery by clicking Retry in the webhook management UI.
Best Practices
- Use HTTPS — Webhook URLs must use HTTPS for security
- Verify signatures — Always validate the
X-SalesOS-Signature header
- Respond quickly — Return a
200 response within 10 seconds; process the payload asynchronously if needed
- Handle duplicates — Use the event
id for deduplication, as retries may deliver the same event multiple times
- Monitor failures — Check the delivery log regularly and fix endpoint issues promptly
Next Steps