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
Details
Usage
After installing, this skill will be available to your AI coding assistant.
Verify installation:
skills listSkill 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
| Event | Description | Payload |
|---|---|---|
search.completed | Async search finished | searchId, resultCount |
profile.enriched | Profile data enriched | profileId, fields |
export.ready | Bulk export ready | exportId, downloadUrl |
quota.warning | Approaching quota limit | usage, limit |
key.rotated | API key rotated | newKeyPrefix |
Output
- Webhook endpoint handler
- Signature verification
- Event type processors
- Retry queue with backoff
Error Handling
| Issue | Cause | Solution |
|---|---|---|
| Invalid signature | Wrong secret | Verify webhook secret |
| Duplicate events | Network retry | Implement idempotency |
| Processing timeout | Slow handler | Use async queue |
Resources
Next Steps
After webhooks, see juicebox-performance-tuning for optimization.
More by jeremylongshore
View allOauth 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 - Auto-activating skill for Backend Development. Triggers on: rabbitmq queue setup, rabbitmq queue setup Part of the Backend Development skill category.
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".
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").
