Gareth Wilson Gareth Wilson

Guide to Adyen Webhooks: Features and Best Practices

Published · Updated


Adyen has become one of the most widely adopted enterprise payment platforms, processing transactions for companies including Microsoft, Uber, eBay, and Spotify. At the heart of any successful Adyen integration lies webhooks, which is the mechanism that keeps your systems synchronized with payment events in real-time.

This guide covers everything you need to know about Adyen webhooks: their features, how to configure them, best practices for production deployments, and the common pain points developers face along with solutions to address them. You may also find our articles on how to secure and verify Adyen webhooks and how to solve Adyen webhook timeout errors helpful.

What are Adyen webhooks?

Adyen webhooks are HTTP POST calls that deliver event notifications to endpoints you define whenever payment events occur. When a payment is authorized, captured, refunded, or experiences a chargeback, Adyen sends a JSON payload containing the event details to your server.

Webhooks are essential because many payment flows are asynchronous. When a customer pays with iDEAL, Bancontact, or other redirect-based methods, confirmation may take seconds, minutes, or even days. Webhooks ensure you receive the final outcome immediately when it becomes available, eliminating the need to poll Adyen's API continuously.

Webhooks in Adyen exist in two primary contexts:

  • Standard Webhooks (Payments) - The primary webhook integration for payment lifecycle events
  • Platform Webhooks - Webhooks for Adyen for Platforms integrations (account holders, balance accounts, transfers)

This guide focuses primarily on Standard webhooks for payment integrations, as they're the most commonly used webhook type.

Adyen webhook features

FeatureDetails
Webhook configurationAdyen Customer Area, Management API, or provisioning
Hashing algorithmSHA256 HMAC
Timeout10-second timeout
Retry logic3 immediate retries, then queued for up to 30 days
Event filteringEnable/disable non-default event codes; default codes always enabled
Manual retryAvailable via Customer Area
Browsable logLimited visibility; retry queue accessible in Customer Area
Delivery protocolHTTPS required (TLS 1.2/1.3); HTTP allowed in test only
Payload formatJSON (recommended), SOAP, HTTP POST
AuthenticationHMAC (recommended), OAuth 2.0 (Standard only), Basic Auth
Port restrictionsLive: 443, 8443, 8843 only; Test: also allows 80, 8080, 8888

Supported event codes

Adyen webhooks notify you of the following payment event types:

Event CodeDescription
AUTHORISATIONPayment was authorized (or failed)
CAPTUREFunds were captured
CAPTURE_FAILEDCapture was rejected by issuer (non-default)
CANCELLATIONPayment was cancelled
REFUNDRefund was processed
REFUND_FAILEDRefund was rejected (non-default)
REFUNDED_REVERSEDRefund funds returned to merchant
CHARGEBACKCustomer disputed the payment
REPORT_AVAILABLESettlement report is ready

Default event codes are enabled automatically. Non-default codes (like CAPTURE_FAILED or REFUND_FAILED) must be manually enabled in your Customer Area under Developers > Webhooks > Edit webhook > Events.

Webhook payload structure

When Adyen sends a webhook notification, it delivers a JSON payload with the following structure:

{
  "live": "false",
  "notificationItems": [
    {
      "NotificationRequestItem": {
        "eventCode": "AUTHORISATION",
        "success": "true",
        "eventDate": "2025-01-15T10:30:00+00:00",
        "merchantAccountCode": "YourMerchantAccount",
        "pspReference": "8825408195409505",
        "merchantReference": "ORDER-12345",
        "amount": {
          "currency": "EUR",
          "value": 1000
        },
        "paymentMethod": "visa",
        "operations": ["CANCEL", "CAPTURE", "REFUND"],
        "additionalData": {
          "hmacSignature": "coqCmt/IZ4E3CzPvMY8zTjQVL5..."
        }
      }
    }
  ]
}

Key payload fields

FieldDescription
liveWhether the event occurred in test or live environment
notificationItemsArray containing webhook events (typically one per delivery)
eventCodeType of event (AUTHORISATION, CAPTURE, REFUND, etc.)
successWhether the event succeeded ("true"/"false" as strings)
eventDateTimestamp when the event occurred
pspReferenceAdyen's unique identifier for the payment
merchantReferenceYour order ID from the original payment request
amountPayment amount with currency and value (in minor units)
paymentMethodPayment method used (visa, ideal, paypal, etc.)
operationsAvailable follow-up actions for this payment
additionalData.hmacSignatureHMAC signature for verification

