Skip to main content

Setting up webhooks

For integrators: how Softpay webhooks notify your server about transactions, merchants, stores and terminals, what to send us to set them up, and how to secure your endpoint.

What webhooks are

A webhook is a message Softpay's server sends to your server when something happens, most often when a transaction reaches its final state. This means your system is told about the result even if your POS app closes or loses connection during the payment.

Webhooks cover payments started any way, including through AppSwitch and the Cloud API. There is no extra cost for using them.

Full technical details, including payload examples, are in the developer documentation.

Webhooks are a safety net, not your main source of truth

Delivery can be delayed or retried, and if your endpoint is unreachable for a long time, some messages may never arrive. Your integration should always follow each transaction to its final state by itself:

  • In your app, wait for the final result of the payment and store it.

  • If your app does not get a final result (for example, it closed or lost connection), do not treat the payment as failed or start a new one straight away. Look up the transaction's final state first.

  • Use webhooks to confirm results and fill gaps, and make sure the same payment is not recorded twice.

Note for the Cloud API: if a payment flow is stopped before any processing has started, no webhook may be sent. Use the Cloud API to look up the transaction instead.

Available events

When we set up your webhook, you choose one of three options:

  • Transaction events: you get transaction.state_change when a transaction is completed, declined, failed or cancelled. This is what most integrators need.

  • Non-transaction events: you get events about your merchants, stores and terminals, for example when you create or change them through the Onboarding API. These are:

    • merchant.state_change: a merchant's status has changed.

    • store.state_change: a store's status has changed.

    • terminal.install: a terminal installation has completed.

    • terminal.state_change: a terminal's status has changed, for example active or inactive.

    • terminal.release: a terminal has been released.

    • terminal.configuration.final: the final terminal configuration state has been reported (Automated setup only).

  • All events: you get both of the above.

You cannot pick individual events within these groups. If you choose non-transaction events, for example, you get all of them. Every event includes its type, so your system can ignore the ones it does not need.

What your endpoint must do

  • Use HTTPS with TLS 1.2 or higher.

  • Accept POST requests with a JSON body.

  • Respond with an HTTP 2xx status within 10 seconds. Anything else counts as a failed delivery, including timeouts and redirects (3xx). Redirects are not followed.

  • Ignore repeated events. Each event has an id that stays the same if the event is sent again, so record it and skip events you have already processed.

  • Parse leniently. New fields may be added without notice, so do not use a strict JSON parser.

How to get webhooks set up

Softpay Support sets up webhooks for you. Once your endpoint is live on a public web server, email Support with:

  • Your endpoint URL(s) and which events each one should receive: transaction events, non-transaction events or all events. We recommend separate URLs for sandbox and production.

  • The merchant(s) the webhook should cover. In sandbox, give the merchant name shown in your sandbox app, for example "AjaxYourCompany".

  • Optional: extra authentication, either a static HTTP header or mutual TLS (see below).

We then send you a signature key, which you use to check that each webhook really comes from Softpay.

New setups and changes can take up to an hour to take effect, so allow for that before you start testing.

Sandbox and production

Start in sandbox. Sandbox and production are set up separately, each with its own signature key. When you are ready for production, send us your production endpoint and authentication details, and we will send you a new signature key.

Several merchants and endpoints

Webhooks are set up per merchant. Every event includes merchantReference, Softpay's own ID for the merchant account. This is not your merchant ID or the acquirer's merchant ID. When we set up webhooks, we send you the merchantReference for each merchant so you can map it to your own IDs. This means you can use one URL for all your merchants, which is the recommended setup.

You can arrange your endpoints in different ways:

  • One endpoint for everything: every webhook includes its event type, so one endpoint can receive all events and sort them.

  • Separate endpoints: for example, transaction events to one endpoint and non-transaction events to another.

  • Several endpoints for the same events: each event can be sent to up to 5 endpoints, for example a backup endpoint or several separate systems that all need the same information.

When you add a new merchant, ask Support to add it to your webhook, unless a partner-level default has been set up for you (see below).

Matching webhooks to your payments

For payments started through AppSwitch or the Cloud API (CloudSwitch), the transaction webhook includes the requestId you set when starting the payment. Use it to match the webhook to the payment in your system, and make sure each payment has its own unique requestId. Payments made directly in the Softpay app, without your POS, have no requestId. For those, use transactionId, Softpay's own ID for the transaction.

Partner-level default for new merchants

If you are both the partner that onboards the merchants and the integrator whose POS they use, a default webhook can be set up for you. It is then added automatically to every new merchant created for you. It only applies to merchants created after it is switched on, so existing merchants have to be added separately. Contact Support if you would like this set up.

A partner-level default is not possible when a partner onboards merchants that use different integrators' POS systems, because webhooks would then send merchant data to an integrator who should not have it. In that case, each merchant has to be added to your webhook individually.

Securing your endpoint

Always check the signature. Every webhook includes the header X-Softpay-Content-Signature-HMAC. It holds an HMAC-SHA256 of the request body, Base64-encoded and made with your signature key. Calculate the same value from the raw request body and compare. Make sure your framework does not change the body before you check it, or the signature will not match. There is a code example in the developer documentation.

We also recommend adding one of these, both set up through Support:

  • Static HTTP header: a fixed header sent with every webhook, for example Authorization: Basic …. Use different values in sandbox and production.

  • Mutual TLS: send us your client certificate in PEM format with the full intermediate certificate chain. Softpay does not track certificate expiry, so send us a new certificate before the current one expires.

Allowing webhooks through your firewall

Softpay does not use fixed IP addresses for webhooks, so IP-based allowlists are not possible. This applies to both sandbox and production. Instead, allow requests based on the path of your webhook endpoint, the method (POST) and your static header value. Then verify the signature on every request.

If you use a service such as Cloudflare, make sure your webhook path is not behind a challenge (for example a Managed Challenge, JS Challenge or bot protection). Webhooks are server-to-server calls and cannot complete a challenge, so they will always fail there.

Failed deliveries and retries

If a delivery fails, Softpay retries for up to 48 hours. After that the event is marked as failed and is not sent again. You are not notified when deliveries fail, so if you stop receiving webhooks, check your endpoint and contact Support.

Changing or removing a webhook

To change your endpoint URL, events or authentication, or to remove a webhook, email Support with the merchant name and the change you need. If you are getting the same webhook twice for every payment, there may be two webhooks set up for the merchant. Let us know and we will remove the extra one.

Did this answer your question?