Skip to content

PayPal webhook

Denied payments, refunds, disputes, cancelled subscriptions and failed subscription payments from PayPal, with typed amounts.

Setup

  1. In the PayPal developer dashboard (developer.paypal.com) open Apps & Credentials, pick Live or Sandbox, and create an app or open an existing one. Copy its Client ID and Secret.
  2. In the same app scroll to Webhooks and choose Add Webhook. PayPal asks for an https address: enter any placeholder for now. Subscribe it to Payment capture denied, Payment capture refunded, Dispute created, Billing subscription cancelled and Billing subscription payment failed (add Payment capture completed only for sales alerts), save, and copy the Webhook ID shown next to it.
  3. In PingLoom open Webhooks, choose New webhook source, pick PayPal, choose the same environment, paste the Client ID, the Secret and the Webhook ID, and create it. Copy the endpoint URL.
  4. Back in PayPal edit the webhook and replace the placeholder with the PingLoom endpoint URL.
  5. Send a test from the PayPal webhook simulator or make a Sandbox payment. The request appears under Recent requests on the PingLoom source page. PayPal's simulator sample events usually fail verification, so a real Sandbox event is the better test.

Verification

PayPal signs each webhook with a certificate (PAYPAL-TRANSMISSION-SIG and four more PAYPAL-* headers), not a shared secret, so it cannot be checked offline. PingLoom asks PayPal's own verify-webhook-signature API, using your PayPal app's Client ID and Secret to get an access token, and accepts the event only when PayPal answers SUCCESS. PingLoom only contacts api-m.paypal.com (Live) or api-m.sandbox.paypal.com (Sandbox), never any address taken from the request, and it never downloads the certificate itself. The PayPal event id drops repeats.

Events

You choose which events become alerts when you create the source, and you can change it later on the source page.

EventPriorityOn by default
Payment deniedhighYes
Dispute openedhighYes
Subscription payment failedhighYes
Payment refundednormalYes
Subscription cancellednormalYes
Sales (payment captured)lowNo

Every money alert carries data.amount (a whole number in the currency's smallest unit, so 1099 is 10.99 USD), data.currency, data.event_type and the PayPal object id. Payer names, emails and addresses are never copied.

The Client ID, Secret and Webhook ID are stored encrypted and shown masked. If PayPal refuses them the source page says PayPal credentials rejected, and PingLoom answers PayPal with an error so PayPal retries later. If PayPal itself cannot be reached PingLoom also answers with an error (503) and creates no alert; the reason is on the Recent requests list.

If you change the app secret or recreate the webhook in PayPal, use Rotate secret on the PingLoom source to enter the new values.