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.
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:
| 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 |
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
Related Documentation
- API Reference - API endpoints for fetching event data
- Authentication - Securing API requests
- Subscriptions Guide - Managing subscription contracts