Breadcrumbs

REST API Webhooks

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 payId in the body. Merchant must query the Get payment details endpoint to retrieve full information. 

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 v1)

X-Paygate-Timestamp

Unix epoch timestamp (seconds since 1970-01-01T00:00:00Z, UTC)

X-Paygate-Signature

Computed signature in the format v1=<hex-hmac>. Supports multiple signatures (e.g. v1=<hmac1>,v2=<hmac2>) for key rotation.


Signature generation (NEXI side)

signed_payload = timestamp + "." + raw_json_body

signature = HMAC_SHA256(secret, signed_payload)

  • secret – HMAC key

  • The computed signature is 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:

  1. Extract the following from the HTTP headers:

    • X-Paygate-Timestamp

    • X-Paygate-Signature

  2. Obtain the raw JSON body (exact bytes received).

  3. Recompute the HMAC locally:
    signed_payload = timestamp + "." + raw_body
    expected_signature = HMAC_SHA256(secret, signed_payload)

  4. Compare the computed value with the received signature using a constant-time comparison function.

  5. 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 payId only 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

2xx

Successfully received and processed by your system

4xx / 5xx

Delivery will be retried according to NEXI retry policy


Summary

Webhook type

Payload

Authentication

Use case

Basic

{ "payId": "..." }

None

Merchant retrieves full details via API

Enhanced

Full payment JSON

HMAC (SHA-256)

Real-time status updates with verified integrity