Webhooks
Webhooks Applications
Utilizing Webhooks is crucial for real-time communication, workflow automation, improved system integration, enhanced scalability, data security, error handling, and regulatory compliance. Webhooks offer a reliable and efficient method for managing the dynamic and interconnected nature of e-commerce transactions, ultimately leading to a more reliable and user-friendly experience for both the platform operators and their customers.
Important Note
Webhook integration is mandatory and not optional. Adhering to this requirement is essential for the successful implementation and operation of the system. Failure to include this feature may result in non-compliance with system specifications, leading to issues such as unexpected failures, data discrepancies, duplication, and other unintended behaviors.Webhooks Version
The latest Webhook API version is 1.3.0. The webhook data that is returned in the latest version reflects the response data structure of the Payments API. Refer to the API Changelog for any changes in the Payments API response data structure.
Whitelisting PaymentsOS Server IPs
All our webhook requests originate from a set of IP addresses. If your server handing webhook requests is behind a firewall, you will need to whitelist the following set of IP addresses to ensure that requests succeed:
- 52.29.158.20
- 3.124.65.163
- 52.59.7.16
Webhook Events Structure
Webhook events returned in version 1.2.0 and higher have a different structure than the events returned in older Webhook versions. Refer to the topic of your choice, depending on the Webhook version you are using:
-
For version 1.2.0 and higher, see Webhook Notifications in Versions 1.2.0 and Higher.
-
For versions 1.0.1 and lower, see Webhook Notifications in Versions 1.0.1 and Lower.
For an overview of the latest changes, refer to the API Changelog.
Setting the API Version
You need to update your webhook configuration if you want to use the latest API version. Simply edit your webhook endpoint and choose the latest version from the Webhook Version list.Creating Webhooks
To begin receiving Webhook notifications, do the following:
- Login to the PaymentsOS Control Center and open the Webhooks configuration page (Accounts > Webhooks).
- Select the test or live relevant environment.
- Enter an endpoint (the HTTPS URL), that Webhooks notifications should be sent to.
- Select the events to track from the Payment Event Alerts list.
- Select the business units to associate with the endpoint from the Associated Business Units list.
Maximum Number of Webhooks
For each business unit in the live environment, you can configure maximum 10 webhooks per event. In the test environment, this is limited to 5 webhooks per event.Receiving Webhook Notifications
PaymentsOS will send Webhook notifications via HTTP POST requests to the URL endpoints that you defined.
If the system doesn’t receive a “Request received successfully” status code response (2xx HTTP), then it will continue resending the Webhook notification for 24 hours, using an exponential retry basis.
Modifying an endpoint while a successful response is pending
If you modify the endpoint while PaymentsOS has not yet received a Request received successfully status code, PaymentsOS will still resend the Webhook notification to the previous endpoint URL. The new endpoint will only take effect for subsequent Webhook events.Manually Resending the Latest Webhook Event
There may be cases in which you’d want to manually resend the latest webhook event for a specific transaction. Say, for instance, there was a technical glitch in your listener. You then fix that glitch, after which you manually re-send the latest webhook event to get updated information about the status of the transaction.
Understanding the latest webhook event
Say you’ve configured three webhook events: one for Create Payment, one for Create Authorization and one for Create Capture. A shopper initiates a payment, for which you invoke the Create Authorization Request. Given your webhook configuration, PaymentsOS will send a webhook event right after the Create Authorization Request has been invoked. If at this stage you were to manually trigger the resending of a webhook event, PaymentsOS will resend the webhook event for the Create Authorization Request (since this was the latest webhook event that was sent).To resend a webhook event, simply invoke through the Resend the Latest Webhook Event API request. In the request body, pass a resource_type
with a value of PAYMENT
and a resource_ids
array with the identifier of the payment request (represented by the Payment Object) for which the latest webhook event should be sent. Just beware that even though resource_ids
is an array, you can only pass a single identifier in the array (we’ll be adding the option for passing multiple identifiers in later versions). Here’s a sample request body:
{
"resource_type": "PAYMENT",
"resource_ids": ["0047c4ef-f658-4e6d-a040-5882e2285f34"]
}
Webhook Notifications in Versions 1.2.0 and Higher
This section explains the structure of Webhook notifications returned in Webhook API versions 1.2.0 and higher. The topic also outlines the steps you need to follow if you want to validate the integrity of the Webhook data you received.
Webhook Header
A Webhook header includes the following fields.
Header Field | Description |
---|---|
signature string | This is a Hash-256 (SHA-256) of specific fields contained in the Webhook response. You can use this hash code to validate the integrity of the Webhook data you received. For more information, see Validating the Integrity of the Webhook Data. |
event-type string | The type of resource that triggered the event. For example, payment.authorization.create |
version string | Version of the Webhooks configuration. |
x-payments-os-env string | PaymentsOS environment header, ‘live’ or ‘test’. |
x-zooz-request-id string | The ID of the original request that triggered the webhook event. |
Here’s an example of a Webhook event header:
x-zooz-request-id: 4a86867f-f2bd-4860-a6c8-10a5ab890f03
version: 1.2.0
x-payments-os-env: test
event-type: payment.charge.update
signature: sig1=3bc4d08447e55a704325db8748582eaefd5ebed0157ec1e587cae4df8f5cd74e
Webhook Body
A Webhook body includes the following fields.
Attribute Name | Description |
---|---|
id string | The Webhook id. This id is unique per Webhook and can be used to validate that the request is unique (idempotency validation). For more information, see Handling Multiple Webhook Requests for the Same Event. |
created timestamp | The date and time the event was created. |
payment_id UUID | The payment id. |
account_id UUID | The merchant account related to the event. |
app_id string | The Business Unit related to the event. |
data object | The full transaction resource that initiated the event. |
Here are examples of Webhook event bodies, for common webhook event types:
{
"id": "13344450-77e9-45b6-9bbe-88fff8c451e5-2018-10-03T04:58:35.385Z-83233f6e-767f-4f55-9d8f-448019e90fbf",
"created": "2018-10-03T04:58:35.385Z",
"account_id": "961c3ded-d539-4b5f-8950-3de93570e988",
"app_id": "com.zooz.docapp",
"payment_id": "13344450-77e9-45b6-9bbe-88fff8c451e5",
"data": {
"id": "cb615c8f-319d-4349-a276-f4ecc7d770d3",
"created": "1538542712789",
"payment_method": {
"type": "tokenized",
"token": "9c7bc2c6-47fe-4d2a-ac20-23847574ae3e",
"token_type": "credit_card",
"holder_name": "John Mark",
"expiration_date": "10/2029",
"last_4_digits": "0077",
"pass_luhn_validation": true,
"bin_number": "400000",
"vendor": "VISA",
"issuer": "",
"card_type": "CREDIT",
"level": "",
"country_code": "USA",
"created": "1538542703826",
"billing_address": {
"country": "USA",
"state": "NY",
"city": "NYC",
"line1": "fifth avenue 10th"
}
},
"result": {
"status": "Succeed"
},
"provider_data": {
"provider_name": "MockProcessor",
"response_code": "0",
"description": "Captured.",
"raw_response": "{\"OID\":\"13344450-77e9-45b6-9bbe-88fff8c451e5\",\"AUTH_CODE\":\"13344\",\"RETURN_MESSAGE\":\"Captured.\",\"TRANSID\":\"187_961c3ded-d539-4b5f-8950-3de93570e988_Charge-TargetPolicy\",\"STATUS\":\"SUCCESS\",\"AMOUNT\":\"40.97\",\"DATE\":\"1538542715367\",\"RETURN_CODE\":\"0\",\"CURRENCY\":\"EUR\"}",
"authorization_code": "13344",
"transaction_id": "187_961c3ded-d539-4b5f-8950-3de93570e988_Charge-TargetPolicy",
"external_id": "13344450-77e9-45b6-9bbe-88fff8c451e5"
},
"amount": 4097
}
}
{
"id": "66ebc442-bf8f-42c6-886b-faee8323aad2-2018-10-03T05:14:17.196Z-83233f6e-767f-4f55-9d8f-448019e90fbf",
"created": "2018-10-03T05:14:17.196Z",
"account_id": "961c3ded-d539-4b5f-8950-3de93570e988",
"app_id": "com.zooz.docapp",
"payment_id": "66ebc442-bf8f-42c6-886b-faee8323aad2",
"data": {
"id": "974cfd3e-a461-4efd-804c-9b39104f56f9",
"created": "1538543654532",
"result": {
"status": "Succeed"
},
"amount": 2000,
"provider_data": {
"provider_name": "MockProcessor",
"response_code": "0",
"description": "Captured.",
"raw_response": "{\"OID\":\"66ebc442-bf8f-42c6-886b-faee8323aad2\",\"AUTH_CODE\":\"66ebc\",\"RETURN_MESSAGE\":\"Captured.\",\"TRANSID\":\"988_961c3ded-d539-4b5f-8950-3de93570e988_Capture\",\"STATUS\":\"SUCCESS\",\"AMOUNT\":\"20\",\"DATE\":\"1538543657182\",\"RETURN_CODE\":\"0\",\"CURRENCY\":\"USD\"}",
"authorization_code": "66ebc",
"transaction_id": "988_961c3ded-d539-4b5f-8950-3de93570e988_Capture",
"external_id": "66ebc442-bf8f-42c6-886b-faee8323aad2"
}
}
}
{
"id": "a3006729-09d7-41e3-9c2f-8fa0cd9d6fdc-2018-10-03T05:22:45.610Z-83233f6e-767f-4f55-9d8f-448019e90fbf",
"created": "2018-10-03T05:22:45.610Z",
"account_id": "961c3ded-d539-4b5f-8950-3de93570e988",
"app_id": "com.zooz.docapp",
"payment_id": "a3006729-09d7-41e3-9c2f-8fa0cd9d6fdc",
"data": {
"id": "df6cfb45-5e03-4815-b777-3124f7a86a43",
"created": "1538544162818",
"result": {
"status": "Succeed"
},
"provider_data": {
"provider_name": "MockProcessor",
"response_code": "0",
"description": "Refunded.",
"raw_response": "{\"OID\":\"a3006729-09d7-41e3-9c2f-8fa0cd9d6fdc\",\"AUTH_CODE\":\"a3006\",\"RETURN_MESSAGE\":\"Refunded.\",\"TRANSID\":\"67_961c3ded-d539-4b5f-8950-3de93570e988_Refund\",\"STATUS\":\"SUCCESS\",\"AMOUNT\":\"20\",\"DATE\":\"1538544165606\",\"RETURN_CODE\":\"0\",\"CURRENCY\":\"USD\"}",
"authorization_code": "a3006",
"transaction_id": "67_961c3ded-d539-4b5f-8950-3de93570e988_Refund",
"external_id": "a3006729-09d7-41e3-9c2f-8fa0cd9d6fdc"
},
"amount": 2000
}
}
{
{
"id": "2eea735d-3c37-4f30-ab54-7ccea9a3b1bd-2018-10-03T05:26:03.793Z-83233f6e-767f-4f55-9d8f-448019e90fbf",
"created": "2018-10-03T05:26:03.793Z",
"account_id": "961c3ded-d539-4b5f-8950-3de93570e988",
"app_id": "com.zooz.docapp",
"payment_id": "2eea735d-3c37-4f30-ab54-7ccea9a3b1bd",
"data": {
"id": "7b746d9d-073a-4eb0-a067-b14d952211e2",
"created": "1538544360751",
"result": {
"status": "Succeed"
},
"provider_data": {
"provider_name": "MockProcessor",
"response_code": "0",
"description": "Canceled.",
"raw_response": "{\"OID\":\"2eea735d-3c37-4f30-ab54-7ccea9a3b1bd\",\"AUTH_CODE\":\"2eea7\",\"RETURN_MESSAGE\":\"Canceled.\",\"TRANSID\":\"322_961c3ded-d539-4b5f-8950-3de93570e988_Void\",\"STATUS\":\"SUCCESS\",\"AMOUNT\":\"20\",\"DATE\":\"1538544363785\",\"RETURN_CODE\":\"0\",\"CURRENCY\":\"USD\"}",
"authorization_code": "2eea7",
"transaction_id": "322_961c3ded-d539-4b5f-8950-3de93570e988_Void",
"external_id": "2eea735d-3c37-4f30-ab54-7ccea9a3b1bd"
}
}
}
Understanding the Structure of the body.data
Object
The structure of the data
object is the same as the structure you receive in the response of a GET request made to the specific resource endpoint. For instance, the structure of the data
object returned in a payment.charge.update
event will be the same as the response body of a GET Charge request. Likewise, the data
object returned in a payment.payment.update
event will be the same as the response body of a GET Payment request.
Use the event-type
value (in the Webhook event header) to ensure you parse the correct data
object structure. Refer to the API reference for a sample response.
Excluding Fields from the body.data
Object
The data
object returned in the webhook body includes the full transaction resource that triggered the webhook event. There are cases, however, where you may not want to receive all data included in a transaction resource. This could be for architectural reasons (to limit the amount of data you receive) or based on security considerations (you may not be allowed to expose all data), just to name a couple. Whatever the case may be, you can easily exclude specific resource data by ‘blacklisting’ the resource fields you don’t want to receive in the webhook event. To do so, edit your Webhooks configuration and click Apply Filter next to the payment event for which you want to exclude the resource fields.
Validating the Integrity of the Webhook Data
Note
This functionality is available in Webhook API version 1.2.0 and higher.If you’re worried about the integrity of the Webhook data you received (or want to be reassured that the data was sent to you by PaymentsOS), you can get assurance that your data hasn’t been monkeyed with. You just have to compare two hash values:
-
The hash value returned in the
signature
field of the Webhook header. -
A HMAC-SHA256 hash value you generate using part of the fields returned in the Webhook event, as well as your app’s private key.
Generating the HMAC-SHA256 hash value is easy. First concatenate the following fields from the Webhook data into a single string. All fields are returned in the Webhook body, with the exception of the event-type
which is returned in the header. Just make sure to add the fields exactly in the order listed and separate each field in the string with a comma. If the field doesn’t exist, replace it with an empty string.
-
event-type
(this field is returned in the Webhook header) -
id
-
account_id
-
payment_id
-
created
-
app_id
-
data.id
-
data.result.status
-
data.result.category
-
data.result.sub_category
-
data.provider_data.response_code
-
data.reconciliation_id
-
data.amount
-
data.currency
Here’s an example of a concatenated string. Notice that empty strings (in the event of a missing field) have been replaced with a ‘,’ (comma). If the missing field is the last one in the sequence, you should include the comma as well.
payment.charge.update,8d3f9e6a-d89b-48bd-9d68-07e1bb582687-2018-09-05T06:44:35.484Z-83233f6e-767f-4f55-9d8f-448019e90fbf,961c3ded-d539-4b5f-8950-3de93570e988,8d3f9e6a-d89b-48bd-9d68-07e1bb582687,2018-09-05T06:44:35.484Z,com.zooz.docapp,557a4e32-d2e9-495a-9a0b-f2a18c39d91b,Succeed,,,0,,4097,
Now use the string to generate the HMAC-SHA256 hash value, using your app’s private key. If the value matches the signature
value in the Webhook header, you can rest assured that the data has not been tempered with. For a quick test, you can use an online HMAC Generator / Tester Tool.
Handling Multiple Webhook Requests for the Same Event
There are cases, such as connectivity issues, that may cause the same request to be sent multiple times for the same event. If you receive the same request multiple times, you can simply ignore the duplicates. Bear in mind that you must still send us a 2xx (success) response so that we will stop resending the webhook event.
You can use the Webhook id (returned in the Webhook body) to validate that a request is unique (idempotency validation) and identify any duplicates.
Webhook Notifications in Versions 1.0.1 and Lower
This section explains the structure of Webhook notifications returned in Webhook API version 1.0.1.
Webhook Header
A Webhook header includes the following fields.
Header Name | Description |
---|---|
digest string | This is a Hash-256 (SHA-256) of the body. |
version string | Version of the Webhooks configuration. |
x-payments-os-env string | PaymentsOS environment header, ‘live’ or ‘test’. |
x-zooz-request-id string | The ID of the original request that triggered the webhook event. |
Webhook Body
A Webhook body includes the following fields.
Attribute Name | Description |
---|---|
event_type string | The type of resource that triggered event. For example, payment.authorization.create |
created timestamp | The date and time the event was created. |
account_id UUID | The merchant account related to the event. |
app_id string | The Business Unit related to the event. |
resource object | The resource object related to the event. |
⇒ id UUID | The payment id |
⇒ action_id UUID | The id of the transaction (such as the refund id, or the charge id.) |
⇒ href UUID | The href link to the associated resource. |
⇒ order_id string | Identifier of the order. |
Here’s an example of a Webhook event body:
{
"event_type": "payment.charge.create",
"created": "2018-02-06T10:10:05.466Z",
"account_id": "961c3ded-d539-4b5f-8950-3de93570e988",
"app-id": "com.zooz.docapp",
"resource": {
"id": "633f5479-7eea-496f-bdc1-629b71d3062a",
"action_id": "adb3e112-8f35-46f5-8ed1-66dab4f9438c",
"href": "https://api.paymentsos.com/payments/633f5479-7eea-496f-bdc1-629b71d3062a/charges/adb3e112-8f35-46f5-8ed1-66dab4f9438c",
"order_id": "myappid"
}
}
Retrieving the Transaction Status
When receiving the webhook, retrieve the status of the transaction, including any additional details, by invoking a GET
request on the resource.href
resource. Building on the example above, here’s how you can retrieve the status of the charge:
GET https://api.paymentsos.com/payments/6ec2cd4d-9ffb-4ab3-a35a-870f7ec8a803/charges/fe25daca-1149-42e1-8576-d7b52ca9ded4
Where to find the status
Thestatus
is returned in the result
object of the GET
response call.