Back to sensacat

Home  /  Integration guides

· SensaCat Team

How to Monitor PayPal Webhooks

PayPal verification needs a network call back to PayPal on every event, which makes your handler depend on PayPal being up to accept PayPal's own webhook.

Monitoring PayPal webhooks has one wrinkle no other major payment provider has: verifying a webhook requires calling PayPal's API. That turns signature verification from a local computation into a network dependency, and it is the source of most PayPal-specific failures.

How PayPal verification actually works

Stripe and Shopify sign with a symmetric HMAC you can verify offline in microseconds. PayPal signs asymmetrically, typically SHA256withRSA, and the documented path is to POST the details to PayPal's verify-webhook-signature endpoint and read the result.

Note webhook_id. It is the ID of your webhook registration, not anything from the request, and using the wrong one is the most common cause of verification failing on a perfectly valid event.

You also need an OAuth token, which means a second API call unless you cache it. Between the token and the verification, an unoptimised handler makes two outbound calls to PayPal before it has decided whether to trust the request.

What this means for your failure modes

If PayPal's API is degraded, verification fails, you reject the event, and PayPal retries it later against the same degraded API. Your integration is broken by the provider it is integrating with, in a way that looks like your fault in your own logs.

Sandbox and live use different base URLs and different credentials. Pointing a live handler at api-m.sandbox.paypal.com returns verification failures for every real event, which is a deeply confusing morning.

Behaviour Stripe PayPal
Signature type HMAC-SHA256, symmetric SHA256withRSA, asymmetric
Verification Local, offline API call to PayPal
Extra dependency None PayPal API availability, OAuth token
Typical added latency Under a millisecond Two network round trips unless cached
Fails when provider is down No Yes

Cache the OAuth token

PayPal access tokens are valid for hours. Requesting a new one per webhook doubles your latency and burns rate limit for no reason.

Monitoring: queue first, verify in the worker

Because verification is slow and externally dependent, the pragmatic structure is to accept and persist the raw event immediately, return 200, then verify and process in a worker. You store an unverified event briefly, which is acceptable as long as you do nothing with it until verification passes.

Ping the monitor from the worker after processing, and send an explicit failure when verification returns anything other than SUCCESS. A run of verification failures almost always means a configuration problem rather than an attack, and you want to know within minutes.

Also check the subscription still exists

Webhook registrations can be removed or edited in the developer dashboard, and an event type can be dropped from a subscription without the subscription itself disappearing. Both produce silence rather than errors.

List your webhooks and their event types on a schedule and compare against what you expect, the same discipline described in monitoring Shopify webhooks.

See webhook monitoring for the general approach and monitoring Stripe webhooks for the symmetric-signature comparison.