Receive and verify PayPal webhooks. Use when setting up PayPal webhook handlers, debugging certificate-based signature verification, or handling payment events like PAYMENT.CAPTURE.COMPLETED, PAYMENT.SALE.COMPLETED, BILLING.SUBSCRIPTION.CREATED, or CHECKOUT.ORDER.APPROVED.
Receive and verify PayPal webhooks. Use when setting up PayPal webhook handlers, debugging certificate-based signature verification, or handling payment events like PAYMENT.CAPTURE.COMPLETED, PAYMENT.SALE.COMPLETED, BILLING.SUBSCRIPTION.CREATED, or CHECKOUT.ORDER.APPROVED.
Debugging PayPal signature verification failures (RSA-SHA256 with cert)
Understanding PayPal event types like PAYMENT.CAPTURE.COMPLETED
Handling payment, subscription, refund, or checkout events
Choosing between PayPal's postback verify API and offline cert verification
How PayPal Webhooks Differ From Most Providers
PayPal does not use HMAC with a shared secret. Instead, each webhook is
signed with PayPal's private key, and you verify it with the matching public
certificate delivered per request via the paypal-cert-url header. The
algorithm is RSA-SHA256 ("SHA256withRSA").
Two valid verification paths:
Postback (no crypto needed) — POST the captured headers, your
webhook_id, and the raw webhook_event body to PayPal's
endpoint. Requires an OAuth
access token. PayPal returns .
/v1/notifications/verify-webhook-signature
{ "verification_status": "SUCCESS" }
Offline self-verify (recommended for low-latency / no extra OAuth call) —
Fetch the cert from paypal-cert-url (cache it; validate the host ends with
.paypal.com), build the message
transmissionId|transmissionTime|webhookId|crc32(rawBody), and verify the
base64 signature against the cert's public key using RSA-SHA256.
The examples in this skill use the offline approach because it is testable
without OAuth and avoids an extra API call per webhook. The postback path is
documented in references/verification.md.
Essential Code (USE THIS)
Required Request Headers
Header
Purpose
paypal-transmission-id
Unique webhook transmission ID
paypal-transmission-time
ISO 8601 timestamp of transmission
paypal-transmission-sig
Base64-encoded RSA-SHA256 signature
paypal-cert-url
URL of the public cert (must be a *.paypal.com host)
crc32(rawBody) is the standard CRC-32 of the raw HTTP body as an unsigned
decimal integer. webhookId is the ID of the webhook registered in your
PayPal app (env var PAYPAL_WEBHOOK_ID).
PAYPAL_WEBHOOK_ID=4JH86294D6297351H # From PayPal app webhook settings
PAYPAL_CLIENT_ID=AYS... # Only needed for the postback verify path
PAYPAL_CLIENT_SECRET=EC... # Only needed for the postback verify path
PAYPAL_ENV=sandbox # sandbox | live
We recommend installing the webhook-handler-patterns skill alongside this one for handler sequence, idempotency, error handling, and retry logic. Key references (open on GitHub):
Handler sequence — Verify first, parse second, handle idempotently third
hookdeck-event-gateway - Webhook infrastructure that replaces your queue — guaranteed delivery, automatic retries, replay, rate limiting, and observability for your webhook handlers