Integration

Webhook Setup

Receive real-time notifications when events occur in your Commerce Index account. Configure webhooks to keep your systems in sync.

Registering Webhooks

You can register webhook endpoints through the Commerce Index dashboard or via the API. In the dashboard, navigate to Settings → Webhooks → Add Endpoint and enter your URL and select the events you want to receive.

Alternatively, register programmatically via the API:

// Register a webhook via API
const response = await fetch('https://api.commerceindex.ai/v1/webhooks', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-CI-Api-Key': 'your_api_key',
    'X-CI-Merchant-Id': 'merch_xyz789'
  },
  body: JSON.stringify({
    url: 'https://your-server.com/webhooks/ci',
    events: [
      'product.updated',
      'order.created',
      'deal.created',
      'health.score_change'
    ],
    secret: 'whsec_your_webhook_secret'
  })
});

const webhook = await response.json();
console.log('Webhook registered:', webhook.id);

Event Types

Subscribe to any combination of the following event types:

EventDescription
product.createdA new product is added to your catalog
product.updatedProduct details (price, title, inventory) are modified
product.deletedA product is removed from the catalog
order.createdA new order is placed
order.paidPayment is confirmed for an order
order.fulfilledAn order has been shipped or fulfilled
inventory.lowStock falls below the configured threshold
deal.createdAn AI agent creates a new deal
deal.expiredA deal reaches its expiration date
agent.decisionAn agent makes a decision requiring notification
health.score_changeYour CI Health Score changes significantly

Payload Format

All webhook payloads follow a consistent JSON structure with the event type, timestamp, event data, and your merchant ID:

{
  "event": "product.updated",
  "timestamp": "2026-01-15T10:30:00Z",
  "data": {
    "product_id": "prod_abc123",
    "title": "Wireless Bluetooth Headphones",
    "price": 79.99,
    "previous_price": 99.99,
    "inventory": 42,
    "changes": ["price", "inventory"]
  },
  "merchant_id": "merch_xyz789",
  "webhook_id": "wh_evt_def456"
}

Signature Verification

Every webhook request includes an X-CI-Signature header containing an HMAC-SHA256 signature of the request body. Always verify this signature to ensure the webhook is authentic and hasn't been tampered with.

  1. 1. Extract the X-CI-Signature header from the request
  2. 2. Compute HMAC-SHA256 of the raw request body using your webhook secret
  3. 3. Compare the computed hash with the received signature using a timing-safe comparison
  4. 4. Reject the request if signatures don't match

Retry Policy

If your endpoint returns a non-2xx status code or times out, Commerce Index will retry delivery up to 3 times with exponential backoff:

1 second

Retry 1

Immediate retry for transient failures

5 seconds

Retry 2

Short delay for temporary outages

30 seconds

Retry 3

Final attempt before marking as failed

Your endpoint must respond within 10 seconds. After all retries are exhausted, the event is logged as failed and visible in your dashboard under Webhooks → Failed Deliveries.

Node.js Handler Example

// Node.js webhook handler (Express)
const express = require('express');
const crypto = require('crypto');

const app = express();
app.use(express.raw({ type: 'application/json' }));

const WEBHOOK_SECRET = process.env.CI_WEBHOOK_SECRET;

function verifySignature(payload, signature) {
  const expected = crypto
    .createHmac('sha256', WEBHOOK_SECRET)
    .update(payload)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

app.post('/webhooks/ci', (req, res) => {
  const signature = req.headers['x-ci-signature'];

  if (!verifySignature(req.body, signature)) {
    return res.status(401).json({ error: 'Invalid signature' });
  }

  const event = JSON.parse(req.body);

  switch (event.event) {
    case 'product.updated':
      console.log('Product updated:', event.data.product_id);
      // Sync product changes to your system
      break;
    case 'order.created':
      console.log('New order:', event.data.order_id);
      break;
    case 'deal.created':
      console.log('New deal:', event.data.deal_id);
      break;
    case 'health.score_change':
      console.log('Health score changed:', event.data.new_score);
      break;
    default:
      console.log('Unhandled event:', event.event);
  }

  res.status(200).json({ received: true });
});

app.listen(3000, () => console.log('Webhook server running on port 3000'));

Python Handler Example

# Python webhook handler (Flask)
import hmac
import hashlib
import json
from flask import Flask, request, jsonify

app = Flask(__name__)
WEBHOOK_SECRET = os.environ.get('CI_WEBHOOK_SECRET')

def verify_signature(payload, signature):
    expected = hmac.new(
        WEBHOOK_SECRET.encode('utf-8'),
        payload,
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature)

@app.route('/webhooks/ci', methods=['POST'])
def handle_webhook():
    signature = request.headers.get('X-CI-Signature')

    if not verify_signature(request.data, signature):
        return jsonify({'error': 'Invalid signature'}), 401

    event = request.get_json()

    if event['event'] == 'product.updated':
        print(f"Product updated: {event['data']['product_id']}")
        # Sync product changes
    elif event['event'] == 'order.created':
        print(f"New order: {event['data']['order_id']}")
    elif event['event'] == 'deal.created':
        print(f"New deal: {event['data']['deal_id']}")
    elif event['event'] == 'health.score_change':
        print(f"Health score: {event['data']['new_score']}")

    return jsonify({'received': True}), 200

if __name__ == '__main__':
    app.run(port=3000)

What's Next?