Security with HMAC signatures

Adyen supports HMAC-SHA256 signatures to verify webhook authenticity. When enabled, Adyen signs the payload with a shared secret, and the signature is included in the additionalData.hmacSignature field.

Each HMAC key is linked to one webhook endpoint. If you have multiple endpoints, generate a separate key for each. You also need to generate new keys when switching from test to live environments.

When generating new HMAC keys, continue accepting webhooks signed with your previous key temporarily, as propagation through Adyen's infrastructure takes time.

Authentication options

Adyen webhooks support multiple authentication methods:

MethodConfiguration
HMAC SignatureCryptographic signature for payload verification (recommended)
OAuth 2.0Token-based authentication (Standard webhooks only)
HTTP Basic AuthUsername and password sent with each request

OAuth 2.0 is strongly recommended over Basic Auth for Standard webhooks. HMAC signatures should always be verified regardless of which authentication method you use.

Configuration hierarchy

Adyen allows webhook configuration at multiple levels:

  • Company Account (recommended): Applies to all merchant accounts
  • Merchant Account: Applies to a specific merchant
  • Merchant Account Groups: Applies to grouped merchants

Adyen strongly recommends company-level configuration to ensure consistent webhook delivery and simplify management. Platform webhooks can only be configured at the company level.

Merchant account filtering

Within a webhook configuration, you can filter which merchant accounts trigger events:

  • All accounts: Every merchant account sends to this endpoint
  • Include only: Only specified merchant accounts send events
  • Exclude specific: All accounts except those specified

Setting up Adyen webhooks

Via the Adyen Customer Area

  1. Log in to your Customer Area
  2. Navigate to Developers > Webhooks
  3. Click + Webhook and select your webhook type (e.g., Standard)
  4. Configure the webhook settings:
    • URL: Your HTTPS endpoint that will receive webhooks
    • Method: JSON (recommended), SOAP, or HTTP POST
    • SSL Version: TLSv1.2 or TLSv1.3
    • Authentication: Configure Basic Auth or Authorization header
  5. Under Additional Settings, enable any non-default event codes
  6. Generate an HMAC Key and save it securely
  7. Click Test to verify connectivity
  8. Click Save

Via the Management API

curl -X POST https://management-test.adyen.com/v3/companies/{companyId}/webhooks \
  -H "X-API-Key: $ADYEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "standard",
    "url": "https://your-endpoint.com/webhooks/adyen",
    "username": "webhook-user",
    "password": "secure-password",
    "active": true,
    "communicationFormat": "json",
    "sslVersion": "TLSv1.2"
  }'

Best practices when working with Adyen webhooks

Verifying HMAC signatures

When processing webhooks from Adyen, verify the HMAC signature to ensure requests genuinely originated from Adyen and weren't modified in transit.

Acknowledge first, process later

Adyen requires acknowledgment within 10 seconds. Always acknowledge immediately and process asynchronously.

Use pspReference + eventCode for idempotency

Adyen may deliver the same webhook multiple times. Use the combination of pspReference and eventCode as a unique identifier:

async function processWebhook(notification) {
  const idempotencyKey = `${notification.pspReference}:${notification.eventCode}`;

  // Check if already processed
  const exists = await redis.get(`processed:${idempotencyKey}`);
  if (exists) {
    console.log(`Webhook ${idempotencyKey} already processed, skipping`);
    return;
  }

  // Process the webhook
  await handlePaymentEvent(notification);

  // Mark as processed with TTL
  await redis.setex(`processed:${idempotencyKey}`, 86400, '1'); // 24 hour TTL
}

Handle out-of-order delivery

Webhooks may arrive out of chronological order. Use eventDate to determine the true sequence.

Adyen webhook limitations and pain points

Strict 10-second timeout

The Problem: Adyen requires webhook acknowledgment within 10 seconds. Any delay (whether from slow database writes, external API calls, or complex validation) causes the webhook to fail and enter the retry queue.

Why It Happens: Adyen optimizes for reliability at scale. The strict timeout ensures their infrastructure isn't blocked by slow consumers and maintains predictable delivery patterns across millions of merchants.

Workarounds:

  • Implement async processing: acknowledge immediately, process later
  • Use a message queue (Hookdeck, Redis, RabbitMQ, SQS) to decouple receipt from processing
  • Minimize synchronous operations in your webhook handler
  • Move all business logic to background workers

