Webhooks
Webhooks allow your application to receive real-time notifications when specific events occur in our system. Instead of polling the API for changes, we push updates directly to your endpoint via HTTP POST requests the moment they happen. This is the recommended way to react to state changes — for example, to trigger order fulfillment when a transaction reaches the Fulfill state (see Transaction States).
Typical use cases
- Instant fulfillment — trigger warehouse picking or digital product delivery the moment a transaction is authorized or fulfilled.
- Automated bookkeeping — feed payment data directly into your ERP or accounting software without manual data entry.
- Inventory synchronization — update stock levels across all sales channels as soon as a sale is finalized.
- Proactive subscription recovery — react immediately when a subscription payment fails, for example by sending a dunning email.
Setup and configuration
Configuring webhooks takes two steps: register a webhook URL (the endpoint on your server that receives the payloads), then create a webhook listener (defines which entity types and states trigger a notification to that URL).
Webhook URLs
Webhook URLs are managed centrally under Space > Settings > General > Webhook URLs. Because the URL is stored in one place, you can change your endpoint without touching the individual listener configurations. You can also create webhook URLs programmatically using our API or SDKs.
Webhook listeners
Webhook listeners are configured under Space > Settings > General > Webhook Listeners. For each listener you define:
- which entity type to observe (e.g. Transaction, Subscription — only certain entities are subscribable; the list of available entities is shown when creating a listener),
- which states should trigger a notification, or all state changes,
- whether payload signing (and with it the
statefield) is enabled, - other metadata such as name, identity, deletion schedule and versioning.
Receiving webhooks
When an event is triggered, we send an HTTP POST request to your registered URL. Your endpoint must return an HTTP 200 response to confirm receipt.
If your endpoint does not confirm the delivery, PostFinance Checkout retries with increasing intervals over a period of up to 80 hours. After 14 failed attempts, the listener is automatically deactivated to avoid endless attempts against an unresponsive endpoint.
All webhook invocations — successful or failed — are logged under Space > Settings > General > Webhook Invocations, including error details and the response returned by your server. This is the first place to look when notifications do not arrive as expected.
Webhook payload structure
The basic payload contains metadata about the event — no business data. Your application must make a follow-up API call to fetch the entity details if needed.
| Field | Description |
|---|---|
eventId | Unique ID for the event |
entityId | ID of the entity that changed |
listenerEntityId | ID of the entity type |
listenerEntityTechnicalName | Technical name of the entity type |
spaceId | Your space ID |
webhookListenerId | ID of the listener |
timestamp | Time of the event |
state (optional) | State of the entity, included if payload signing is enabled |
Basic payload example
{
"eventId": 138833842,
"entityId": 63762876,
"listenerEntityId": 1472041829003,
"listenerEntityTechnicalName": "Transaction",
"spaceId": 30140,
"webhookListenerId": 285874,
"timestamp": "2022-08-23T14:20:53+0000"
}
Payload with state (signed)
{
"eventId": 138833842,
"entityId": 63762876,
"listenerEntityId": 1472041829003,
"listenerEntityTechnicalName": "Transaction",
"spaceId": 30140,
"webhookListenerId": 285874,
"timestamp": "2022-08-23T14:20:53+0000",
"state": "PROCESSING"
}
If the state field is present, your application can act on the state change directly — saving the additional API call to check the entity's state.
Security: payload signing
A robust signing mechanism based on ECDSA with SHA-256 guarantees the authenticity and integrity of every payload: it proves the notification really came from us and has not been tampered with. Payloads are hashed and signed with a private key; the matching public key is exposed via the Webhook Encryption Service using a keyId. Payload signing is enabled per listener.
Signed requests include an x-signature header:
x-signature: algorithm=SHA256withECDSA, keyId=2dcd5b38-78a1-47ea-a1c7-ed760403d88c, signature=jXt3fB8v7v/ea2MGUXj+c+...
| Field | Description |
|---|---|
algorithm | Always SHA256withECDSA |
keyId | Identifier of the public key used to verify the signature |
signature | The encoded signature itself |
To verify a payload, retrieve the public key for the keyId from PostFinance Checkout and validate the signature against the received payload. We recommend using one of our official SDKs — they provide built-in methods that handle the key retrieval and signature verification for you.
Payload signing is mandatory. Integrate the signature verification from the start of your development.
Always serve your webhook endpoint over HTTPS to protect the payload and headers in transit.
Firewall requirements
To ensure webhook delivery, allow incoming HTTPS requests from the following IP addresses in your firewall and at your hosting provider:
52.211.247.160
52.211.171.77
52.211.239.229
52.211.209.173
52.208.210.84
52.212.109.85
52.210.89.1
52.212.185.152
52.212.192.130
Quick checklist
- Configure the destination URL and enable the payload signature (mandatory — it also gives you the
statefield). - Define a webhook listener (via portal or API) for the entities and states you are interested in.
- Return HTTP
200from your endpoint to confirm each delivery. - Implement server-side logic to verify the
x-signature, parse thestatedirectly, or retrieve the entity via the API. - Monitor the webhook invocations in your space and adjust as necessary.
Troubleshooting
- What does 'Webhook call failed' mean and how can it be fixed?
- How can I use wallee webhooks with active .htaccess basic HTTP authentication?
- Retries exhausted? Reactivate the listener after fixing your endpoint, and check the invocation log for the exact error returned by your server.