Webhook Callback
After the customer completes the payment (or if the payment fails or is canceled) on the APM side, Exirom will send an HTTP callback (webhook) to the callbackUrl specified in your request. This callback is a server-to-server POST request containing a JSON body with the transaction’s final status and details.
It’s crucial to verify that this callback is authentic and hasn’t been tampered with. Each callback request includes an X-Checksum header, which is an HMAC-SHA256 signature of certain fields from the callback payload (such as accountId, amount, currency, transactionId). Using your secret key, you should recompute the expected checksum and compare it to the X-Checksum header value. This ensures the callback truly came from Exirom and the data wasn’t altered in transit. (See the Checksum Authentication Guide for the exact algorithm and fields used in the signature.)
Callback Data Fields (ApmPaymentTxInfoDto)
The JSON payload of the callback (referred to as ApmPaymentTxInfoDto) contains the following fields:
| Field | Type | Description |
|---|---|---|
transactionId | String | The unique transaction ID (as provided in the initial response). |
requestId | String | The original requestId you sent in the payment request. |
accountId | Long | Your merchant account ID associated with this transaction. |
transactionStatus | Enum (TxStatus) | Final status of the transaction (e.g., COMPLETED, DECLINED, EXPIRED, etc.). |
declineCode | Integer | If the transaction was declined, this is the error or decline code. Null if not applicable. |
declineSubReason | String | Additional details about why the transaction was declined, if available. |
orderCurrency | String | The currency of the original order (same as the currency you sent). |
processedCurrency | String | The currency in which the transaction was processed by the APM. (This could differ from orderCurrency if conversion occurred.) |
orderAmount | Double | The original order amount (as a numeric value) that was requested. |
processedAmount | Double | The amount that was processed in the processedCurrency. This might differ if currency conversion or fees applied. |
conversionRate | Double | The exchange rate used if any currency conversion took place (otherwise 1.0). |
apmRequestPayload | Object (ApmPayload) | The payment method payload from your original request (apmPayload), echoing what was sent. |
apmResponseData | Object (ApmResponseData) | The APM-specific response data, similar to what was returned in the initial response. It may include information like the redirect URL or transaction IDs from the provider. |
callbackUrl | String | The callback URL that this notification was sent to (i.e., the URL you provided in the request). |
successRedirectUrl | String | The success redirect URL that was provided in the original request (if any). |
failureRedirectUrl | String | The failure redirect URL provided in the original request (if any). |
billingDetails | Object (ApmBillingDetails) | The billing details from the original request (same data you sent). |
order | Object (Order) | The order information from the original request. |
createdAt | String | Timestamp when the transaction was created (in ISO date-time format). |
All the above information allows your system to reconcile the transaction. For instance, you can look up the transaction by requestId in your records, see the final transactionStatus, and update your order or payment records accordingly. The presence of your original order and billingDetails data can help link the callback to internal objects, but you should primarily use the requestId or transactionId for lookup.
Example Callback Data
Here is an example of a callback payload for the earlier example transaction, assuming the payment was completed successfully by the customer:
{
"transactionId": "tx-987654321",
"requestId": "req-123456789",
"accountId": 12345,
"transactionStatus": "COMPLETED",
"declineCode": null,
"declineSubReason": null,
"orderCurrency": "USD",
"processedCurrency": "USD",
"orderAmount": 100.0,
"processedAmount": 100.0,
"conversionRate": 1.0,
"apmRequestPayload": {
"paymentMethod": "ExPay", //All the payment methods are defined in the section below
"paymentType": "E_WALLET" //All the payment types are defined in the section below
// (Original request payload details would appear here)
},
"apmResponseData": {
"paymentMethod": "ExPay",
"paymentType": "E_WALLET",
"redirectUrl": "https://pay.expay.example.com/checkout/tx-987654321",
"providerTransactionId": "ExPay-tx-12345"
},
"callbackUrl": "https://merchant.example.com/callbacks/payments",
"billingDetails": {
// (Original billingDetails from the request)
},
"order": {
// (Original order details from the request)
},
"createdAt": "2023-01-01T12:00:00Z"
}
When your server receives this callback, it should:
- Verify the
X-Checksumheader (to ensure the data is authentic). - Check the
transactionStatusand update your system accordingly (e.g., mark the order as paid ifCOMPLETED, or handle a failure ifDECLINED). - (Optional) Respond with a 200 OK to acknowledge receipt. Exirom’s system will typically expect a successful response; otherwise, it might retry the callback.
Note: The paymentMethod and paymentType in
apmRequestPayload,apmResponseDataspecify the APM (ExPay e-wallet in this case).
Important – Amount Type and Checksum ValidationThe
amountfield uses different numeric representations depending on the message direction:
- Requests:
amountis sent as a string (e.g."200.00")- Callbacks:
amountis returned as a numeric value (e.g.200.0)Exirom processes amounts using native numeric types. As a result, decimal formatting (such as trailing zeros) is not preserved in callbacks.
Example:
- Request:
"200.00"- Callback:
200.0When validating or generating a callback checksum, always use the exact
amountvalue received in the callback payload.Do not reuse or reformat the original request amount, as this may cause checksum mismatches.
Webhook Callback Behavior - HPP, APM and Cards
Webhook Callback Method Identification
In some integrations, merchants use Hosted Payment Pages (HPP) instead of server-to-server (S2S) flows.
In these cases, Exirom does not know the final payment method at transaction creation time.
The end user selects the payment type later in the flow (Card or a specific APM).
As a result, the transaction lifecycle may involve different DTOs, and the final callback structure depends on the payment method chosen by the user.
To guarantee predictable webhook handling, Exirom explicitly identifies the resolved payment method in every callback.
Callback Identification Fields
Exirom provides explicit identifiers in webhook callbacks so merchants can determine which DTO to expect before parsing the body.
1) paymentMethod (Query Parameter)
paymentMethod (Query Parameter)All webhook callbacks are sent as HTTP POST requests.
Regardless of the original callbackUrl provided during transaction creation, Exirom appends the paymentMethod query parameter to the callback URL.
| Parameter | Possible Values | Description |
|---|---|---|
paymentMethod | card, apm | High-level payment method category |
2) apmType (Query Parameter and Payload Field)
apmType (Query Parameter and Payload Field)When paymentMethod=apm, Exirom appends apmType to the callback URL and includes it in the callback payload.
| Field / Parameter | Type | Description |
|---|---|---|
apmType | String | Specific APM selected by the user |
- Present only when
paymentMethod=apm - Value is taken from the Supported Payment Methods (
PaymentMethod) enum - Enables routing and parsing decisions before reading the callback body
Callback URL Examples
If the original callback URL is:
https://merchant.com/payment-statusExirom will invoke one of the following:
Card Payment
POST https://merchant.com/payment-status?paymentMethod=cardAPM Payment
POST https://merchant.com/payment-status?paymentMethod=apm&apmType={APM_METHOD}Example:
POST https://merchant.com/payment-status?paymentMethod=apm&apmType=UPI_QRParsing APM Callbacks (apmResponseData)
apmResponseData)When paymentMethod=apm, the callback payload contains:
| Field | Type | Description |
|---|---|---|
apmResponseData | ApmResponseData | Additional data specific to the APM and payment flow. This often contains the information needed to redirect the user or render an iframe. |
The structure of apmResponseData varies by apmType.
Merchants must use apmType to select the correct parser and flow handling logic.
Important Do not assumeapmResponseDatahas the same shape for all APMs. Always route parsing and UX behavior based onapmType.
Where to Find the Correct apmResponseData Schema
apmResponseData SchemaEach apmType has dedicated documentation describing:
- the expected
apmResponseDatafields - redirect vs iframe behavior
- any required follow-up actions (polling, SDK steps, confirmations)
- provider-specific notes and edge cases
Use the apmType value (from the callback URL or payload) to navigate to the relevant APM documentation page and implement the correct parsing and user experience flow.
Processing Guidance
- Read
paymentMethodfrom the callback URL to determine Card vs APM callback DTO - When
paymentMethod=apm, readapmTypeto determine which APM schema applies - Parse
apmResponseDataaccording to the dedicated docs for thatapmType - For HPP flows, rely on callback identifiers rather than the original request intent
Outcome A single webhook endpoint can reliably handle Card and all APM callbacks with deterministic parsing and flow control.
Updated about 1 month ago
