Guide to Worldline Webhooks: Features and Best Practices
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
| Feature | Details |
|---|---|
| Webhook configuration | Merchant Portal (Direct), Configuration Center (Connect), or per-request via API |
| Signature algorithm | HMAC-SHA256 |
| Signature header | X-GCS-Signature |
| Key ID header | X-GCS-KeyId |
| Response timeout | 10 seconds (Connect) |
| Retry logic | 5 retries with escalating intervals (10 min — 1 hr — 2 hr — 8 hr — 24 hr) |
| Retry tracking | retry-count header included with each attempt |
| Manual retry | Not available |
| Endpoint verification | GET request with X-GCS-Webhooks-Endpoint-Verification header (Connect) |
| Max endpoints | 5 per merchant ID |
| Event filtering | Per-endpoint event type subscription (Connect) |
| Browsable log | Limited; debug grids available in some plugins |
| HTTPS required | Yes — 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:
| Event | Description |
|---|---|
payment.created | The transaction or operation (e.g., a refund) has been created |
payment.redirected | The consumer has been redirected to a third party for authentication/payment |
payment.authorization_requested | An authorization has been requested against an asynchronous system |
payment.pending_approval | Transactions waiting for your approval |
payment.pending_completion | Transactions waiting for you to complete them |
payment.pending_capture | Transactions waiting for you to capture them |
payment.capture_requested | The transaction is in the queue to be captured (card authorized) |
payment.captured | The transaction has been captured with online confirmation received |
payment.rejected | The transaction has been rejected |
payment.rejected_capture | The capture request was rejected by Worldline or a downstream acquirer |
payment.cancelled | You or your customer cancelled the transaction |
payment.refunded | The transaction has been refunded |
refund.refund_requested | The transaction is in the queue to be refunded |
paymentlink.created | A payment link was created |
paymentlink.clicked | A payment link was clicked or visited |
paymentlink.paid | A payment was successfully processed via the payment link |
paymentlink.cancelled | The payment link was cancelled |
paymentlink.expired | The 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
| Field | Description |
|---|---|
apiVersion | API version of the webhook event (v1 or v2) |
created | Timestamp of when the event was generated |
id | Unique identifier for this specific webhook event |
merchantId | The merchant account the event relates to |
payment.id | The payment identifier (changes with maintenance operations) |
payment.status | Current transaction status (e.g., CREATED, CAPTURED, REFUNDED) |
payment.statusOutput.statusCode | Numeric status code for the transaction |
payment.statusOutput.statusCategory | High-level status grouping (CREATED, PENDING_CONNECT_OR_3RD_PARTY, COMPLETED) |
payment.paymentOutput.amountOfMoney | Transaction amount and currency |
payment.paymentOutput.references.merchantReference | Your original order reference |
type | The 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:
- Retrieve the key ID from the
X-GCS-KeyIdheader - Look up the corresponding webhook secret key
- Convert the request body to bytes using UTF-8 encoding
- Create an HMAC-SHA256 signature using the secret key
- Base64-encode the resulting signature
- Compare it with the value in the
X-GCS-Signatureheader
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:
| Operation | Event | Status Code | payment.id |
|---|---|---|---|
| You send an authorization via CreatePayment | payment.created | 5 | payment.id1 |
| You capture via CapturePayment | payment.capture_requested | 91 | payment.id2 |
| Worldline confirms the capture | payment.captured | 9 | payment.id2 |
| You refund via RefundPayment | refund.refund_requested | 81 | payment.id3 |
| Worldline confirms the refund | payment.refunded | 8 | payment.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)
- Log in to the Merchant Portal
- Navigate to Developer > Webhooks
- Click Generate webhooks keys to create your webhook credentials (store the Secret Webhook Key immediately — it's only visible for 60 seconds)
- Click Add webhook endpoint and enter your HTTPS endpoint URL
- Confirm the endpoint (you can add up to five URLs)
Via the Configuration Center (Worldline Connect)
- Log in to the Configuration Center
- Navigate to the Webhooks Keys page and click Request webhooks key
- Open the Webhooks page for the relevant merchant ID
- Click Add endpoint, provide the HTTPS URL, and select which event types it should receive
- 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
GetPaymentDetailsorGetHostedCheckoutStatusto 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.idandtypeas a deduplication key - On Worldline Connect, use the unique event
idfield 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
SendTestWebhookendpoint to verify your setup rather than triggering real transactions - During development, use per-request
feedbacks.webhooksUrlsto 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
SendTestWebhookAPI 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:
- Create a Hookdeck connection with a destination pointing to your development server
- Configure the Hookdeck source URL as your webhook endpoint in Worldline
- Trigger a real payment in the sandbox environment
- 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.