Handling Webhooks
Learn how to receive and process webhook events from Sesamy.
Overview
Sesamy sends webhook notifications to your configured endpoints when specific events occur. Webhooks are designed to be lightweight, containing only essential identifiers. Your application should use these identifiers to fetch the full details from the Sesamy API.
Built-in Webhook Forwarding
If you want Sesamy to forward events to your endpoint without building a custom consumer, you can use the built-in webhook integration. Provide the following to your Sesamy account manager:
| Field | Type | Description |
|---|---|---|
url | string | Your endpoint URL |
headers | object | (Optional) Custom HTTP headers for authentication (e.g., Authorization: Bearer token) |
The built-in integration forwards six of the eight standard event types (all except entitlement.1#new and entitlement.1#update). Events that receive a 5xx or 429 response are retried with exponential backoff. See Integration Concepts for full retry details.
The rest of this page covers how to build your own webhook consumer for more advanced use cases.
Webhook Request Format
Webhooks are sent as HTTP POST requests with the following structure:
{
"eventType": "userVendor.1#new",
"vendorId": "vendor_123",
"userId": "user_456",
"contractId": "contract_789",
"entitlementId": "entitlement_012",
"checkoutId": "checkout_345",
"occured_at": "2025-11-10T12:00:00Z"
}Payload Fields
| Field | Type | Description |
|---|---|---|
eventType | string | The type of event that occurred (see Event Types below) |
vendorId | string | The vendor identifier |
userId | string | The user identifier |
occured_at | string | ISO 8601 timestamp of when the event occurred |
contractId | string | (Optional) Contract identifier, if applicable |
entitlementId | string | (Optional) Entitlement identifier, if applicable |
checkoutId | string | (Optional) Checkout identifier, if applicable |
Event Types
The following webhook events are available. For a comprehensive reference of events, tags, and retry behaviour used by built-in integrations, see Integration Concepts.
| Event Type | Description |
|---|---|
userVendor.1#new | A new user-vendor relationship was created |
userVendor.1#update | A user-vendor relationship was updated |
contract.1#purchased | A contract was purchased |
contract.1#update | A contract was updated |
contract#cancelRequest | A cancellation request was made for a contract |
entitlement.1#new | A new entitlement was created for a user |
entitlement.1#update | An existing entitlement was updated |
checkout.1#confirm | A checkout was confirmed |
Setting Up Webhook Endpoints
Your webhook endpoint should:
- Accept POST requests
- Respond quickly (within a few seconds)
- Return a 2xx status code to acknowledge receipt
- Process the webhook asynchronously if needed
Example Endpoint
app.post('/webhooks/sesamy', async (req, res) => {
const { eventType, vendorId, userId, contractId, occured_at } = req.body;
// Acknowledge receipt immediately
res.status(200).send('OK');
// Process asynchronously
processWebhook({ eventType, vendorId, userId, contractId, occured_at });
});Fetching Full Event Data
Webhooks contain minimal data to reduce payload size. Use the provided identifiers to fetch complete information from the Sesamy API:
async function processWebhook({ eventType, vendorId, userId, contractId, checkoutId }) {
switch (eventType) {
case 'contract.1#purchased':
case 'contract.1#update':
// Fetch contract details
const contract = await sesamyClient.getContract(contractId);
// Process contract data
break;
case 'userVendor.1#new':
case 'userVendor.1#update':
// Fetch user-vendor relationship
const userVendor = await sesamyClient.getUserVendor(vendorId, userId);
// Process user data
break;
case 'checkout.1#confirm':
// Fetch checkout details
const checkout = await sesamyClient.getCheckout(checkoutId);
// Process checkout data
break;
}
}Best Practices
1. Validate Webhook Authenticity
Always verify that webhooks are coming from Sesamy. Check the request headers and implement signature verification if available.
2. Handle Idempotency
Webhooks may be delivered more than once. Ensure your processing logic is idempotent by tracking processed event IDs.
const processedEvents = new Set();
async function processWebhook(payload) {
const eventId = `${payload.eventType}-${payload.occured_at}-${payload.userId}`;
if (processedEvents.has(eventId)) {
return; // Already processed
}
// Process the webhook
// ...
processedEvents.add(eventId);
}3. Implement Retry Logic
If fetching data from the Sesamy API fails, implement exponential backoff retry logic:
async function fetchWithRetry(apiCall, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await apiCall();
} catch (error) {
if (i === maxRetries - 1) throw error;
await new Promise((resolve) => setTimeout(resolve, Math.pow(2, i) * 1000));
}
}
}4. Log All Webhooks
Keep a log of all received webhooks for debugging and auditing:
app.post('/webhooks/sesamy', async (req, res) => {
// Log the webhook
logger.info('Webhook received', {
eventType: req.body.eventType,
timestamp: req.body.occured_at,
payload: req.body,
});
res.status(200).send('OK');
processWebhook(req.body);
});Testing Webhooks Locally
To test webhooks during development:
- Use a tool like ngrok to expose your local endpoint
- Configure the ngrok URL in your Sesamy vendor settings
- Trigger events in your test environment
- Monitor the webhook delivery in your local application
# Start ngrok
ngrok http 3000
# Use the ngrok URL as your webhook endpoint
# https://abc123.ngrok.io/webhooks/sesamyTroubleshooting
Webhooks Not Received
- Verify your endpoint is publicly accessible
- Check that your server responds with a 2xx status code
- Ensure your firewall allows incoming connections
- Review webhook logs in the Sesamy dashboard (if available)
Duplicate Webhooks
- Implement idempotency checks using event identifiers
- Store processed event IDs to prevent reprocessing
Missing Data
- Always fetch complete data from the API using the provided identifiers
- Don't rely solely on webhook payload for critical data
Next Steps
- Integration Concepts -- shared concepts for built-in integrations
- API Reference -- API endpoints for fetching event data
- Authentication -- securing API requests
- Subscriptions Guide -- managing subscription contracts