Gareth Wilson Gareth Wilson

Guide to Worldline Webhooks: Features and Best Practices

Published


Worldline is one of Europe's largest payment services providers, processing billions of transactions annually for merchants across the globe. Whether you're using Worldline Direct (their modern API platform) or Worldline Connect (formerly Ingenico ePayments), webhooks are the primary mechanism for receiving asynchronous notifications about payment lifecycle events — from authorization and capture through to refunds and cancellations.

This guide covers everything you need to know about Worldline webhooks: their features, how to configure them, best practices for production deployments, and the common pain points developers face along with practical solutions.

What are Worldline webhooks?

Worldline webhooks are HTTP POST callbacks that deliver transaction status notifications to HTTPS endpoints on your server. Whenever a payment event occurs (such as a successful authorization, a capture confirmation, or a refund) Worldline sends a JSON payload containing the full transaction details, including the payment.id, amount, status, and any relevant customer data.

Webhooks notify you of both successful and failed operations, enabling you to automate your transaction processing workflow and keep your order management systems in sync without polling the API.

Worldline's webhook system exists across two primary platforms:

  • Worldline Direct — The modern API platform with webhook management via the Merchant Portal
  • Worldline Connect — The legacy platform with webhook configuration via the Configuration Center

While the platforms share many concepts, there are differences in configuration, endpoint verification, and IP handling. This guide covers both where they diverge.

Worldline webhook features

FeatureDetails
Webhook configurationMerchant Portal (Direct), Configuration Center (Connect), or per-request via API
Signature algorithmHMAC-SHA256
Signature headerX-GCS-Signature
Key ID headerX-GCS-KeyId
Response timeout10 seconds (Connect)
Retry logic5 retries with escalating intervals (10 min — 1 hr — 2 hr — 8 hr — 24 hr)
Retry trackingretry-count header included with each attempt
Manual retryNot available
Endpoint verificationGET request with X-GCS-Webhooks-Endpoint-Verification header (Connect)
Max endpoints5 per merchant ID
Event filteringPer-endpoint event type subscription (Connect)
Browsable logLimited; debug grids available in some plugins
HTTPS requiredYes — encrypted communication only
SDK support.NET, Java, Node.js, PHP, Python, Ruby, Go

Supported event types

Worldline webhooks notify you of the following payment lifecycle events:

EventDescription
payment.createdThe transaction or operation (e.g., a refund) has been created
payment.redirectedThe consumer has been redirected to a third party for authentication/payment
payment.authorization_requestedAn authorization has been requested against an asynchronous system
payment.pending_approvalTransactions waiting for your approval
payment.pending_completionTransactions waiting for you to complete them
payment.pending_captureTransactions waiting for you to capture them
payment.capture_requestedThe transaction is in the queue to be captured (card authorized)
payment.capturedThe transaction has been captured with online confirmation received
payment.rejectedThe transaction has been rejected
payment.rejected_captureThe capture request was rejected by Worldline or a downstream acquirer
payment.cancelledYou or your customer cancelled the transaction
payment.refundedThe transaction has been refunded
refund.refund_requestedThe transaction is in the queue to be refunded
paymentlink.createdA payment link was created
paymentlink.clickedA payment link was clicked or visited
paymentlink.paidA payment was successfully processed via the payment link
paymentlink.cancelledThe payment link was cancelled
paymentlink.expiredThe payment link expiration date was reached

Webhook payload structure

Each webhook delivers a JSON array containing one or more event objects. Here's an example of a payment.captured event:

[
  {
    "apiVersion": "v1",
    "created": "2025-01-15T14:30:42.146Z",
    "id": "7aeb0c3d-066e-4d31-bfe9-f9b5e48414df",
    "merchantId": "YOUR_MERCHANT_ID",
    "payment": {
      "paymentOutput": {
        "amountOfMoney": {
          "amount": 1000,
          "currencyCode": "EUR"
        },
        "references": {
          "merchantReference": "ORDER_12345"
        },
        "cardPaymentMethodSpecificOutput": {
          "paymentProductId": 1,
          "authorisationCode": "auth123",
          "card": {
            "cardNumber": "************4675",
            "expiryDate": "1226"
          },
          "fraudResults": {
            "fraudServiceResult": "challenged",
            "avsResult": "U",
            "cvvResult": "M"
          },
          "threeDSecureResults": {
            "version": "2.2.0",
            "authenticationStatus": "Y",
            "eci": "5",
            "liability": "issuer"
          }
        },
        "paymentMethod": "card"
      },
      "status": "CAPTURED",
      "statusOutput": {
        "isCancellable": false,
        "statusCategory": "COMPLETED",
        "statusCode": 9,
        "isAuthorized": false,
        "isRefundable": true
      },
      "id": "3092546156"
    },
    "type": "payment.captured"
  }
]

