Webhooks
NEXI Paygate REST API supports Webhooks to notify your system about the final result of the payment for hosted integration types. Webhooks enable near real-time update without the need to poll for payment status.
Overview
You can specify your Webhook URL in the API request by passing: urls.webhook
Create checkout session
Create payment
When the payment is finalized, NEXI sends an HTTPS POST request to your configured endpoint.
Two Webhook types are available:
|
Type |
Description |
Authenthication |
|---|---|---|
|
Basic Webhook |
Sends only the |
Not signed (no HMAC required) |
|
Enhanced Webhook |
Sends full payment information in JSON format (see schema below). |
Signed with HMAC (see Security & verification) |
1. Basic Webhook
Example payload
{
"payId": "78f5adccfe8640e5a549613389ff33we"
}
Description
The payload contains only the unique Computop payId. You can use this value to call the Retrieve payment details by payment ID endpoint to obtain full transaction details.
Since no sensitive data is transmitted, no HMAC signature is used for this Webhook type.
2. Enhanced Webhook
The Enhanced Webhook includes detailed transaction data in the payload and is signed with an HMAC signature to ensure authenticity and integrity.
Example payload
{
"payId": "78f5adccfe8640e5a549613389ff33we",
"transId": "txn_7890",
"refNr": "45687",
"status": "OK",
"responseCode": "00000000",
"responseDescription": "success",
"amount": {
"value": 10000,
"currency": "EUR"
},
"paymentMethods": [
{
"type": "CARD"
}
],
"creationDate": "2025-09-23T13:20:30Z"
}
JSON schema
View JSON schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "PaymentResponse",
"type": "object",
"properties": {
"payId": {
"type": "string",
"description": "A unique identifier assigned by Computop Paygate to the payment."
},
"transId": {
"type": "string",
"description": "Transaction ID created in your system; should be unique per payment."
},
"refNr": {
"type": ["string", "null"],
"description": "Your reference number for the specific operation; used for reconciliation."
},
"status": {
"type": "string",
"description": "Status of the transaction."
},
"responseCode": {
"type": "string",
"description": "Response code of the transaction."
},
"responseDescription": {
"type": "string",
"description": "Response description associated with the response code."
},
"amount": {
"type": "object",
"properties": {
"value": {
"type": "number",
"description": "Total order amount in the smallest currency unit."
},
"currency": {
"type": "string",
"pattern": "^[A-Z]{3}$",
"description": "3-character ISO currency code."
}
},
"required": ["value", "currency"]
},
"paymentMethods": {
"type": "array",
"items": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"APPLEPAY","BANCONTACT","BOLETO","CARD","DIRECTDEBIT","EASYCOLLECT",
"FLOAPAY","GOOGLEPAY","IDEAL","INSTANEA","KLARNA","MOBILEPAY",
"MULTIBANCO","MYBANK","PAYPAL","PAYU","PFCONNECT","RATEPAY",
"RIVERTY","SWISH","WERO"
],
"description": "Payment method used for this transaction."
}
},
"required": ["type"]
},
"description": "Selected payment method(s)."
},
"creationDate": {
"type": "string",
"format": "date-time",
"description": "Date and time when the order was created."
}
},
"required": [
"payId",
"transId",
"status",
"responseCode",
"responseDescription",
"amount",
"paymentMethods",
"creationDate"
],
"additionalProperties": false
}
Security & verification
Enhanced Webhooks are authenticated using HMAC-SHA256 signatures to ensure that notifications originate from NEXI and have not been tampered with.
Signature headers
|
Header |
Description |
|---|---|
|
X-Paygate-Signature-Version |
Version of the signature format (currently |
|
X-Paygate-Timestamp |
Unix epoch timestamp (seconds since 1970-01-01T00:00:00Z, UTC) |
|
X-Paygate-Signature |
Computed signature in the format |
Signature generation (NEXI side)
signed_payload = timestamp + "." + raw_json_body
signature = HMAC_SHA256(secret, signed_payload)
-
secret– HMAC key -
The computed
signatureis hex-encoded and placed in the header as:
X-Paygate-Signature: v1=<hex-hmac>
Merchant verification (Your side)
To verify the authenticity of the Webhook:
-
Extract the following from the HTTP headers:
-
X-Paygate-Timestamp -
X-Paygate-Signature
-
-
Obtain the raw JSON body (exact bytes received).
-
Recompute the HMAC locally:
signed_payload = timestamp + "." + raw_body
expected_signature = HMAC_SHA256(secret, signed_payload) -
Compare the computed value with the received signature using a constant-time comparison function.
-
Reject the Webhook if:
-
Signatures do not match, or
-
Timestamp differs by more than ±5 minutes from your system clock.
-
Example verification (Pseudocode)
import hmac, hashlib, time
def verify_signature(secret, body, timestamp, header_signature):
signed_payload = f"{timestamp}.{body}".encode("utf-8")
computed_hmac = hmac.new(secret.encode(), signed_payload, hashlib.sha256).hexdigest()
return hmac.compare_digest(f"v1={computed_hmac}", header_signature)
Timestamp format
-
Unix epoch (integer, seconds since 1970-01-01T00:00:00Z)
-
UTC-based (no time zone offset)
Example:
X-Paygate-Timestamp: 1718530883
To generate the current Unix timestamp:
long unixTimeSeconds = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
Best practices
-
Always use HTTPS for Webhook endpoints
-
Verify HMAC signatures before processing any data
-
Validate payloads against the provided JSON schema
-
Implement idempotency: process each
payIdonly once -
Log the full headers and payload for troubleshooting
-
Respond with HTTP 2xx (e.g.,
200 OK) to acknowledge successful receipt.
Response expectations
|
Response |
Meaning |
|---|---|
|
|
Successfully received and processed by your system |
|
|
Delivery will be retried according to NEXI retry policy |
Summary
|
Webhook type |
Payload |
Authentication |
Use case |
|---|---|---|---|
|
Basic |
|
None |
Merchant retrieves full details via API |
|
Enhanced |
Full payment JSON |
HMAC (SHA-256) |
Real-time status updates with verified integrity |