| schema_version | 6 |
| name | stripe-webhook-signature-verification |
| description | Use when validating incoming Stripe webhook requests in a Node.js or Next.js backend before processing any payment event. Verifies the `stripe-signature` header against `STRIPE_WEBHOOK_SECRET` using Stripe's HMAC-SHA256 scheme, and rejects replays older than 300 seconds. Do NOT use for general HTTP signature validation (use a generic crypto-signature skill), for processing the webhook payload after signature is confirmed (use payment-provider-router), or for Stripe API calls that are not webhook-driven. |
| version | 0.1.0 |
| type | capability |
| category | engineering |
| domain | engineering/payments |
| scope | portable |
| owner | saas-stripe-postgres-example |
| freshness | 2026-05-18 |
| drift_check | {"last_verified":"2026-05-18","truth_source_hashes":{"stripe-webhook-docs":"sha256:placeholder-record-with-node-scripts-skill-graph-drift-js"}} |
| eval_artifacts | none |
| eval_state | unverified |
| routing_eval | absent |
| stability | experimental |
| license | MIT |
| compatibility | {"runtimes":["node"],"node":">=20","notes":"Stripe SDK >=14; expects raw request body (not parsed JSON) for signature verification."} |
| allowed-tools | Read Grep |
| keywords | ["stripe webhook signature verification","stripe-signature header","webhook hmac verification","STRIPE_WEBHOOK_SECRET","stripe constructEvent","replay attack prevention","webhook security","payment webhook validation","stripe webhook secret"] |
| triggers | ["stripe-webhook-signature-verification"] |
| paths | ["app/api/webhooks/stripe/route.ts","lib/stripe/webhook.ts"] |
| examples | ["how do I verify that a webhook is really from Stripe?","my webhook handler is returning 400 — is the signature verification failing?","set up the Stripe webhook endpoint in a Next.js App Router API route","reject replayed webhook events older than 5 minutes"] |
| anti_examples | ["process the Stripe payment_intent.succeeded event payload","call the Stripe API to create a payment intent","validate a generic HTTP signature that is not from Stripe"] |
| relations | {"boundary":[{"skill":"payment-provider-router","reason":"payment-provider-router decides which downstream handler receives the verified event; this skill verifies authenticity before any routing happens"},{"skill":"nextjs-server-action-validation","reason":"nextjs-server-action-validation validates user-submitted form input via Zod; this skill validates Stripe's HMAC signature — different trust boundary, different mechanism"}],"depends_on":[{"skill":"postgres-rls-pattern","reason":"idempotency key lookups that prevent double-processing run inside the RLS-scoped query layer; this skill activates before those lookups"}],"verify_with":["nextjs-server-action-validation"]} |
| portability | {"readiness":"portable","targets":["skill-md"]} |
| lifecycle | {"stale_after_days":90,"review_cadence":"quarterly"} |