Key payload fields

FieldDescription
apiVersionAPI version of the webhook event (v1 or v2)
createdTimestamp of when the event was generated
idUnique identifier for this specific webhook event
merchantIdThe merchant account the event relates to
payment.idThe payment identifier (changes with maintenance operations)
payment.statusCurrent transaction status (e.g., CREATED, CAPTURED, REFUNDED)
payment.statusOutput.statusCodeNumeric status code for the transaction
payment.statusOutput.statusCategoryHigh-level status grouping (CREATED, PENDING_CONNECT_OR_3RD_PARTY, COMPLETED)
payment.paymentOutput.amountOfMoneyTransaction amount and currency
payment.paymentOutput.references.merchantReferenceYour original order reference
typeThe event type (e.g., payment.captured, payment.refunded)

Security with HMAC signatures

Worldline signs every webhook payload using HMAC-SHA256 with your webhook secret key. The signature is included in the X-GCS-Signature HTTP header, and the key identifier is sent via the X-GCS-KeyId header.

To verify a webhook signature manually:

  1. Retrieve the key ID from the X-GCS-KeyId header
  2. Look up the corresponding webhook secret key
  3. Convert the request body to bytes using UTF-8 encoding
  4. Create an HMAC-SHA256 signature using the secret key
  5. Base64-encode the resulting signature
  6. Compare it with the value in the X-GCS-Signature header

Worldline recommends using separate keys for REST API authentication and webhook signature verification. The webhook key does not expire (unlike the REST API key), but if you regenerate it via the Merchant Portal, the previous key is revoked immediately.

Endpoint verification (Worldline Connect)

On the Connect platform, Worldline verifies your endpoint when it's first registered. The platform sends an HTTPS GET request containing a random string in the X-GCS-Webhooks-Endpoint-Verification header. Your endpoint must respond with a plain text body containing only that header's value. If verification fails, the endpoint is added in a deactivated state and can be activated later after fixing the issue.

Understanding payment.id changes

One of the more nuanced aspects of Worldline webhooks is how the payment.id changes over a transaction's lifecycle. When you perform maintenance operations (captures, refunds), the payment.id changes. However, when Worldline performs status changes internally (like confirming a capture), the payment.id remains the same.

Here's how it works in practice:

OperationEventStatus Codepayment.id
You send an authorization via CreatePaymentpayment.created5payment.id1
You capture via CapturePaymentpayment.capture_requested91payment.id2
Worldline confirms the capturepayment.captured9payment.id2
You refund via RefundPaymentrefund.refund_requested81payment.id3
Worldline confirms the refundpayment.refunded8payment.id3

Use the GetPaymentDetails endpoint with the operations.id property to trace the full payment.id history for a transaction.

Setting up Worldline webhooks