How Hookdeck Can Help: Hookdeck acts as a webhook proxy, immediately acknowledging Adyen's webhooks while reliably forwarding them to your endpoint. This eliminates timeout concerns entirely and gives your application as much time as needed to process events.

No granular event filtering

The Problem: While you can enable/disable non-default event codes, default events (like AUTHORISATION) cannot be disabled. You receive all default events even if you only need a subset, increasing processing overhead.

Why It Happens: Adyen considers certain events essential for payment reconciliation and wants to ensure merchants don't accidentally miss critical payment updates.

Workarounds:

  • Filter events in your handler and quickly acknowledge unwanted ones
  • Use separate endpoints for different processing requirements
  • Implement early-exit logic for events you don't need

How Hookdeck Can Help: Hookdeck's filtering rules let you route or discard events based on payload content before they reach your server. Create rules to only forward specific eventCode values, reducing load on your infrastructure.

Out-of-order delivery

The Problem: Adyen doesn't guarantee chronological delivery. A CAPTURE webhook might arrive before the AUTHORISATION for the same payment, breaking workflows that assume sequential processing.

Why It Happens: Distributed systems, retry queues, and network conditions mean events generated milliseconds apart may arrive in any order. Adyen prioritizes delivery reliability over strict ordering.

Workarounds:

  • Use eventDate timestamps to determine true chronological order
  • Implement idempotent handlers that check current state before processing
  • Build event buffers that hold and reorder events before processing
  • Store all events and process based on state rather than arrival order

How Hookdeck Can Help: Hookdeck can buffer incoming webhooks and deliver them to your endpoint in the correct order based on timestamp or sequence number. Its transformation capabilities can also enrich events with ordering metadata.

Duplicate event delivery

The Problem: The same webhook event may be delivered multiple times, especially during retry scenarios. Without proper handling, this can cause duplicate orders, double refunds, or inconsistent data.

Why It Happens: Adyen uses at-least-once delivery. Network timeouts, infrastructure issues, or delayed acknowledgments can trigger redelivery of events you've already processed.

Workarounds:

  • Track processed events using eventCode + pspReference as a unique key
  • Implement idempotent operations that produce the same result regardless of repetition
  • Use database constraints to prevent duplicate record creation
  • Cache processed event IDs with appropriate TTL

How Hookdeck Can Help: Hookdeck's deduplication feature can automatically filter duplicate webhooks based on configurable payload fields. It can identify and filter duplicate events before they reach your endpoint, simplifying your handler logic.

Challenging local development

The Problem: Testing webhooks locally requires exposing your development machine to the internet. Tools like ngrok work but generate new URLs on restart, requiring constant reconfiguration in Adyen's Customer Area.

Why It Happens: Webhooks are server-to-server communication. Adyen's infrastructure needs a publicly accessible endpoint to deliver events, which conflicts with typical local development setups behind NAT and firewalls.

Workarounds:

  • Use ngrok with a paid plan for static domains
  • Leverage Adyen's Postman collections for initial testing
  • Use cloud development environments (Gitpod, GitHub Codespaces)
  • Set up a staging environment with a stable endpoint

How Hookdeck Can Help: Hookdeck provides stable webhook URLs that never change. Use the Hookdeck CLI to create a tunnel to your localhost, receiving real Adyen webhooks locally without reconfiguring Adyen when your tunnel restarts.

Complex multi-environment key management

The Problem: Managing HMAC keys across development, staging, and production environments is error-prone. Using the wrong key causes silent verification failures, and key rotation requires careful coordination.

Why It Happens: Each webhook endpoint needs its own HMAC key, and test vs. live environments require separate keys. Organizations with multiple merchant accounts and environments can end up managing dozens of keys.

Workarounds:

  • Use the Key Check Value (KCV) to verify you're using the correct key
  • Implement key management in your configuration/secrets management system
  • Document which keys belong to which environments
  • Use environment variables to inject the correct key at runtime

How Hookdeck Can Help: Hookdeck handles HMAC verification for Adyen webhooks automatically. Configure your Adyen HMAC key once in Hookdeck, and it verifies all incoming webhooks. Your application only needs to implement Hookdeck's simpler signature verification.

Webhook configuration expiration

The Problem: Adyen automatically deletes webhook configurations that have been inactive for more than six months. This can silently break integrations for seasonal businesses or infrequently-used features.

Why It Happens: Adyen cleans up unused configurations to maintain system hygiene and reduce the overhead of maintaining stale endpoints.

