Webhooks

Receive real-time notifications when events happen on your store. Webhooks are HTTP POST requests sent to your server.

Setting Up Webhooks

Create webhooks from your store dashboard:

  1. Go to Settings → Webhooks
  2. Click Create Webhook
  3. Enter your endpoint URL (must be HTTPS in production)
  4. Select which events to subscribe to
  5. Save and note your signing secret

Available Events

EventDescription
order.createdA new order was placed on your store
order.shippedAn order was marked as shipped
order.deliveredAn order was marked as delivered
listing.createdA new listing was created in your inventory
listing.updatedA listing was updated (price, quantity, etc.)
listing.deletedA listing was removed from your inventory
inventory.lowA listing's quantity fell below the threshold

Webhook Payload

All webhook payloads follow this structure:

{
  "id": "whd_xxx...",
  "event": "order.created",
  "createdAt": "2024-01-15T10:00:00Z",
  "data": {
    // Event-specific data
    "order": {
      "id": "order_xxx...",
      "orderNumber": "CTCGX-12345",
      "status": "CONFIRMED",
      "totalAmount": 2499,
      // ... full order details
    }
  }
}

Request Headers

Each webhook request includes these headers:

HeaderDescription
Content-Typeapplication/json
X-CTCGX-SignatureHMAC signature for verification
X-CTCGX-EventThe event type (e.g., order.created)
X-CTCGX-Delivery-IdUnique ID for this delivery attempt

Verifying Signatures

The X-CTCGX-Signature header contains:

t=1705320000,v1=abc123...

To verify:

  1. Extract the timestamp (t) and signature (v1)
  2. Create a signed payload: {timestamp}.{request_body}
  3. Compute HMAC-SHA256 using your webhook secret
  4. Compare with the v1 signature

Example (Node.js)

const crypto = require('crypto');

function verifyWebhook(payload, signature, secret) {
  const [tPart, v1Part] = signature.split(',');
  const timestamp = tPart.split('=')[1];
  const expectedSig = v1Part.split('=')[1];

  const signedPayload = `${timestamp}.${payload}`;
  const computedSig = crypto
    .createHmac('sha256', secret)
    .update(signedPayload)
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(computedSig),
    Buffer.from(expectedSig)
  );
}

Retry Policy

If your endpoint returns a non-2xx status code, we'll retry:

  • 5 attempts with exponential backoff
  • Retries at: 1 min, 5 min, 30 min, 2 hours, 24 hours
  • After 10 consecutive failures, the webhook is disabled

Best Practices

Respond Quickly

Return a 200 response immediately, then process the event asynchronously. We timeout after 30 seconds.

Handle Duplicates

Store the delivery ID and check for duplicates before processing. Retries may send the same event multiple times.

Use HTTPS

In production, your webhook endpoint must use HTTPS. HTTP endpoints are only allowed in test mode.

API Playground

Select an endpoint from the documentation to try it out here.