askill
juicebox-webhooks-events

juicebox-webhooks-eventsSafety 95Repository

Implement Juicebox webhook handling. Use when setting up event notifications, processing webhooks, or integrating real-time updates from Juicebox. Trigger with phrases like "juicebox webhooks", "juicebox events", "juicebox notifications", "juicebox real-time".

0 stars
1.2k downloads
Updated 2/3/2026

Package Files

Loading files...
SKILL.md

Juicebox Webhooks & Events

Overview

Implement webhook handlers for real-time Juicebox events and notifications.

Prerequisites

  • Juicebox account with webhooks enabled
  • HTTPS endpoint for webhook delivery
  • Request signature verification capability

Instructions

Step 1: Register Webhook Endpoint

// First, configure in Juicebox dashboard or via API
import { JuiceboxClient } from '@juicebox/sdk';

const client = new JuiceboxClient({
  apiKey: process.env.JUICEBOX_API_KEY!
});

await client.webhooks.create({
  url: 'https://your-app.com/webhooks/juicebox',
  events: [
    'search.completed',
    'profile.enriched',
    'export.ready',
    'quota.warning'
  ],
  secret: process.env.JUICEBOX_WEBHOOK_SECRET
});

Step 2: Implement Webhook Handler

// routes/webhooks.ts
import { Router } from 'express';
import crypto from 'crypto';

const router = Router();

// Verify webhook signature
function verifySignature(payload: string, signature: string, secret: string): boolean {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(`sha256=${expected}`)
  );
}

router.post('/webhooks/juicebox', express.raw({ type: 'application/json' }), async (req, res) => {
  const signature = req.headers['x-juicebox-signature'] as string;
  const payload = req.body.toString();

  // Verify signature
  if (!verifySignature(payload, signature, process.env.JUICEBOX_WEBHOOK_SECRET!)) {
    return res.status(401).json({ error: 'Invalid signature' });
  }

  const event = JSON.parse(payload);

  // Acknowledge receipt immediately
  res.status(200).json({ received: true });

  // Process event asynchronously
  await processWebhookEvent(event);
});

export default router;

Step 3: Process Different Event Types

// services/webhook-processor.ts
interface WebhookEvent {
  id: string;
  type: string;
  timestamp: string;
  data: any;
}

export async function processWebhookEvent(event: WebhookEvent): Promise<void> {
  console.log(`Processing event: ${event.type} (${event.id})`);

  switch (event.type) {
    case 'search.completed':
      await handleSearchCompleted(event.data);
      break;

    case 'profile.enriched':
      await handleProfileEnriched(event.data);
      break;

    case 'export.ready':
      await handleExportReady(event.data);
      break;

    case 'quota.warning':
      await handleQuotaWarning(event.data);
      break;

    default:
      console.warn(`Unknown event type: ${event.type}`);
  }
}

async function handleSearchCompleted(data: { searchId: string; resultCount: number }) {
  // Notify user that search is complete
  await notificationService.send({
    type: 'search_complete',
    searchId: data.searchId,
    message: `Search completed with ${data.resultCount} results`
  });
}

async function handleProfileEnriched(data: { profileId: string; fields: string[] }) {
  // Update local cache with enriched data
  await cacheService.invalidate(`profile:${data.profileId}`);
  await db.profiles.update({
    where: { id: data.profileId },
    data: { enrichedAt: new Date() }
  });
}

async function handleExportReady(data: { exportId: string; downloadUrl: string }) {
  // Notify user and store download URL
  await notificationService.send({
    type: 'export_ready',
    exportId: data.exportId,
    downloadUrl: data.downloadUrl
  });
}

async function handleQuotaWarning(data: { usage: number; limit: number }) {
  // Alert team about quota usage
  const percentage = (data.usage / data.limit) * 100;
  if (percentage > 80) {
    await alertService.send({
      severity: 'warning',
      message: `Juicebox quota at ${percentage.toFixed(1)}%`
    });
  }
}

Step 4: Implement Retry Logic

// lib/webhook-queue.ts
import { Queue } from 'bullmq';

const webhookQueue = new Queue('juicebox-webhooks', {
  connection: { host: 'localhost', port: 6379 }
});

export async function queueWebhookProcessing(event: WebhookEvent): Promise<void> {
  await webhookQueue.add('process', event, {
    attempts: 3,
    backoff: {
      type: 'exponential',
      delay: 1000
    }
  });
}

// Worker
import { Worker } from 'bullmq';

new Worker('juicebox-webhooks', async (job) => {
  await processWebhookEvent(job.data);
}, {
  connection: { host: 'localhost', port: 6379 }
});

Webhook Events Reference

EventDescriptionPayload
search.completedAsync search finishedsearchId, resultCount
profile.enrichedProfile data enrichedprofileId, fields
export.readyBulk export readyexportId, downloadUrl
quota.warningApproaching quota limitusage, limit
key.rotatedAPI key rotatednewKeyPrefix

Output

  • Webhook endpoint handler
  • Signature verification
  • Event type processors
  • Retry queue with backoff

Error Handling

IssueCauseSolution
Invalid signatureWrong secretVerify webhook secret
Duplicate eventsNetwork retryImplement idempotency
Processing timeoutSlow handlerUse async queue

Resources

Next Steps

After webhooks, see juicebox-performance-tuning for optimization.

Install

Download ZIP
Requires askill CLI v1.0+

AI Quality Score

95/100Analyzed 2/12/2026

A high-quality, comprehensive guide for implementing Juicebox webhooks. It covers registration, secure signature verification, event processing, and asynchronous retry logic with clear, actionable code examples.

95
100
90
95
95

Metadata

Licenseunknown
Version1.0.0
Updated2/3/2026
PublisherHelixDevelopment

Tags

apisecurity