Setting Up Webhooks
Get real-time notifications when extractions complete or design changes are detected.
Why Webhooks?
Instead of polling the API for status updates, webhooks push events to your server as they happen. This enables:
- Instant notifications — No delay waiting for poll intervals
- Reduced API calls — Don’t waste requests checking status
- Automation — Trigger workflows automatically
Step 1: Create an Endpoint
Your webhook endpoint must:
- Accept POST requests
- Return 2xx status within 5 seconds
- Verify the HMAC signature
Example (Node.js/Express)
const express = require('express');
const crypto = require('crypto');
const app = express();
const WEBHOOK_SECRET = process.env.STYLEGRAB_WEBHOOK_SECRET;
// Parse raw body for signature verification
app.use('/webhooks/stylegrab', express.raw({ type: '*/*' }));
app.post('/webhooks/stylegrab', (req, res) => {
// Verify signature
const signature = req.headers['x-stylegrab-signature'];
const timestamp = req.headers['x-stylegrab-timestamp'];
const signedPayload = `${timestamp}.${req.body.toString()}`;
const expectedSig = crypto
.createHmac('sha256', WEBHOOK_SECRET)
.update(signedPayload)
.digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expectedSig))) {
return res.status(401).send('Invalid signature');
}
// Process the event
const event = JSON.parse(req.body);
console.log(`Received: ${event.event}`);
switch (event.event) {
case 'extraction.completed':
handleExtractionComplete(event.data);
break;
case 'diff.detected':
handleDiffDetected(event.data);
break;
}
res.status(200).send('OK');
});
function handleExtractionComplete(data) {
console.log(`Extraction ${data.extraction_id} finished`);
// Send to Slack, update database, etc.
}
function handleDiffDetected(data) {
console.log(`${data.changes.total_changes} changes detected!`);
// Alert the team, block deployment, etc.
}
app.listen(3000);
Step 2: Register the Webhook
curl -X POST https://api.stylegrab.dev/api/webhooks \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://yoursite.com/webhooks/stylegrab",
"events": ["extraction.completed", "diff.detected", "snapshot.created"]
}'
Response:
{
"id": "wh_abc123",
"url": "https://yoursite.com/webhooks/stylegrab",
"events": ["extraction.completed", "diff.detected", "snapshot.created"],
"secret": "whsec_a1b2c3d4e5f6...",
"active": true
}
⚠️ Save the
secret! Store it asSTYLEGRAB_WEBHOOK_SECRETin your environment. You won’t see it again.
Step 3: Test the Webhook
Run an extraction and watch for the webhook:
# Trigger an extraction
curl -X POST https://api.stylegrab.dev/api/extractions \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"url": "https://example.com"}'
Your endpoint should receive:
{
"event": "extraction.completed",
"timestamp": "2024-01-15T10:30:02Z",
"data": {
"extraction_id": "ext_abc123",
"url": "https://example.com",
"snapshot_id": "snap_xyz789"
}
}
Integrations
Slack Notifications
async function handleDiffDetected(data) {
await fetch(process.env.SLACK_WEBHOOK_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
text: `🎨 Design drift detected on ${data.url}`,
blocks: [
{
type: 'section',
text: {
type: 'mrkdwn',
text: `*${data.changes.total_changes} changes* detected between snapshots`
}
},
{
type: 'section',
fields: [
{ type: 'mrkdwn', text: `*Colors:* ${data.changes.colors_changed}` },
{ type: 'mrkdwn', text: `*Typography:* ${data.changes.typography_changed}` }
]
}
]
})
});
}
GitHub Actions
Trigger a workflow when design changes are detected:
# .github/workflows/design-check.yml
on:
repository_dispatch:
types: [design_drift]
jobs:
alert:
runs-on: ubuntu-latest
steps:
- name: Create Issue
uses: actions/github-script@v6
with:
script: |
github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: 'Design drift detected',
body: 'StyleGrab detected changes. Review the diff at...'
})
Troubleshooting
Webhook not receiving events
- Check your endpoint is publicly accessible
- Verify HTTPS is working (webhooks require HTTPS)
- Check the webhook is
activein the API
Signature verification failing
- Ensure you’re using the raw request body (not parsed JSON)
- Check the secret matches what was returned when creating the webhook
- Verify timing — reject requests with timestamps > 5 minutes old
Webhook marked as failed
After 3 failed delivery attempts, the webhook is marked failed. Fix your endpoint and the next event will retry delivery.