Agent skill
Prive Webhooks Skill
Receive and verify Prive webhooks (Prive is now Recurly Commerce, Shopify subscriptions). Use when setting up Prive webhook handlers, debugging x-prive-hmac-sha256 signature verification, or handling subscriptions/created, billingAttempts/failed, orders/created, and paymentMethod/updated topics.
Install this skill
npx skills add hookdeck/webhook-skills --skill prive-webhooks
Prive is a subscription app for Shopify merchants, now part of Recurly Commerce. The docs, API and headers still use the Prive name, so this skill does too.
When to Use This Skill
- How do I receive Prive webhooks?
- How do I verify the
x-prive-hmac-sha256signature on a Prive webhook? - How do I handle
subscriptions/createdorbillingAttempts/failedwebhooks? - Why is my Prive webhook signature verification failing?
- How do I route Prive topics to separate handlers?
Verification (core)
Prive signs the raw request body with HMAC-SHA256, keyed with the secret token Prive gives the merchant, and sends the digest in x-prive-hmac-sha256 as a bare base64 string (Shopify-style, no prefix). Prive's Node sample passes 'hex' as a third argument to update(), which Node ignores, so the digest is base64, not hex. There is no timestamp. Compare in constant time, without decoding the header.
Node:
const crypto = require('crypto');
function verifyPriveSignature(rawBody, header, secret) {
if (!header || !secret) return false;
const expected = crypto.createHmac('sha256', secret).update(rawBody).digest('base64');
const a = Buffer.from(header, 'utf8');
const b = Buffer.from(expected, 'utf8');
return a.length === b.length && crypto.timingSafeEqual(a, b);
}
Python:
import base64, hashlib, hmac
def verify_prive_signature(raw_body: bytes, header: str | None, secret: str) -> bool:
if not header or not secret:
return False
expected = base64.b64encode(
hmac.new(secret.encode(), raw_body, hashlib.sha256).digest()
).decode()
# Encode both sides: compare_digest raises TypeError on non-ASCII str
return hmac.compare_digest(header.encode("utf-8"), expected.encode("utf-8"))
Read the raw body before any JSON parsing. In Express use express.raw({ type: '*/*' }) so any content type verifies.
For complete handlers with tests, see examples/express/, examples/nextjs/, examples/fastapi/.
Webhook Topics
Each Prive webhook subscribes to one topic, chosen when the webhook is created (topic field of the create-webhook endpoint).
| Topic | Description |
|---|---|
subscriptions/created | A subscription was created |
subscriptions/line_ | A line was removed from a subscription |
subscriptions/status/updated | A subscription's status changed |
orders/created | A subscription order was created |
billingAttempts/created | A billing attempt was created |
billingAttempts/success | A billing attempt succeeded |
billingAttempts/failed | A billing attempt failed |
paymentMethod/updated | A payment method was updated |
subscriptionActivities/created | A subscription activity was created |
subscription/customAttributes/updated | A subscription's custom attributes were updated |
No topic header or body field is documented. Create one webhook per topic, each with its own endpoint path (for example /webhooks/prive/billing-attempts-failed), or one Hookdeck connection per topic, and dispatch on the path. The examples map those paths to topics.
Setup
- Prive (now Recurly Commerce) provides the secret token. Ask Prive support for it if you don't have it.
- Create a webhook per topic with the Prive create-webhook endpoint, pointing at your endpoint URL.
- With Hookdeck, create a Prive source and give it the same secret token as its signing secret, then add one connection per topic. See references/setup.md.
Environment Variables
PRIVE_WEBHOOK_SECRET=your_prive_secret_token # Provided by Prive; ask Prive support if you don't have it
Local Development
# Start tunnel (no account needed)
npx hookdeck-cli listen 3000 prive --path /webhooks/prive
Reference Materials
- references/overview.md - Prive webhook concepts and topics
- references/setup.md - Getting the secret token and creating webhooks
- references/verification.md - Signature verification details and gotchas