jeremylongshore

juicebox-webhooks-events

@jeremylongshore/juicebox-webhooks-events
jeremylongshore
1,004
123 forks
Updated 1/18/2026
View on GitHub

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".

Installation

$skills install @jeremylongshore/juicebox-webhooks-events
Claude Code
Cursor
Copilot
Codex
Antigravity

Details

Pathplugins/saas-packs/juicebox-pack/skills/juicebox-webhooks-events/SKILL.md
Branchmain
Scoped Name@jeremylongshore/juicebox-webhooks-events

Usage

After installing, this skill will be available to your AI coding assistant.

Verify installation:

skills list

Skill Instructions


name: juicebox-webhooks-events description: | 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". allowed-tools: Read, Write, Edit, Bash(gh:), Bash(curl:) version: 1.0.0 license: MIT author: Jeremy Longshore jeremy@intentsolutions.io

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.

More by jeremylongshore

View all
oauth-callback-handler
1,004

Oauth Callback Handler - Auto-activating skill for API Integration. Triggers on: oauth callback handler, oauth callback handler Part of the API Integration skill category.

rabbitmq-queue-setup
1,004

Rabbitmq Queue Setup - Auto-activating skill for Backend Development. Triggers on: rabbitmq queue setup, rabbitmq queue setup Part of the Backend Development skill category.

model-evaluation-suite
1,004

evaluating-machine-learning-models: This skill allows Claude to evaluate machine learning models using a comprehensive suite of metrics. It should be used when the user requests model performance analysis, validation, or testing. Claude can use this skill to assess model accuracy, precision, recall, F1-score, and other relevant metrics. Trigger this skill when the user mentions "evaluate model", "model performance", "testing metrics", "validation results", or requests a comprehensive "model evaluation".

neural-network-builder
1,004

building-neural-networks: This skill allows Claude to construct and configure neural network architectures using the neural-network-builder plugin. It should be used when the user requests the creation of a new neural network, modification of an existing one, or assistance with defining the layers, parameters, and training process. The skill is triggered by requests involving terms like "build a neural network," "define network architecture," "configure layers," or specific mentions of neural network types (e.g., "CNN," "RNN," "transformer").