Via the Merchant Portal (Worldline Direct)

  1. Log in to the Merchant Portal
  2. Navigate to Developer > Webhooks
  3. Click Generate webhooks keys to create your webhook credentials (store the Secret Webhook Key immediately — it's only visible for 60 seconds)
  4. Click Add webhook endpoint and enter your HTTPS endpoint URL
  5. Confirm the endpoint (you can add up to five URLs)

Via the Configuration Center (Worldline Connect)

  1. Log in to the Configuration Center
  2. Navigate to the Webhooks Keys page and click Request webhooks key
  3. Open the Webhooks page for the relevant merchant ID
  4. Click Add endpoint, provide the HTTPS URL, and select which event types it should receive
  5. Your endpoint must pass the verification GET request to become active

Per-request webhook URLs

Instead of hard-coding webhook URLs, you can specify them per transaction using the feedbacks.webhooksUrls property in your CreateHostedCheckout or CreatePayment requests:

{
  "order": {
    "amountOfMoney": {
      "amount": 1000,
      "currencyCode": "EUR"
    }
  },
  "feedbacks": {
    "webhooksUrls": [
      "https://your-server.com/webhooks/worldline",
      "https://backup-server.com/webhooks/worldline"
    ]
  }
}

Note that values in feedbacks.webhooksUrls override any URLs configured in your account. The older feedbacks.webhookUrl property is deprecated.

Best practices when working with Worldline webhooks

Verifying HMAC signatures

When processing webhooks, always verify the signature to ensure the request genuinely originated from Worldline. Using the official SDKs handles this automatically.

Respond immediately to avoid timeouts

Worldline has a tight response timeout. Decouple your business logic from webhook handling — return a 2xx status code immediately, then process the event asynchronously.

Implement idempotent processing

Worldline explicitly states that duplicate webhook deliveries are a feature of their reliable delivery architecture. Use the combination of payment.id and type to deduplicate:

async function processWebhookEvent(event) {
  const idempotencyKey = `${event.payment.id}-${event.type}`;

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

  await handleEvent(event);

  // Mark as processed with 48-hour TTL
  await redis.setex(`webhook:${idempotencyKey}`, 172800, '1');
}

Track payment.id changes across the lifecycle

Since payment.id changes with maintenance operations, maintain a mapping in your database:

async function trackPaymentId(event) {
  const { merchantReference } = event.payment.paymentOutput.references;
  const currentPaymentId = event.payment.id;

  await db.orders.update(
    { merchantReference },
    {
      $set: { currentPaymentId, lastStatus: event.payment.status },
      $push: { paymentIdHistory: currentPaymentId }
    }
  );
}

Build a fallback polling mechanism

Worldline themselves recommend implementing backup polling alongside webhooks. Use GetHostedCheckoutStatus or GetPaymentDetails to reconcile.

Worldline webhook limitations and pain points

Tight response timeout

The Problem: Worldline Connect enforces a response timeout as short as 10 seconds. If your endpoint doesn't respond within this window, Worldline treats the delivery as failed and queues a retry. For endpoints that need to perform any non-trivial processing (such as database lookups or downstream API calls) this window is very tight.

Why It Happens: Worldline optimizes for throughput and rapid acknowledgment. The timeout is server-side and not configurable via the Merchant Portal or Configuration Center.

Workarounds:

  • Always return a 2xx response immediately before performing any business logic
  • Use a message queue (Hookdeck, RabbitMQ, SQS, Redis) to decouple receipt from processing
  • Avoid synchronous database writes in the webhook handler itself

How Hookdeck Can Help: Hookdeck accepts webhooks from Worldline on your behalf and forwards them to your endpoint with configurable delivery timeouts, giving you more time to process complex payment events without triggering Worldline's retry logic.

Only five retries with no manual replay

The Problem: When webhook delivery fails, Worldline retries only five times over a roughly 35-hour window (10 minutes, 1 hour, 2 hours, 8 hours, 24 hours). After that, the webhook is lost. There is no built-in mechanism to manually replay or retrieve missed webhooks.

Why It Happens: Worldline's retry schedule is fixed at the platform level. There is no dead letter queue, no delivery log accessible via API, and no manual retry button in the Merchant Portal.

Workarounds:

  • Build a fallback polling mechanism using GetPaymentDetails or GetHostedCheckoutStatus to catch any missed events
  • Implement your own webhook receipt log so you can detect gaps
  • Set up health monitoring on your webhook endpoint to minimize downtime

How Hookdeck Can Help: Hookdeck provides automatic retries with configurable backoff policies, a dead letter queue for failed deliveries, and a dashboard with full delivery history. You can manually replay any failed webhook with a single click, eliminating the risk of permanently lost payment notifications.

Duplicate webhook deliveries by design

The Problem: Worldline explicitly states that receiving duplicate webhook events is a feature, not a bug. Their documentation says to "assume every webhook event might be repeated." This places the burden of idempotent processing entirely on the developer.

Why It Happens: Worldline's at-least-once delivery architecture prioritizes reliability over exactness. In scenarios where delivery confirmation is ambiguous (such as network timeouts) the platform re-sends the event to ensure it arrives.

Workarounds:

  • Use the combination of payment.id and type as a deduplication key
  • On Worldline Connect, use the unique event id field for deduplication
  • Maintain a processed-events cache with a TTL (e.g., 48 hours in Redis)

How Hookdeck Can Help: Hookdeck's built-in deduplication feature can automatically filter duplicate webhooks based on payload content or custom identifiers, ensuring your endpoint processes each unique payment event exactly once.

Secret key displayed for only 60 seconds

The Problem: When you generate webhook credentials in the Worldline Direct Merchant Portal, the Secret Webhook Key is displayed for only 60 seconds. If you miss it, the key is gone and cannot be retrieved, you must regenerate, which immediately revokes the existing key and disrupts any active integrations.

Why It Happens: This is a security measure to reduce the risk of secret key exposure. However, it creates friction, especially in team environments where credentials need to be shared or stored in secret managers.

Workarounds:

  • Have your secret management tool (Vault, AWS Secrets Manager, etc.) ready before generating the key
  • Copy the key immediately and store it in your environment configuration
  • Document the regeneration process so your team can quickly recover if a key is missed

How Hookdeck Can Help: By routing webhooks through Hookdeck, the webhook secret is managed between Worldline and Hookdeck. You can then use Hookdeck's own authentication mechanisms to secure delivery to your endpoint, reducing the operational burden of Worldline's key management.

Configuration propagation delay

The Problem: On Worldline Connect, changes to webhook configuration (adding endpoints, updating event subscriptions) can take up to 10 minutes to take effect. During development and debugging, this delay significantly slows iteration.

Why It Happens: Worldline's distributed infrastructure propagates configuration changes asynchronously across their systems, introducing a delay before new settings are active.

Workarounds:

  • Plan webhook configuration changes well ahead of deployment
  • Use the SendTestWebhook endpoint to verify your setup rather than triggering real transactions
  • During development, use per-request feedbacks.webhooksUrls to override account-level configuration instantly

How Hookdeck Can Help: With Hookdeck as your webhook ingestion layer, you configure your Worldline endpoint URL once (pointing to Hookdeck) and manage all routing, filtering, and forwarding changes instantly in Hookdeck's dashboard — no waiting for Worldline's propagation.

Per-request webhook URL override issues

The Problem: Developers have reported that webhook URLs specified in CreateHostedCheckoutRequest via feedbacks.webhooksUrls are sometimes ignored, with Worldline calling the URL configured in the Merchant Portal instead.

Why It Happens: The root cause appears to be a platform-level behavior where the per-request URL is not consistently honored. This may be related to specific payment flows or configuration states.

Workarounds:

  • Test per-request URLs thoroughly before relying on them in production
  • Fall back to account-level URL configuration if per-request overrides are unreliable
  • If running multiple storefronts, consider using separate merchant IDs with dedicated webhook URLs

How Hookdeck Can Help: Route all Worldline webhooks to a single Hookdeck endpoint and use Hookdeck's routing rules to fan out events to different destinations based on payload content (such as merchantReference or custom metadata), eliminating the need for per-request URL overrides entirely.

HTTPS-only requirement complicates local development

The Problem: Worldline requires all webhook endpoints to use HTTPS. During local development and testing, developers cannot receive webhooks directly on localhost without additional tooling.

Why It Happens: This is a security requirement. Worldline only supports encrypted communication for webhook delivery to protect sensitive payment data in transit.

Workarounds:

  • Use tunneling tools like Hookdeck CLI to expose your local development server via a public HTTPS URL
  • Use Worldline's SendTestWebhook API endpoint for basic testing
  • Develop against recorded webhook payloads in a local test suite

How Hookdeck Can Help: Hookdeck provides a CLI that creates a secure tunnel between Hookdeck's infrastructure and your local server. Webhooks from Worldline are received by Hookdeck and forwarded to your localhost, with full visibility in the Hookdeck dashboard.

Testing Worldline webhooks

Validate your credentials

Before testing delivery, verify that your webhook key and secret are correctly configured using the ValidateWebhookCredentials endpoint:

curl -X POST https://payment.preprod.direct.worldline-solutions.com/v2/{merchantId}/webhooks/validate \
  -H "Authorization: Bearer $WORLDLINE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "key": "your-webhook-key",
    "secret": "base64-encoded-hmac-of-empty-string"
  }'

