Persona webhooks events
Skill jeremylongshore/claude-code-plugins-plus-skills/skills/.curated/persona-webhooks-events
425 plugins, 2,810 skills, 200 agents for Claude Code. Open-source marketplace at tonsofskills.com with the ccpi CLI package manager.
npx -y skills add jeremylongshore/claude-code-plugins-plus-skills --skill persona-webhooks-eventsAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
What its author says it does
Copied from the file, not written here
'Handle Persona webhook events for inquiry and verification status changes.
The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
4.1 KB, as published. Nobody here has run it
persona webhooks events | sed 's/\b(.)/\u\1/g'
Overview
HMAC signature verification, inquiry.completed/approved/declined events, idempotent processing.
Prerequisites
- Completed
persona-install-authsetup - Valid Persona API key (sandbox or production)
Instructions
Step 1: Configure Webhook in Dashboard
1. Dashboard > Settings > Webhooks > Add Webhook
2. URL: https://your-app.com/webhooks/persona
3. Events: inquiry.completed, inquiry.approved, inquiry.declined,
verification.passed, verification.failed
4. Copy the webhook secret for signature verification
Step 2: Webhook Endpoint with HMAC Verification
import express from 'express';
import crypto from 'crypto';
const app = express();
app.post('/webhooks/persona',
express.raw({ type: 'application/json' }),
async (req, res) => {
const signature = req.headers['persona-signature'] as string;
const secret = process.env.PERSONA_WEBHOOK_SECRET!;
// Verify HMAC-SHA256 signature
const expectedSig = crypto
.createHmac('sha256', secret)
.update(req.body)
.digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(signature || ''), Buffer.from(expectedSig))) {
return res.status(401).json({ error: 'Invalid signature' });
}
const event = JSON.parse(req.body.toString());
await handlePersonaEvent(event);
res.status(200).json({ received: true });
}
);
Step 3: Event Handlers
async function handlePersonaEvent(event: any) {
const { type, data } = event;
switch (type) {
case 'inquiry.completed':
const inquiryId = data.attributes.payload.data.id;
const referenceId = data.attributes.payload.data.attributes['reference-id'];
console.log(`Inquiry completed: ${inquiryId} for user ${referenceId}`);
// Update user KYC status in your database
await updateUserKycStatus(referenceId, 'completed');
break;
case 'inquiry.approved':
await updateUserKycStatus(data.attributes.payload.data.attributes['reference-id'], 'approved');
break;
case 'inquiry.declined':
await updateUserKycStatus(data.attributes.payload.data.attributes['reference-id'], 'declined');
break;
case 'verification.passed':
console.log(`Verification passed: ${data.attributes.payload.data.id}`);
break;
case 'verification.failed':
console.log(`Verification failed: ${data.attributes.payload.data.id}`);
break;
default:
console.log(`Unhandled event: ${type}`);
}
}
Step 4: Idempotent Processing
const processedEvents = new Set<string>();
async function idempotentHandle(event: any) {
const eventId = event.data.id;
if (processedEvents.has(eventId)) {
console.log(`Skipping duplicate: ${eventId}`);
return;
}
await handlePersonaEvent(event);
processedEvents.add(eventId);
}
Output
- Webhook endpoint with HMAC signature verification
- Event handlers for inquiry and verification lifecycle
- Idempotent processing preventing duplicates
Error Handling
| Issue | Cause | Solution |
|---|---|---|
| Invalid signature | Wrong webhook secret | Re-copy secret from Dashboard |
| Missing events | Events not selected | Check webhook configuration |
| Duplicate processing | Retry delivery | Use event ID deduplication |
Resources
Next Steps
For common errors, see persona-common-errors.