Webhooks
Receive real-time notifications when events happen in your TruCustom account.
Overview
Webhooks allow your application to receive HTTP POST notifications when specific events occur, such as when a customer finalizes a design. This enables you to build reactive integrations without polling the API.
Available Events
| Event | Description |
|---|---|
design.created |
A new design session was started |
design.updated |
A design was saved/updated |
design.finalized |
A design was finalized (customer completed customization) |
product.synced |
Products were synced from your e-commerce platform |
Webhook Payload
All webhook payloads follow this structure:
{
"event": "design.finalized",
"timestamp": "2024-01-15T10:30:00Z",
"data": {
"id": "design-uuid",
"session_token": "abc123...",
"product_id": "product-uuid",
"product_name": "Custom T-Shirt",
"store_id": "store-uuid",
"status": "finalized",
"preview_url": "https://...",
"canvas_data": { ... }
}
}
Configuring Webhooks
Webhook endpoints are configured per-store in your e-commerce platform settings. The customizer will POST to your platform's webhook endpoint when events occur.
Swell Integration
For Swell stores, webhooks are automatically registered when you connect your store:
POST https://trucustom.net/webhooks/swell
ShopStack Integration
For ShopStack stores:
POST https://trucustom.net/webhooks/shopstack
Verifying Webhooks
All webhook requests include a signature header for verification. Verify this signature to ensure the webhook came from TruCustom.
Signature Header
X-TC-Signature: sha256=abc123...
Verification Example (Ruby)
def verify_webhook(payload, signature, secret)
expected = "sha256=" + OpenSSL::HMAC.hexdigest(
"SHA256",
secret,
payload
)
Rack::Utils.secure_compare(expected, signature)
end
# In your controller
def webhook
payload = request.raw_post
signature = request.headers["X-TC-Signature"]
unless verify_webhook(payload, signature, ENV["WEBHOOK_SECRET"])
head :unauthorized
return
end
# Process the webhook
event = JSON.parse(payload)
# ...
end
Verification Example (Node.js)
const crypto = require('crypto');
function verifyWebhook(payload, signature, secret) {
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature)
);
}
// In your Express route
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-pc-signature'];
if (!verifyWebhook(req.body, signature, process.env.WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
const event = JSON.parse(req.body);
// Process the webhook
res.status(200).send('OK');
});
Responding to Webhooks
Your endpoint should respond with a 2xx status code within 30 seconds.
200 OK- Webhook received and processed202 Accepted- Webhook received, will process asynchronously
Retry Policy
If your endpoint fails to respond, we'll retry with exponential backoff:
- 1st retry: 1 minute
- 2nd retry: 5 minutes
- 3rd retry: 30 minutes
- 4th retry: 2 hours
- 5th retry: 12 hours (final)
Best Practices
- Respond quickly - Return a 2xx immediately, process async if needed
- Handle duplicates - Webhooks may be sent more than once
- Verify signatures - Always validate the webhook signature
- Use HTTPS - Only HTTPS endpoints are supported
- Log everything - Keep logs for debugging