Skip to main content

Webhook contract

Static lint for webhook handlers (Stripe, Paddle, GitHub, Clerk, etc.).

What it catches

  • Missing signature verification (constructEvent, verifyWebhook, signature headers)
  • Missing idempotency (event.id, processed_events, ON CONFLICT)
  • Missing raw body reads when signature verification requires them

Example config

version: 1
contracts:
- type: webhook
handler_paths: [app/api/**/webhook/**, src/**/webhook/**]
require_idempotency: true
require_raw_body: true
severity: high

CLI

npx prodverdict check webhook --config prodverdict.yml

Runs on every PR. No billing secrets required.