agentsclimarketplace

Persona webhooks events

Skill jeremylongshore/claude-code-plugins-plus-skills/plugins/saas-packs/persona-pack/skills/persona-webhooks-events

'Handle Persona webhook events for inquiry and verification status changes.From its SKILL.md

Install
npx -y skills add jeremylongshore/claude-code-plugins-plus-skills --skill persona-webhooks-events

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

What its file declares

Copied from the file, not written here

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, 811 tokens by cl100k_base, 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-auth setup
  • 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

IssueCauseSolution
Invalid signatureWrong webhook secretRe-copy secret from Dashboard
Missing eventsEvents not selectedCheck webhook configuration
Duplicate processingRetry deliveryUse event ID deduplication

Resources

Next Steps

For common errors, see persona-common-errors.

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Gives 0 of the 12 instructions most ux research skills give in 811 tokens

Counted across 242 of the 261 authors here whose files we hold, read 2026-09-06

  • Fall back to prompt text when image generation failsin 16 of 242, across 7 files
  • Offer three name candidates with reasonsin 16 of 242, across 7 files
  • Comment on each result before asking the userin 16 of 242, across 7 files
  • Check for an approved image-generation skill before auto-generatingin 15 of 242, across 6 files
  • Degrade gracefully instead of interrupting on errorsin 14 of 242, across 5 files
  • Guide the user to write SOUL.md and IDENTITY.mdin 13 of 242, across 6 files
  • Derive two to four boundary rules in character voicein 11 of 242, across 4 files
  • Report SXO score separately from SEO Health Scorein 11 of 242, across 6 files
  • Run gacha.py for random drawsin 11 of 242, across 4 files
  • Score the page across seven gap dimensionsin 11 of 242, across 6 files
  • Derive three to five user stories citing SERP signalsin 11 of 242, across 6 files
  • Confirm DataForSEO cost estimates before calling its APIsin 11 of 242, across 6 files

Said here and by no other author read

  • Configure the webhook in the Persona Dashboard
  • Subscribe to inquiry and verification lifecycle events
  • Copy the webhook secret from the Dashboard
  • Verify the HMAC-SHA256 signature of each request
  • Return 401 for invalid signatures
  • Read the raw request body before parsing

Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.