Skip to content

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 delivery is handled

You create and configure webhook endpoints through Automatum, but the actual delivery of events — signing requests, retrying failures, and applying backoff — is performed by Automatum’s webhook delivery service, a separate downstream component. The behavior described below (the signature scheme, retry policy, and auto-disable thresholds) reflects that delivery service.

How Webhooks Work

┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│  Event      │────▶│  Automatum  │────▶│  Your       │
│  Occurs     │     │  Webhook    │     │  Endpoint   │
└─────────────┘     └─────────────┘     └─────────────┘


                    ┌─────────────┐
                    │  Retry if   │
                    │  Failed     │
                    └─────────────┘
  1. Event occurs in Automatum (e.g., offer accepted)
  2. The webhook delivery service sends an HTTP POST to your endpoint
  3. Your endpoint processes the event
  4. Returns 2xx status to acknowledge receipt
  5. If failed, the delivery service retries with exponential backoff

Setting Up Webhooks

Create Webhook Endpoint

  1. Navigate to Settings > Webhooks
  2. Click Add Webhook
  3. Configure:
    • Endpoint URL: Your HTTPS endpoint
    • Description: Human-readable name
    • Events: Select events to subscribe
    • Secret: Auto-generated signing secret
  4. Click Create Webhook

Endpoint Requirements

Your webhook endpoint must:

  • Accept HTTP POST requests
  • Use HTTPS (SSL/TLS required)
  • Respond promptly (the delivery service enforces a request timeout)
  • 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

The type field is a string. Marketplace business events (entitlement.*, private_offer.*, metering.*) are emitted by Automatum’s marketplace backend, and co-sell events (cosell.*) are emitted directly by the API when an opportunity or referral changes state. webhook.test is sent by the Send Test Event action. Subscribe a webhook only to the events it needs; a webhook receives an event only if its Events list includes that type.

Test Events

EventDescription
webhook.testSent when you use Send Test Event to verify your endpoint

Entitlement Events

EventDescription
entitlement.createdNew entitlement/contract created
entitlement.updatedEntitlement details updated
entitlement.renewedEntitlement was renewed
entitlement.cancelledEntitlement was cancelled

Private Offer Events

EventDescription
private_offer.createdNew private offer created
private_offer.acceptedCustomer accepted offer

Customer Events

EventDescription
customer.createdNew customer registered
customer.updatedCustomer info updated

Metering Events

EventDescription
metering.submittedUsage report submitted
metering.confirmedMarketplace confirmed receipt
metering.failedUsage report failed

Co-Sell Events

Emitted for AWS ACE opportunities and Azure Partner Center referrals. ACE has no "Closed Won" stage — a win is the Launched stage, reported as cosell.opportunity.won.

EventDescription
cosell.opportunity.createdACE opportunity submitted to AWS
cosell.opportunity.updatedACE opportunity stage changed
cosell.opportunity.wonACE opportunity reached Launched
cosell.opportunity.lostACE opportunity reached Closed Lost
cosell.referral.createdAzure referral created in Partner Center
cosell.referral.acceptedAzure referral accepted
cosell.referral.wonAzure referral closed as Won
cosell.referral.lostAzure referral closed as Lost
cosell.referral.declinedAzure referral declined

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

FieldTypeDescription
idstringUnique event identifier
typestringEvent type
createdstringISO 8601 timestamp
dataobjectEvent-specific data
organizationIdstringYour 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

The webhook delivery service signs every request with an HMAC-SHA256 signature over the payload, using your webhook secret, and sends it in a header:

X-Automatum-Signature: sha256=abc123...

Always verify signatures to ensure requests are from Automatum. Because signing is performed by the delivery service, verify against the secret shown for your webhook in the dashboard.

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

  1. Always verify signatures - Never trust unverified requests
  2. Use HTTPS - Encrypt data in transit
  3. Rotate secrets - Periodically regenerate webhook secrets
  4. Validate data - Check payload structure and types
  5. Idempotency - Handle duplicate deliveries gracefully

Retry Policy

Retries and backoff are handled by Automatum’s webhook delivery service, not by this API. The delivery service applies the following behavior:

  • Request timeout: Each delivery attempt waits up to 10 seconds for a response.
  • Success: Any 2xx status acknowledges the event.
  • Retryable failures: Network errors, timeouts, HTTP 429, and HTTP 5xx are retried — up to 12 attempts before the event is dropped to a dead-letter queue.
  • Permanent failures: Other 4xx responses (for example 400, 401, 403, 404, 410) are treated as permanent. The event is not retried, because a repeated attempt would fail the same way.
  • Failure tracking: Consecutive failures are counted per webhook.
  • Auto-disable: A webhook is disabled after 10 consecutive failures. A successful delivery resets the counter.
  • Manual retry: Disabled webhooks can be re-enabled from the dashboard.

Design your endpoint to return the right status

Return a 2xx only after you have accepted the event. Return a 5xx (or 429) when you want Automatum to retry later. Return a 4xx only for a request your endpoint can never accept — that stops the retries.

Managing Webhooks

View Webhook Logs

  1. Go to Settings > Webhooks
  2. Click on webhook endpoint
  3. View Delivery Logs

Log details include:

  • Timestamp
  • Event type
  • Request payload
  • Response status
  • Response body
  • Duration

Test Webhooks

Send test events to verify setup:

  1. Go to Settings > Webhooks
  2. Click on webhook endpoint
  3. Click Send Test Event
  4. Select event type
  5. Review delivery result

Disable/Enable Webhooks

Temporarily disable without deleting:

  1. Go to webhook settings
  2. Toggle Enabled switch
  3. Webhook paused (events not sent)

Delete Webhooks

Remove webhook permanently:

  1. Go to webhook settings
  2. Click Delete Webhook
  3. 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.XX

TIP

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

  1. Verify endpoint URL is correct
  2. Check endpoint is publicly accessible
  3. Confirm HTTPS certificate is valid
  4. Review firewall/security rules
  5. Check webhook is enabled

Signature Verification Failing

  1. Verify using correct secret
  2. Check payload encoding (UTF-8)
  3. Ensure no middleware modifies body
  4. Verify signature header name

Timeouts

  1. Respond promptly (the delivery service enforces a request timeout)
  2. Process async after acknowledging
  3. Check endpoint performance
  4. Review server resources

Missing Events

  1. Check event types are subscribed
  2. Review webhook logs
  3. Verify endpoint returned 2xx
  4. 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

  1. Create Webhook: Navigate to Settings > Webhooks > Add Webhook
  2. List Webhooks: View all webhooks in Settings > Webhooks
  3. Update Webhook: Click on a webhook to edit its configuration
  4. Delete Webhook: Click Delete on the webhook details page
  5. 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.

Automatum GTM Platform