Webhooks
Learn which webhooks Datman sends for each event, and how to receive them.
A webhook is an HTTP POST request that Datman sends to an endpoint on your server when an event happens, such as a change in a payment's status. You must accept each webhook with an HTTP 200 status code, store the message, and then process its contents.
With webhooks, you don't need to keep polling an API endpoint to find out whether an asynchronous process has finished. You can make an API request, move on to other processes, and act on the result when Datman tells you that the event has happened.
Datman sends webhooks when:
- The status of a payment changes, for example when a payment is authorised, captured or cancelled.
- An internal transfer between two of your merchants succeeds or fails.
Why you need webhooks
Many flows in a Datman integration are asynchronous. The final status of a payment is not known when the shopper's browser comes back to your site. For example, after 3D Secure authentication or a payment on the hosted payment page, the redirect only tells you that the shopper has left Datman's page.
Webhooks solve this by sending you the outcome as soon as it is available. Treat the webhook, not the redirect, as the final status. You can then update your own systems. For example, when a payment for Example Pizza Ltd is authorised, you can mark the order as paid and send it to the kitchen.
Requirements
Before you begin, take into account the following requirements, limitations, and preparations.
| Requirement | Description |
|---|---|
| Integration type | A Datman partner integration that takes payments or makes internal transfers. |
| Webhooks | Your server must have a public HTTPS endpoint that accepts JSON POST requests. |
| Setup steps | Before you begin, get your signing keys from Datman so that you can verify signatures. |
How it works
- You send the URL of your webhook endpoint in the API request that starts the event, for example when you create a payment session.
- Datman sends an HTTP POST request with a JSON body to that URL when the event happens.
- Your server verifies the signature in the request header, to confirm that the webhook was sent by Datman and was not modified in transit.
- Your server stores the webhook in your database or a queue, so you can process it later.
- Your server accepts the webhook by responding with HTTP 200.
- Your server processes the data and applies your business logic. Make sure that you accept the webhook before you apply any business logic, because an error in your business logic can stop you from accepting it.
Example
Example Payments Partner creates a payment session for Example Pizza Ltd, a takeaway in Manchester, for an order of GBP 24.50. In the request, it sends WebhookUrl https://partner.example.com/webhooks/datman.
- The shopper pays and completes 3D Secure.
- Datman sends a
paymentStatuswebhook tohttps://partner.example.com/webhooks/datmanwithstatusauthorisation andsuccesstrue. - Example Payments Partner verifies the
HMACSignatureheader, stores the webhook, responds with HTTP 200, and then marks the order as paid.
Webhook structure
Each webhook is an HTTP POST request with a JSON body. The body is a flat JSON object: there is no common wrapper object or event type field. You can tell which webhook you received by the URL you set and by the fields in the body.
Each webhook carries a signature in a request header:
| Header | Sent with | Description |
|---|---|---|
HMACSignature | paymentStatus | HMAC-SHA256 of the request body, computed with your webhook secret and hex-encoded. |
X-Datman-Signature | internalTransferSucceeded, internalTransferFailed | HMAC-SHA256 of the request body, computed with your transfer signing key and hex-encoded. |
Note that HTTP header names are case-insensitive, so your framework can show HMACSignature as hmacsignature. For how to check the signature, see Verify webhook signatures.
Below is an example request body for a paymentStatus webhook.
Example webhook request body
{
"order_id": "ORD-100245",
"amount": "24.50",
"currency": "GBP",
"customer_id": "CUST-55021",
"xref": "O88213045M663412T4821937",
"status": "authorisation",
"success": "true",
"date": "2026-10-15 12:34:56+01:00",
"card_type": "visa"
}The full schema for each webhook is in the API Explorer.
Payment webhooks
Payment webhooks inform your system about changes in the status of a payment.
| Type | Description |
|---|---|
paymentStatus | The status of a payment changed. The status field tells you the event, such as authorisation or capture, and success tells you whether it succeeded. |
Transfer webhooks
Transfer webhooks inform your system about the result of an internal transfer between two of your merchants.
| Type | Description |
|---|---|
internalTransferSucceeded | The funds of an internal transfer moved from the source merchant to the destination merchant. |
internalTransferFailed | An internal transfer failed. The reason field tells you why. |
You can identify transfer webhooks by checking the following fields:
| Event | request_id | status | reason |
|---|---|---|---|
| Transfer succeeded | The request_id of the transfer | success | Not present |
| Transfer failed | The request_id of the transfer | Not present | Why the transfer failed |
Set up your webhook endpoint
Webhooks are HTTP callbacks sent to an endpoint on your server. To receive them, you need an endpoint that:
- Is publicly accessible over HTTPS.
- Accepts an HTTP POST request with a JSON body.
- Can read the raw request body, because you need it to verify the signature.
You don't subscribe to these webhooks in a portal. Instead, you send the URL of your endpoint in each request that starts an event:
| Webhook | Where you set the URL |
|---|---|
paymentStatus | webhook_url in the encrypted payload for the hosted payment page. |
internalTransferSucceeded, internalTransferFailed | webhook_url when you transfer funds between two merchants. |
Accept webhooks
When you receive a webhook from Datman, respond with HTTP 200 to show that you received it. Do not validate or process the data at this step.
How Datman handles a webhook that you don't accept depends on the webhook:
| Webhook | If you don't respond with HTTP 200 |
|---|---|
paymentStatus | Datman counts only HTTP 200 as accepted, so any other status code, including another 2xx code such as 202, counts as a failure. Datman sends the webhook again later. |
internalTransferSucceeded, internalTransferFailed | Datman sends each transfer webhook once and doesn't send it again. |
Process webhooks
After you accept the webhook and verify its signature, you can process the data in the body. This involves parsing the body and using the data to update your systems.
Webhook payload
The body contains the event data. For paymentStatus, the status field describes what happened and the date field tells you when it happened. To make sure that you process events in the correct order, always check date.
Handling duplicates
You can receive the same paymentStatus webhook more than once, for example when Datman sends it again because your server didn't respond with HTTP 200. Make sure that your system can deal with duplicates. Duplicate webhooks have the same xref and status. Your server should use the details from the latest webhook.
Check webhook deliveries
To see which payment webhooks Datman sent for a payment, use Get webhook deliveries for a transaction. The response lists each webhook call with the URL called, the payload sent, the HTTP status code your server returned in http_response_code, and when it was sent.
If http_response_code is not 200, check that your endpoint URL is correct, publicly accessible, and not blocked by a firewall, and that your server responds with HTTP 200 before it runs any business logic.
Test and go live
We recommend that you make a test payment in the sandbox environment and check the webhooks associated with it. Match the test payment to the webhook you receive by its order_id or xref.
When you go live, send the URL of your live webhook endpoint in your live requests, and use your live signing keys to verify signatures.
Next steps
Verify webhook signatures (required)
Check that each webhook was sent by Datman and was not modified.
Payment status webhooks
Find out which webhooks Datman sends for payment events.
Internal transfer succeeded
Find out what Datman sends when an internal transfer succeeds.
Internal transfer failed
Find out what Datman sends when an internal transfer fails.

