Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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 as STYLEGRAB_WEBHOOK_SECRET in 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

  1. Check your endpoint is publicly accessible
  2. Verify HTTPS is working (webhooks require HTTPS)
  3. Check the webhook is active in the API

Signature verification failing

  1. Ensure you’re using the raw request body (not parsed JSON)
  2. Check the secret matches what was returned when creating the webhook
  3. 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.

Next Steps