Workarounds:

  • Implement monitoring to detect missing webhooks
  • Use test webhooks periodically to keep configurations active
  • Document all webhook configurations and review regularly
  • Set calendar reminders to verify webhook health

How Hookdeck Can Help: Hookdeck endpoints remain stable regardless of activity. By pointing Adyen at Hookdeck, you maintain an active webhook configuration while Hookdeck handles forwarding to your actual endpoints, which may vary in activity.

Port restrictions

The Problem: Live webhooks only work on ports 443, 8443, or 8843. If your infrastructure uses non-standard ports, you'll need to reconfigure or add a reverse proxy.

Why It Happens: Adyen enforces standard HTTPS ports for security compliance and to ensure webhooks traverse firewalls reliably.

Workarounds:

  • Use a reverse proxy (nginx, HAProxy) to forward from allowed ports
  • Reconfigure your application to listen on standard ports
  • Use a load balancer that accepts on standard ports

How Hookdeck Can Help: Hookdeck receives webhooks on standard ports and can forward to any port on your infrastructure, removing port restrictions from your architecture decisions.

No built-in payload transformation

The Problem: You can't modify the webhook payload structure. If your system expects a different format, you must transform every incoming webhook before processing.

Why It Happens: Adyen maintains a standardized payload format for consistency across their platform and documentation.

Workarounds:

  • Build a transformation layer in your webhook handler
  • Use middleware to normalize payloads before processing
  • Create wrapper objects that map Adyen's format to your domain model

How Hookdeck Can Help: Hookdeck's transformation feature lets you modify webhook payloads in transit using JavaScript. Transform Adyen's payload structure to match your application's expected format before delivery.

Single endpoint per webhook configuration

The Problem: Each webhook configuration delivers to exactly one endpoint. If you need the same events in multiple systems (analytics, fulfilment, fraud detection), you must create separate webhook configurations for each.

Why It Happens: Adyen's webhook system is designed for straightforward point-to-point delivery rather than event fan-out patterns.

Workarounds:

  • Create multiple webhook configurations pointing to different endpoints
  • Build your own fan-out service that receives webhooks and distributes them
  • Use a message broker to distribute events internally

How Hookdeck Can Help: Hookdeck supports multiple destinations per source. Receive Adyen webhooks once and fan out to multiple endpoints automatically, reducing configuration overhead and ensuring consistent delivery across systems.

Testing Adyen webhooks

Use the built-in test feature

The webhook configuration in your Customer Area includes a Test button that sends a sample payload. However, be aware that:

  • Test payloads may differ from real payment events
  • The test may succeed while real deliveries fail due to payload differences
  • Some authentication issues only surface with actual payment data

Use a request inspector

Before building your handler, inspect real Adyen payloads using services like Hookdeck's Console:

  1. Create a temporary webhook URL
  2. Configure it as your webhook endpoint in Adyen
  3. Make a test payment to trigger real events
  4. Inspect the payload structure and headers

Use Adyen's Postman collections

Adyen provides official Postman collections with sample webhook payloads for rapid development:

  • Test different event types without making real payments
  • Develop handlers before going live
  • Debug payload parsing issues

Local development with Hookdeck

For the most realistic testing experience:

  1. Install the Hookdeck CLI: npm install -g hookdeck-cli
  2. Start a local tunnel: hookdeck listen 3000 adyen
  3. Copy the generated URL to your Adyen webhook configuration
  4. Process real webhooks locally with full replay and inspection capabilities

Conclusion

Adyen webhooks are essential for building robust payment integrations, providing real-time notifications for the entire payment lifecycle. The rich payload structure with event codes, payment details, and HMAC signatures enables secure, reliable processing of payment events.

However, limitations around timeouts, duplicate delivery, out-of-order events, and local development mean production deployments require careful consideration. Implementing proper signature verification, idempotent processing, and asynchronous handling will address most common issues.

For most deployments with reliable endpoints and moderate transaction volumes, Adyen's built-in webhook system combined with proper error handling and idempotency works well. For high-volume payment processing, complex multi-destination routing, or mission-critical payment workflows where delivery guarantees matter, webhook infrastructure like Hookdeck can address Adyen's limitations, providing configurable timeouts, payload transformation, automatic deduplication, and comprehensive delivery monitoring without modifying your Adyen configuration.

Additional resources


Gareth Wilson

Gareth Wilson

Product Marketing

Multi-time founding marketer, Gareth is PMM at Hookdeck and author of the newsletter, Community Inc.