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:
- Go to Settings → Webhooks
- Click Create Webhook
- Enter your endpoint URL (must be HTTPS in production)
- Select which events to subscribe to
- Save and note your signing secret
Available Events
| Event | Description |
|---|---|
order.created | A new order was placed on your store |
order.shipped | An order was marked as shipped |
order.delivered | An order was marked as delivered |
listing.created | A new listing was created in your inventory |
listing.updated | A listing was updated (price, quantity, etc.) |
listing.deleted | A listing was removed from your inventory |
inventory.low | A 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:
| Header | Description |
|---|---|
Content-Type | application/json |
X-CTCGX-Signature | HMAC signature for verification |
X-CTCGX-Event | The event type (e.g., order.created) |
X-CTCGX-Delivery-Id | Unique ID for this delivery attempt |
Verifying Signatures
Important
Always verify webhook signatures to ensure requests are from CTCGX.
The X-CTCGX-Signature header contains:
t=1705320000,v1=abc123...
To verify:
- Extract the timestamp (
t) and signature (v1) - Create a signed payload:
{timestamp}.{request_body} - Compute HMAC-SHA256 using your webhook secret
- Compare with the
v1signature
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
Idempotency
Design your webhook handler to be idempotent. Use the delivery ID to detect and handle duplicate deliveries.
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.