Overview
Webhooks are automated server-to-server notifications Nuvei can send when a relevant transaction or event occurs. After the merchant sends a transaction request to Nuvei, Nuvei communicates with the customer’s bank or other funding source to transfer the funds from the customer’s account to the merchant’s account. When Nuvei receives a response from the bank or other funding source, Nuvei notifies the merchant of the result of the transaction via a webhook. Nuvei sends webhooks directly to the merchant’s web server, providing reliable and secure server-to-server communication between the merchant and Nuvei. The webhooks verify that Nuvei completed the transaction.
The sections below describe how to integrate webhooks and how to handle webhooks when using Nuvei’s REST API 2.0 or Web SDK 2.0 integration methods.
For other Nuvei integration methods, webhooks are referred to as Direct Merchant Notifications (DMNs).
Integrating Webhooks
When a merchant has integrated Nuvei’s webhooks, the Nuvei server sends an POST request that includes the relevant parameters to the merchant web server:
- HTTPS POST – Body of the request includes parameter name-value pairs.
To integrate Nuvei’s webhooks, the merchant provides the URL or IP address of the webhook listener on the merchant’s web server. The listener is usually a small module or application that constantly waits for incoming HTTPS requests from Nuvei’s server. When using Nuvei REST API 2.0, Nuvei recommends specifying the relevant webhook URL parameter in the relevant request. For example, in /payments
requests, Nuvei recommends including urlDetails.webhookUrl
.
Additional Integration Steps
Nuvei can send many webhooks at one time, depending on how many transactions and/or retries of failed attempts are being relayed simultaneously. Some firewalls might recognize these as DDoS attacks and block Nuvei’s servers; for example, Incapsula. Nuvei recommends that the merchant ensures certain IP address ranges are whitelisted with local and web firewalls.
Also, Nuvei recommends that merchants use merchantTransactionId
in the webhook for mapping webhooks to transactions.
Webhooks for APM Transactions
When an APM transaction occurs, Nuvei can send a webhook that includes the result of the transaction (result.status
). For APM transactions, the possible Status
values are:
- approved: The APM provider processed and approved the transaction.
- declined: The APM provider processed and declined the transaction.
- pending: The APM provider is processing the transaction.
- update: Indicates an update to the transaction’s status. Relevant only for certain APMs that handle North American bank transfers. For details, see the relevant APM guide. REST 2.0 currently supports the Bank Transfer (ACH) APM.
Depending on the APM, transactions can be processed synchronously or asynchronously. Asynchronous processing can involve time delays ranging from a few seconds to several days. After Nuvei receives the final result (approved or declined) from the APM or APM provider, Nuvei sends the merchant an additional webhook containing the same transaction data as the previous webhook and the final result.status
of the transaction.
Example Payment Webhooks (JSON)
Example Payment Webhook with status
=pending (APM)
{ "authorizingEntityId": "<your authorizingEntityId>", "processingEntityId": "<your processingEntityId>", "merchantTransactionId": "<ID of the transaction in the merchant system>", "buyerId": "JohnSmith123", "version": "2.0", "amount": 10.5, "currency": "USD", "transactionType": "Auth", "result": { "status": "pending" }, "timeStamp": "2024-08-28T12:11:47.337302438Z", "paymentOption": { "alternativePaymentMethod": { "name": "ACH", "data": { "accountNumber": "111111111", "routingNumber": "123456780" }, "merchantReference": "12391284AF87C7D2", "paymentTokenId": "c19ec945499a4641977ef5be6deb74df" } } }
Example Payment Webhook with status
=updated (APM)
{ "authorizingEntityId": "<your authorizingEntityId>", "processingEntityId": "<your processingEntityId>", "merchantTransactionId": "<ID of the transaction in the merchant system>", "buyerId": "JohnSmith123", "version": "2.0", "amount": 10.5, "currency": "USD", "transactionType": "Auth", "result": { "status": "updated" }, "timeStamp": "2024-08-28T12:11:47.337302438Z", "paymentOption": { "alternativePaymentMethod": { "name": "ACH", "data": { "accountNumber": "111111111", "routingNumber": "123456780" }, "merchantReference": "12391284AF87C7D2", "paymentTokenId": "c19ec945499a4641977ef5be6deb74df" } } }
Example Payment Webhook with status
=approved (APM)
{ "authorizingEntityId": "<your authorizingEntityId>", "processingEntityId": "<your processingEntityId>", "merchantTransactionId": "<ID of the transaction in the merchant system>", "buyerId": "JohnSmith123", "version": "2.0", "amount": 10.5, "currency": "USD", "transactionType": "Auth", "result": { "status": "approved" }, "timeStamp": "2024-08-28T12:11:47.337302438Z", "paymentOption": { "alternativePaymentMethod": { "name": "ACH", "data": { "accountNumber": "111111111", "routingNumber": "123456780" }, "merchantReference": "12391284AF87C7D2", "paymentTokenId": "c19ec945499a4641977ef5be6deb74df" } } }
Webhook Parameters
Merchants can receive webhooks in one of the following formats:
- JSON – POST requests
- XML
Parameter POST JSON/ GET Query String (if different) | Description |
---|---|
transactionId | A unique 64-bit number that identifies the fiscal transaction in the Nuvei payment gateway. |
externalTransactionId | A unique ID generated by Nuvei that represents the APM transaction. |
currency | Currency of the transaction |
transactionType | The value of this parameter shows the type of transaction. Type - Sale, Auth, PreAuth. |
result.status | The Gateway transaction status. Possible values that can return: approved, authorizedOnly, declined, error, pending, redirect, challenge, fingerprint, authenticated, authenticationNotSupported |
result.error.code | Error code returned from REST API or Nuvei GW |
result.error.reason | Error reason returned from REST API or Nuvei GW |
authCode | The authorization code of the transaction |
cvv2Code | CVV2 (card verification value) response. Possible values: M – CVV2 Match N – CVV2 No Match P – Not Processed U – Issuer is not certified and/or has not provided Visa with the encryption keys. S – CVV2 processor is unavailable. |
avsCode | The AVS (address verification) response. The following values may be returned: A – The street address matches, but the ZIP code does not. W – Whole 9-digit ZIP code matches, but the street address does not. Y – Both the 5-digit ZIP code and the street address match. X – An exact match of both the 9-digit ZIP code and the street address. Z – Only the 5-digit ZIP code matches, the street code does not. U – Issuer Unavailable S – Not Supported R – Retry B – Not Authorized (declined) N – Both street address and ZIP code do not match. |
providerResponseDetails.code | The code returned by the provider in cases of error or decline status |
providerResponseDetails.reason | The reason returned by the provider in cases of error or decline status |
partialApproval.requestedAmount | For a partial approval transaction, represents the amount requested. It can be greater than the amount that was able to be processed (totalAmount). |
partialApproval.requestedCurrency | For a partial approval transaction, represent the currency of the amount requested. It should be the same as the currency of the amount processed (currency). |
paymentOption.card.cardHolderName | Name on the card of the customer that processes a transaction, if supplied. |
paymentOption.card.maskedCardNumber | Masked card number of the user that processes a transaction, if supplied. The parameter becomes mandatory if the payment method is a credit card or debit card. If another payment method is used, then the parameter won't return. |
paymentOption.card.bin | The first six digits from the credit card number for identifying the processing bank. The rest of the number is not displayed. |
paymentOption.card.last4Digits | The last four digits of the credit card number |
paymentOption.card.expirationMonth | Expiration month of the card used for this transaction, if supplied. The parameter becomes mandatory if the payment method is credit card. If another payment method is used, then the parameter won't return. |
paymentOption.card.expirationYear | Expiration year of the card used for this transaction, if supplied. The field becomes mandatory if the payment method is credit card. If another payment method is used, then the parameter won't return. |
paymentOption.card.acquirerId | Acquiring bank unique ID. The value 0 represents an invalid bank code. |
paymentOption.card.cardType | The type of card used in the transaction. Possible values: credit or debit. |
paymentOption.card.cardBrand | The card company of the input card |
paymentOption.card.paymentAccountReference | A unique identifier associated with a specific cardholder PAN, which can be used in place of sensitive consumer identification fields. If the PaymentAccountReference value is returned in the response (depending on the card scheme decision), then this value is also returned to the Merchant. |
paymentOption.card.paymentTokenId | Each time a customer uses a payment method, Nuvei assigns a unique ID to that payment method. The next time the customer uses a payment method in which Nuvei has already assigned an ID, the ID is returned as the value of this parameter. When a new payment method is used, the value of this parameter will change. |
paymentOption.card.merchantReference | The token name in the merchant system |
paymentOption.card.threeD.fingerprintUrl | The 3DS fingerprint URL. It is required to redirect to it in case of 3DS and send the fingerprintPayload as parameter. |
paymentOption.card.threeD.fingerprintPayload | Base 64 encoded string containing the transaction Id etc. that send as parameter during POST to threeSD fingerprintUrl |
paymentOption.card.threeD.v2Supported | The 3DS support indication. Possible values: FALSE (not supported) or TRUE (supported). |
paymentOption.card.threeD.isExemptionRequestInAuthentication | Indicates if an exemption was requested during authorization. |
paymentOption.card.threeD.acsUrl | URL/endpoint used to redirect the customer to the card issuer/bank 3DS verification page. |
paymentOption.card.threeD.cReq | The base 64 encoded cReq relevant for 3DS. acsUrl will be sent as well as a separate field. |
paymentOption.card.threeD.acsTransId | |
paymentOption.card.threeD.version | The 3DS version. |
paymentOption.card.threeD.serverTransId | |
paymentOption.card.threeD.eci | An Electronic Commerce Indicator (ECI) value is the result of a 3DS authentication request, returned by a Directory Server ("issuer ACS") (namely Visa, Mastercard, JCB, and American Express). Possible ECI values: Visa: 5 – The cardholder was successfully authenticated. 6 – The issuer or cardholder does not participate in a 3DS program. 7 – Payment authentication was not performed. Mastercard: 1 – The issuer or cardholder does not participate in a 3DS program. 2 – The cardholder was successfully authenticated. 6 – Payment authentication was not performed. 7 – The cardholder was successfully authenticated for the initial MIT. |
paymentOption.card.threeD.cavv | A cryptogram created by the issuer that serve as a proof that the merchant is entitled tor this authentication. |
paymentOption.card.threeD.whiteListStatus | whiteListStatus – from final GW response to Sale TRX. This field is relevant only for a 3DS deposit flow. |
paymentOption.card.threeD.acsChallengeMandate | The 3DS challenge required indication. Possible values: N (not required) or Y (required). |
paymentOption.card.threeD.authenticationType | The type of authentication performed during the 3DS challenge. If the merchant wants to react differently for each authentication type, it is possible per the value returned. Possible values: 01 – Static 02 – Dynamic 03 – OOB 04 – Decoupled 05–79 – Reserved for EMVCo future use, values invalid until defined by EMVCo 80–99 – Reserved for DS use |
paymentOption.card.threeD.authenticationResult | Indicates whether a transaction qualifies as an authenticated transaction or account verification. Possible values: Y = Authentication Verification Successful. N = Not Authenticated /Account Not Verified; Transaction denied. U = Authentication/ Account Verification Could Not Be Performed; Technical or other problem, as indicated in ARes or RReq. A = Attempts Processing Performed; Not Authenticated/Verified, but a proof of attempted authentication/verification is provided. C = Challenge Required; Additional authentication is required using the CReq/CRes. D = Challenge Required; Decoupled Authentication confirmed. R = Authentication/ Account Verification Rejected; Issuer is rejecting" |
paymentOption.card.threeD.flow | The 3DS flow required by the issuer. Possible values: challenge, frictionless, exemption |
paymentOption.card.threeD.reasonId | reason id |
paymentOption.card.threeD.reason | If the attempt failed, this parameter is returned by the banks to indicate the reason why the transaction was not passed as full 3D. Returned in the end of the 3DS after successful frictionless. |
paymentOption.card.threeD.cardholderInfoText | The text provided by the ACS/Issuer to the cardholder during a frictionless transaction that was not authenticated by the ACS/Issuer. For example: “Additional authentication is needed for this transaction. Please contact [Issuer Name] at xxx-xxx-xxxx.” If this parameter is populated, the merchant must display the information to the cardholder. |
paymentOption.card.threeD.challengePreferenceReason | This value is returned following a 3DS challenge and describes the reason for challenge. |
paymentOption.card.threeD.acquirerDecision | The acquirer’s request from the merchant to perform a certain flow. Possible values: ChallengeRequest, ExemptionRequest |
paymentOption.card.threeD.decisionReason | The description of the acquirer’s decision. |
paymentOption.card.threeD.challengeCancelReason | Reason description for a canceled 3DS authorization as received from the issuer. |
paymentOption.card.threeD.challengeCancelReasonId | Reason ID for a canceled 3DS authorization as received from the issuer. |
paymentOption.card.threeD.isLiabilityOnIssuer | Indicates if there is a 3DS liability shift. |
paymentOption.alternativePaymentMethod.name | The APM name provided in the request |
paymentOption.alternativePaymentMethod.data.xxxxx | Key pair value provided in the request by the merchant when doing a payment with APM. For example, ACH account number paymentOption.alternativePaymentMethod.data.accountNumber |
paymentOption.alternativePaymentMethod.merchantReference | The token name in the merchant system |
paymentOption.alternativePaymentMethod.paymentTokenId | Each time a customer uses a payment method, Nuvei assigns a unique ID to that payment method. The next time the customer uses a payment method in which Nuvei has already assigned an ID, the ID is returned as the value of this parameter. When a new payment method is used, the value of this parameter will change. |
paymentOption.eWallet.provider | The E-wallet provider. For example, Apple Pay. |
paymentOption.eWallet.eciIndicator | This is provided by the E-wallet provider in cases 3DS was performed during tokenization of the card in the end user's device. |
paymentOption.eWallet.expirationMonth | Expiration month of the card used for this transaction, if supplied. The parameter becomes mandatory if the payment method is credit card. |
paymentOption.eWallet.expirationYear | Expiration year of the card used for this transaction, if supplied. The field becomes mandatory if the payment method is credit card. |
paymentOption.eWallet.cardHolderName | Name on the card of the customer that processes a transaction, if supplied. |
paymentOption.eWallet.maskedCardNumber | Masked card number of the user that processes a transaction, if supplied. The parameter becomes mandatory if the payment method is a credit card or debit card. If another payment method is used, then an empty string is returned. |
paymentOption.eWallet.bin | The first six digits from the credit card number for identifying the processing bank. The rest of the number is not displayed. |
paymentOption.eWallet.last4Digits | Last four digits of the credit card number |
paymentOption.eWallet.cardType | The type of card used in the transaction. Possible values: credit or debit. |
paymentOption.eWallet.cardBrand | The card company of the input card |
paymentOption.eWallet.acquirerId | Acquiring bank unique ID. The value 0 represents an invalid bank code. |
Message Authentication
Message authentication determines if a message originates from Nuvei and if the message is changed by another party.
Message Authentication Flow
The merchant creates the shared secret and shares the shared secret with Nuvei for registration in the Nuvei system. In the event that the merchant does not provide the shared secret to Nuvei, Nuvei creates a unique secret key (similar to a password) and securely shares the secret key with the merchant. The secret key is used to create and verify the message signature.
2. Prepare the Message
- Convert the message content (full message body) to bytes using UTF-8.
- Hash the message content in bytes using SHA-256 to obtain a unique fingerprint of the message content. Referred to as ‘H’ in this document.
3. Add a Timestamp
Obtain the current time in Unix timestamp format (number of seconds since 1970). Referred to as ‘T’ in this document.
4. Create a Signature (Digest)
- Combine the hash (H) and the timestamp (T).
- To create a signature, use the shared secret key and the secure function HMAC-SHA256.
- Convert the result to Base64 format. The reformatted result is the ‘digest’. Referred to as ‘D’ in this document.
4. Send the Message with Headers
The message is sent to the merchant, with two special headers added:
- X-Authentication-Timestamp: [T]
- X-Authentication-Digest: [D]
5. Verify the Message (Performed by Merchant)
To verify the message, the merchant performs the following flow:
- Hash the message body.
- Use the received timestamp.
- Use the shared secret to calculate the digest.
- Compare the calculated digest with the digest in the header.
- If the digests match, the message is verified as authentic.
- If the digests do not match, the message may be fake or changed.
- Check the timestamp.
If the timestamp is determined to be too far in the past or future, the merchant rejects the message to prevent a replay attack.