Skip to content
Back to blog
Provider GuidesPayPalAdyenDocuSignSignature Verification

New: PayPal, Adyen, DocuSign, and Plaid Webhooks

webhooks.cc now supports 32 providers. This release adds PayPal's RSA certificate verification, Adyen's body-embedded HMAC, DocuSign Connect, and Plaid.

Jun 11, 20266 min read

webhooks.cc now supports 32 webhook providers. This release adds four: PayPal, Adyen, DocuSign, and Plaid — and with PayPal comes the catalog's first asymmetric signature scheme.

Until now, every provider in the catalog signed with a shared secret: you and the provider both hold the key, and verification recomputes an HMAC. PayPal works differently. It signs with a private key you never see and publishes the matching certificate. Verification means fetching that certificate and checking an RSA signature — and webhooks.cc now does that for you.

What support means

Every provider in the catalog gets three things:

  • Test templates. Generate a realistic payload and send it to any endpoint. You don't need a real provider account.
  • Auto-detection. Captured requests show the provider and event in the request list.
  • Signature verification. Check a captured request in the dashboard, from the SDK, or automatically on every request.

The four new providers

ProviderSignature locationScheme
PayPalpaypal-transmission-sig + paypal-cert-urlRSA-SHA256 over id|time|webhookId|crc32(body)
Adyen(body field) additionalData.hmacSignatureHMAC-SHA256 (base64) over eight notification fields
DocuSignx-docusign-signature-1HMAC-SHA256 (base64) over the raw body
Plaidplaid-verificationJWT (ES256) — detection and templates only, see below

That brings the catalog to 32 providers: all 32 generate templates and auto-detect, and 30 verify signatures.

PayPal: certificate-based verification

PayPal signs transmissionId|transmissionTime|webhookId|crc32(rawBody) with its private key and points to the certificate in the paypal-cert-url header. webhooks.cc fetches the certificate — only from PayPal's own hosts, over HTTPS — extracts the RSA public key, and checks the signature.

Your credential is the Webhook ID from your PayPal app settings, not a secret. The endpoint settings dialog and the Signature tab both label it that way.

import { verifySignature } from "@webhooks-cc/sdk";
 
const result = await verifySignature(request, {
  provider: "paypal",
  secret: process.env.PAYPAL_WEBHOOK_ID!,
});
 
console.log(result.valid);

If the certificate can't be downloaded, verifySignature throws instead of returning false — a network failure is not a verdict on the signature. Automatic verification on the receiver records the same distinction: a failed fetch shows as skipped with the reason, never as a false "verified" or "invalid".

Set PayPal as the signing provider on your endpoint and let the receiver verify automatically. Browsers block cross-origin downloads of PayPal certificates, so the dashboard's manual paste-a-secret check can't fetch the certificate — the automatic server-side check is the right tool here.

Adyen: the signature lives in the body

Adyen sends no signature header. Each notification item carries its own HMAC at notificationItems[].NotificationRequestItem.additionalData.hmacSignature, computed over eight colon-joined fields (PSP reference, merchant account, amount, event code, and so on) with the hex HMAC key from your Customer Area.

webhooks.cc verifies every item in the batch. A batch only counts as valid when each item carries its own correct signature — one genuine item can't vouch for a forged or unsigned sibling.

const result = await verifySignature(request, {
  provider: "adyen",
  secret: process.env.ADYEN_HMAC_KEY!, // hex key from the Customer Area
});

DocuSign and Plaid

DocuSign Connect is the simple one: HMAC-SHA256 over the raw body, base64-encoded in x-docusign-signature-1. Configure the same HMAC key you set in your Connect configuration and every envelope event verifies automatically.

Plaid gets templates and detection, but not verification yet. Plaid signs with a JWT in the plaid-verification header, and checking it requires fetching Plaid's verification key with your Plaid API credentials — credentials webhooks.cc shouldn't hold. Plaid templates send without a secret:

await client.endpoints.sendTemplate(endpoint.slug, {
  provider: "plaid",
  template: "TRANSACTIONS",
});

Send a signed test webhook

Same flow as every other provider — pick a template, pass the credential, and the payload arrives signed:

import { WebhooksCC } from "@webhooks-cc/sdk";
 
const client = new WebhooksCC({ apiKey: process.env.WHK_API_KEY! });
const endpoint = await client.endpoints.create({ expiresIn: "1h" });
 
await client.endpoints.sendTemplate(endpoint.slug, {
  provider: "adyen",
  template: "AUTHORISATION",
  secret: process.env.ADYEN_HMAC_KEY!,
});

The dashboard's Send button and the MCP send_webhook tool offer the same templates.

A few quirks worth knowing

  • PayPal templates carry a placeholder signature. Template generation can't hold PayPal's private key, so generated PayPal payloads are shaped for detection and capture testing, not for passing verification. Real PayPal webhooks verify correctly.
  • Adyen's key is hex. Paste the HMAC key exactly as the Customer Area shows it — the verifier decodes the hex before computing the HMAC.
  • Plaid templates need no secret — the only provider besides SendGrid and Discord where you can omit it.

Where to go next

Provider templates

Every provider, its templates, and the header each one signs.

Verify webhook signatures

Verify captures in the dashboard or in code, provider by provider.

FAQ