Send a test webhook

Use the SendTestWebhook endpoint to trigger a test delivery to your endpoint:

curl -X POST https://payment.preprod.direct.worldline-solutions.com/v2/{merchantId}/webhooks/test \
  -H "Authorization: Bearer $WORLDLINE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-endpoint.com/webhooks/worldline"
  }'

The test payload uses type: "payment.test" and contains sample transaction data. Your server should respond with a 2xx status code, and Worldline will return HTTP 204 to confirm successful delivery.

Use a request inspector

Before building your handler, inspect real Worldline payloads using Hookdeck Console:

  1. Create a Hookdeck connection with a destination pointing to your development server
  2. Configure the Hookdeck source URL as your webhook endpoint in Worldline
  3. Trigger a real payment in the sandbox environment
  4. Inspect the full payload, headers, and signature in Hookdeck's dashboard

Validate in staging

Test your webhook integration with realistic scenarios in Worldline's preprod environment:

  • Full payment flow: created — authorization_requested — captured
  • Rejected transactions and error handling
  • Capture and refund lifecycle with payment.id changes
  • Multiple concurrent transactions
  • Endpoint downtime and retry behavior

Conclusion

Worldline webhooks provide a robust foundation for integrating payment lifecycle events into your systems. The comprehensive event coverage (from payment creation through captures, refunds, and payment links) combined with HMAC-SHA256 signature verification and official SDKs in six languages gives you the tools needed to build secure, reliable integrations.

However, the tight response timeout, limited retry window, duplicate deliveries by design, and minimal observability tooling mean that production deployments require careful engineering. Implementing immediate acknowledgment, idempotent processing, fallback polling, and thorough logging are essential.

For straightforward integrations with a single endpoint and moderate transaction volume, Worldline's built-in webhook system combined with their server SDKs works well. For higher-volume deployments, multi-destination routing, or mission-critical payment workflows where every transaction notification matters, webhook infrastructure like Hookdeck can address Worldline's limitations by providing configurable timeouts, automatic deduplication, comprehensive delivery monitoring, and a dead letter queue without modifying your Worldline configuration.


Gareth Wilson

Gareth Wilson

Product Marketing

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