Webhooks
Receive real-time notifications for marketplace events via HTTP callbacks.
Overview
Webhooks allow your application to receive automatic notifications when events occur in Automatum. Instead of polling the API, webhooks push data to your endpoint as events happen.
How Webhooks Work
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Event │────▶│ Automatum │────▶│ Your │
│ Occurs │ │ Webhook │ │ Endpoint │
└─────────────┘ └─────────────┘ └─────────────┘
│
▼
┌─────────────┐
│ Retry if │
│ Failed │
└─────────────┘- Event occurs in Automatum (e.g., offer accepted)
- Automatum sends HTTP POST to your endpoint
- Your endpoint processes the event
- Returns 2xx status to acknowledge receipt
- If failed, Automatum retries with exponential backoff
Setting Up Webhooks
Create Webhook Endpoint
- Navigate to Settings > Webhooks
- Click Add Webhook
- Configure:
- Endpoint URL: Your HTTPS endpoint
- Description: Human-readable name
- Events: Select events to subscribe
- Secret: Auto-generated signing secret
- Click Create Webhook
Endpoint Requirements
Your webhook endpoint must:
- Accept HTTP POST requests
- Use HTTPS (SSL/TLS required)
- Respond within 10 seconds (timeout enforced)
- Return 2xx status code on success
- Be publicly accessible
Example Endpoint (Node.js)
javascript
const express = require('express');
const crypto = require('crypto');
const app = express();
app.use(express.json());
const WEBHOOK_SECRET = process.env.AUTOMATUM_WEBHOOK_SECRET;
app.post('/webhooks/automatum', (req, res) => {
// Verify signature
const signature = req.headers['x-automatum-signature'];
const payload = JSON.stringify(req.body);
const expectedSignature = crypto
.createHmac('sha256', WEBHOOK_SECRET)
.update(payload)
.digest('hex');
if (signature !== `sha256=${expectedSignature}`) {
return res.status(401).send('Invalid signature');
}
// Process event
const event = req.body;
console.log('Received event:', event.type);
switch (event.type) {
case 'entitlement.created':
handleEntitlementCreated(event.data);
break;
case 'entitlement.updated':
handleEntitlementUpdated(event.data);
break;
case 'private_offer.accepted':
handleOfferAccepted(event.data);
break;
case 'metering.failed':
handleMeteringFailed(event.data);
break;
// Handle other events...
}
// Acknowledge receipt
res.status(200).json({ received: true });
});
app.listen(3000);Example Endpoint (Python)
python
from flask import Flask, request, jsonify
import hmac
import hashlib
import os
app = Flask(__name__)
WEBHOOK_SECRET = os.environ['AUTOMATUM_WEBHOOK_SECRET']
def verify_signature(payload, signature):
expected = hmac.new(
WEBHOOK_SECRET.encode(),
payload,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(f'sha256={expected}', signature)
@app.route('/webhooks/automatum', methods=['POST'])
def webhook():
signature = request.headers.get('X-Automatum-Signature')
if not verify_signature(request.data, signature):
return jsonify({'error': 'Invalid signature'}), 401
event = request.json
print(f"Received event: {event['type']}")
# Process event based on type
if event['type'] == 'entitlement.created':
handle_entitlement_created(event['data'])
elif event['type'] == 'private_offer.accepted':
handle_offer_accepted(event['data'])
elif event['type'] == 'metering.failed':
handle_metering_failed(event['data'])
return jsonify({'received': True}), 200
if __name__ == '__main__':
app.run(port=3000)Webhook Events
Entitlement Events
| Event | Description |
|---|---|
entitlement.created | New entitlement/contract created |
entitlement.updated | Entitlement details updated |
entitlement.renewed | Entitlement was renewed |
entitlement.cancelled | Entitlement was cancelled |
Private Offer Events
| Event | Description |
|---|---|
private_offer.created | New private offer created |
private_offer.accepted | Customer accepted offer |
Customer Events
| Event | Description |
|---|---|
customer.created | New customer registered |
customer.updated | Customer info updated |
Metering Events
| Event | Description |
|---|---|
metering.submitted | Usage report submitted |
metering.confirmed | Marketplace confirmed receipt |
metering.failed | Usage report failed |
Webhook Payload
Payload Structure
json
{
"id": "evt_1234567890",
"type": "private_offer.accepted",
"created": "2026-01-16T10:30:00Z",
"data": {
"id": "offer_abc123",
"customerId": "cust_xyz789",
"listingId": "listing_456",
"vendor": "aws",
"value": 50000,
"duration": 12,
"acceptedAt": "2026-01-16T10:30:00Z"
},
"organizationId": "org_123"
}Common Fields
| Field | Type | Description |
|---|---|---|
id | string | Unique event identifier |
type | string | Event type |
created | string | ISO 8601 timestamp |
data | object | Event-specific data |
organizationId | string | Your organization ID |
Event-Specific Data
entitlement.created:
json
{
"id": "ent_abc123",
"customerId": "cust_xyz789",
"listingId": "listing_456",
"details": {
"subscriptionStatus": "subscribed",
"entries": [
{
"name": "enterprise",
"units": 1,
"price": ""
}
],
"expiration": "2027-01-31T00:00:00Z",
"startDate": "2026-01-16T10:30:00Z"
}
}private_offer.accepted:
json
{
"id": "offer_abc123",
"listingId": "listing_456",
"vendorOfferId": "offer-123456",
"status": "accepted",
"details": {
"summary": {
"offerName": "Enterprise Deal",
"customerName": "Acme Corporation"
}
}
}metering.failed:
json
{
"id": "meter_abc123",
"listingId": "listing_456",
"customerId": "cust_xyz789",
"status": "failed",
"message": "Error message from marketplace",
"details": {
"reportingDate": "2026-01-16",
"usages": []
}
}Security
Signature Verification
Every webhook request includes a signature header:
X-Automatum-Signature: sha256=abc123...Always verify signatures to ensure requests are from Automatum.
Verification Code
javascript
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(`sha256=${expectedSignature}`)
);
}Security Best Practices
- Always verify signatures - Never trust unverified requests
- Use HTTPS - Encrypt data in transit
- Rotate secrets - Periodically regenerate webhook secrets
- Validate data - Check payload structure and types
- Idempotency - Handle duplicate deliveries gracefully
Retry Policy
Webhook delivery uses AWS SQS for reliable message delivery with automatic retries:
- SQS Retry Mechanism: Failed deliveries are automatically retried by SQS with exponential backoff
- Failure Tracking: Each webhook tracks failure count
- Auto-Disable: Webhooks are automatically disabled after 10 consecutive failures
- Manual Retry: Disabled webhooks can be re-enabled and retried from the dashboard
Managing Webhooks
View Webhook Logs
- Go to Settings > Webhooks
- Click on webhook endpoint
- View Delivery Logs
Log details include:
- Timestamp
- Event type
- Request payload
- Response status
- Response body
- Duration
Test Webhooks
Send test events to verify setup:
- Go to Settings > Webhooks
- Click on webhook endpoint
- Click Send Test Event
- Select event type
- Review delivery result
Disable/Enable Webhooks
Temporarily disable without deleting:
- Go to webhook settings
- Toggle Enabled switch
- Webhook paused (events not sent)
Delete Webhooks
Remove webhook permanently:
- Go to webhook settings
- Click Delete Webhook
- Confirm deletion
WARNING
Deleting a webhook stops all event delivery immediately. Events during downtime are not recoverable.
Webhook IP Addresses
If you need to whitelist IPs, Automatum webhooks originate from:
52.XX.XX.XX
52.XX.XX.XX
54.XX.XX.XXTIP
Contact support@automatum.io for current IP ranges.
Best Practices
1. Respond Quickly
Return 200 immediately, process async (must respond within 10 seconds):
javascript
app.post('/webhook', async (req, res) => {
// Acknowledge immediately
res.status(200).send('OK');
// Process asynchronously
processEventAsync(req.body);
});2. Handle Duplicates
Events may be delivered more than once:
javascript
const processedEvents = new Set();
function handleEvent(event) {
if (processedEvents.has(event.id)) {
return; // Already processed
}
processedEvents.add(event.id);
// Process event...
}3. Use Queues
For reliability, queue events for processing:
javascript
const Queue = require('bull');
const webhookQueue = new Queue('webhooks');
app.post('/webhook', (req, res) => {
webhookQueue.add(req.body);
res.status(200).send('OK');
});
webhookQueue.process(async (job) => {
await processEvent(job.data);
});4. Log Everything
Maintain detailed logs for debugging:
javascript
function handleWebhook(event) {
console.log({
eventId: event.id,
type: event.type,
receivedAt: new Date().toISOString(),
data: event.data
});
}5. Monitor Health
Track webhook delivery metrics:
- Success rate
- Average response time
- Error patterns
- Retry frequency
Troubleshooting
Not Receiving Webhooks
- Verify endpoint URL is correct
- Check endpoint is publicly accessible
- Confirm HTTPS certificate is valid
- Review firewall/security rules
- Check webhook is enabled
Signature Verification Failing
- Verify using correct secret
- Check payload encoding (UTF-8)
- Ensure no middleware modifies body
- Verify signature header name
Timeouts
- Respond within 10 seconds (timeout enforced)
- Process async after acknowledging
- Check endpoint performance
- Review server resources
Missing Events
- Check event types are subscribed
- Review webhook logs
- Verify endpoint returned 2xx
- Check for filtered events
API Reference
::: note Webhook Management Webhook management endpoints are available through the Automatum dashboard. The webhook API routes are internal and not part of the public OAuth API (/api/v1/*). To manage webhooks, use the dashboard at Settings > Webhooks. :::
Webhook Management via Dashboard
- Create Webhook: Navigate to Settings > Webhooks > Add Webhook
- List Webhooks: View all webhooks in Settings > Webhooks
- Update Webhook: Click on a webhook to edit its configuration
- Delete Webhook: Click Delete on the webhook details page
- Test Webhook: Click Send Test Event to verify your endpoint
Webhook Configuration
When creating or updating a webhook, you can configure:
- Name: Human-readable identifier
- Description: Optional description
- URL: HTTPS endpoint URL (required)
- Events: Array of event types to subscribe to (at least one required)
- Secret: Optional signing secret for signature verification
- Active Status: Enable/disable webhook delivery
Next Steps
Need Help?
Contact support@automatum.io for webhook assistance.