Webhooks

Last updated:November 07, 2025
Webhooks are HTTP-based callbacks that notify your system when specific events occur on your entities. Instead of polling for updates, you configure a webhook once, and it pushes data to your system when relevant events happen - such as updates on payments, tokens, scheduled payments, risk decisions or transaction state changes.

Why use webhooks?

Webhooks help you:
  • Receive data automatically when something changes
  • Automate workflows (e.g., update order status, trigger refunds)
  • Simplify integration - just provide a URL to start receiving events
  • Reduce load on your systems by avoiding polling

When not to use webhooks

Webhooks are asynchronous and typically fast, but not guaranteed to be instant. In rare cases - such as during platform releases or data center switchovers - delivery may be delayed by several minutes. If your workflow depends on real-time transaction status, use the Transaction Status query API instead.

Use webhooks when:

  • You want event-driven automation
  • You need transaction updates for reporting or reconciliation
  • A short delay (up to ~15 minutes) is acceptable

Use transaction status query when:

  • You need immediate confirmation (e.g., to capture funds or deliver goods while the shopper is present)
  • Your workflow is time-sensitive

Availability

Webhooks are typically delivered within seconds of the triggering event. However, during platform releases, data center switchovers, or application restarts, delivery may be delayed by up to 15 minutes.

Important: If your use case requires immediate awareness of transaction status (e.g., to capture funds or deliver goods while the shopper is still present), we strongly recommend using the Transaction Status query API instead of relying solely on webhooks.
Use case type Recommended approach Reason
Real-time decisions (e.g., capture, fulfillment) Transaction Status query API Ensures immediate and reliable status
Reporting & reconciliation Webhooks Delays are acceptable; automation-friendly
Non-critical automation Webhooks Efficient and event-driven
High-frequency polling Not recommended Use webhooks or transaction export via SFTP instead

Retry & failure behavior

BehaviorDescription
Timeout No response within 30 seconds → marked as failed
Failure Non-2xx HTTP response → marked as failed
Retry intervals 1 min → 2 min → 4 min → 8 min → 15 min → 30 min → 1 hour → daily (up to 30 days)
Failing retry pattern Retries pause if all messages fail at a given interval; resume once delivery succeeds
Daily failure summary Email with up to 100 failed notifications per endpoint
Retention Failed messages stored for 30 days, then purged

Message Ordering & Load

  • No guaranteed order: Events may arrive out of sequence. Design your system to handle this.
  • Multiple final messages: You may receive more than one final status (e.g., success + failure). Deduplicate based on transaction ID and status.
  • High throughput: Your server must handle bursts (e.g., 30+ notifications/sec). Use asynchronous processing and caching where possible.

Configuration

Webhooks are managed in the user interface portal under: Administration → Webhooks.

You can configure webhooks at any level of your entity hierarchy. Each webhook will receive notifications for the entity it’s configured on, as well as all its descendants.

Scope & hierarchy

FeatureDescription
Entity scope A webhook receives events from its entity and all child entities
Multiple endpoints The same notification is sent to all active webhook URLs configured at or above the entity level
Filtering You can filter which types of events (e.g., payments, risks) each webhook should receive
Automatic retries Failed deliveries are automatically retried based on the retry policy
Failure alerts Daily email alerts are sent when delivery fails repeatedly

Add a webhook

To add a webhook, configure the following parameters:

ParameterDescription
URL The public endpoint that will receive the webhook notifications
Types Event categories to subscribe to: PAYMENTS, REGISTRATIONS, SCHEDULES, RISKS
Fields Choose ALL (full payload) or NON_CUSTOMER_DATA (exclude sensitive fields)
Secret A 64-character hex string used to encrypt the payload
Wrapper Format of the payload: None (hex string) or JSON (wrapped in JSON)
Emails One or more email addresses to receive daily failure summaries
Newly created webhooks are inactive by default. They must be tested and activated before receiving real notifications.

Test a webhook

Before activation, you must test the webhook using the "Click to Test" feature. This sends a dummy notification to your configured URL.

The test ensures:

  • The URL is reachable
  • Your firewall allows incoming traffic
  • Your server responds with HTTP 2xx
  • The payload is correctly received and decrypted
Once the test succeeds, the webhook becomes active and will start receiving real notifications.
If the test fails, the webhook remains inactive and no events will be delivered.

Format

Webhook notifications are sent as JSON objects with a consistent structure. This allows your system to parse and process them reliably.

{
	"type": [notification_type],
	"action": [status],
	"payload": [content]
}

Field descriptions

FieldDescription
type The category of the event: PAYMENT, REGISTRATION, SCHEDULE, or RISK
action Only present for REGISTRATION events. Indicates the change: CREATED, UPDATED, or DELETED
payload The full content of the event. This mirrors the response you would receive from the corresponding API (e.g., payment, risk transaction)
The payload contains all relevant transaction data, depending on your selected field configuration (ALL or NON_CUSTOMER_DATA)
The structure is consistent across event types, but the payload schema varies depending on the event (e.g., payment vs. risk)

Example - payment

{
   "type":"PAYMENT",
   "payload":{
      "id":"8a829449515d198b01517d5601df5584",
      "paymentType":"PA",
      "paymentBrand":"VISA",
      "amount":"92.00",
      "currency":"EUR",
      "presentationAmount":"92.00",
      "presentationCurrency":"EUR",
      "descriptor":"3017.7139.1650 OPP_Channel ",
      "result":{
         "code":"000.000.000",
         "description":"Transaction succeeded"
      },
      "authentication":{
         "entityId":"8a8294185282b95b01528382b4940245"
      },
      "card":{
         "bin":"420000",
         "last4Digits":"0000",
         "holder":"Jane Jones",
         "expiryMonth":"05",
         "expiryYear":"2018"
      },
      "customer":{
         "givenName":"Jones",
         "surname":"Jane",
         "merchantCustomerId":"jjones",
         "sex":"F",
         "email":"jane@jones.com"
      },
      "customParameters":{
         "SHOPPER_promoCode":"AT052"
      },
      "risk":{
         "score":"0"
      },
      "buildNumber":"ec3c704170e54f6d7cf86c6f1969b20f6d855ce5@2015-12-01 12:20:39 +0000",
      "timestamp":"2015-12-07 16:46:07+0000",
      "ndc":"8a8294174b7ecb28014b9699220015ca_66b12f658442479c8ca66166c4999e78",
      "channelName": "OPP_Channel",
      "source": "SYSTEM",
      "paymentMethod": "CC",
      "shortId": "5420.6916.5424"
  }
}

Example - registration

{
   "type":"REGISTRATION",
   "action": "CREATED",
   "payload":{
      "id":"8a82944a53e6a0150153eaf693584262",
      "paymentBrand":"VISA",
      "result":{
         "code":"000.000.000",
         "description":"Transaction succeeded",
         "randomField1315125026":"Please allow for new unexpected fields to be added"
      },
      "card":{
         "bin":"420000",
         "last4Digits":"0000",
         "holder":"Jane Jones"
      },
      "authentication":{
         "entityId":"8a8294174b7ecb28014b9699220015ca"
      },
      "redirect":{
         "parameters":[

         ]
      },
      "risk":{
         "score":""
      },
      "timestamp":"2016-04-06 09:45:41+0000",
      "ndc":"8a8294174b7ecb28014b9699220015ca_b1539494024c411684b544574716e608",
      "channelName": "OPP_Channel",
      "source": "SYSTEM",
      "paymentMethod": "CC",
      "shortId": "7820.6916.2918"
   }
}

Example - schedule

{
  "type": "SCHEDULE",
  "payload": {
    "id": "8acda4a489919d63018996faf10b2a66",
    "registrationId": "8acda4a889919e5e018996f86a8f127a",
    "paymentType": "SD",
    "presentationAmount": "92.00",
    "presentationCurrency": "EUR",
    "result": {
      "code": "000.000.000",
      "description": "Transaction succeeded",
      "randomField1730751282": "Please allow for new unexpected fields to be added"
    },
    "resultDetails": {
      "ConnectorTxID1": "8acda4a489919d63018996faf10b2a66"
    },
    "customer": {
         "givenName":"Jones",
         "surname":"Jane",
         "merchantCustomerId":"jjones",
         "sex":"F",
         "email":"jane@jones.com"
    },
    "authentication": {
      "entityId": "8a8294174b7ecb28014b9699220015ca"
    },
    "redirect": {
      "parameters": []
    },
    "risk": {
      "score": ""
    },
    "timestamp": "2023-07-27 10:52:55+0000",
    "ndc": "ef2c099f5b29455a9dbd260c59bcc224",
    "channelName": "OPP_Channel",
    "source": "SCHEDULER",
    "paymentMethod": "DC",
    "shortId": "3833.0396.7654"
  }
}

Example - risk

{
 "type": "RISK",
  "payload": {
    "id": "8ac9a4a86461239601646522acb26523",
    "referencedId": "8ac9a4a86461239601646522aaf96510",
    "paymentType": "RI",
    "paymentBrand": "VISA",
    "presentationAmount": "0.0",
    "result": {
      "code": "000.000.000",
      "description": "Transaction succeeded"
    },
    "card": {
      "bin": "420000",
      "last4Digits": "0000",
      "holder": "Jane Jones",
      "expiryMonth": "03",
      "expiryYear": "2025"
    },
    "authentication": {
      "entityId": "8a8294174b7ecb28014b9699220015ca"
    },
    "redirect": {
      "parameters": []
    },
    "risk": {
      "score": ""
    },
    "timestamp": "2018-07-04 11:52:08+0000",
    "ndc": "8a8294174b7ecb28014b9699220015ca_b1539494024c411684b544574716e608",
    "channelName": "OPP_Channel",
    "source": "SYSTEM",
    "paymentMethod": "RM",
    "shortId": "3833.0396.7654"
  }
}

Encryption

To protect sensitive transaction data from tampering or unauthorized access, all webhook payloads are encrypted before being sent to your configured endpoint. Decryption is required on your side to access the actual event content.

Encryption details

ParameterDescription
Algorithm AES (Advanced Encryption Standard)
Key 64-character hexadecimal string (configured in the webhook settings)
Key length 256 bits (32 bytes)
Block mode GCM (Galois/Counter Mode)
Padding None
Initialization vector Sent in HTTP header X-Initialization-Vector (hexadecimal)
Authentication tag Sent in HTTP header X-Authentication-Tag (hexadecimal)
Payload format Encrypted hexadecimal string in the body
Wrapper option None (raw hex string) or JSON (e.g., { "encryptedBody": "..." })

Payload wrappers

Depending on your configuration, the encrypted payload is delivered in one of two formats:
  • None (default)
    • Content-Type: text/plain
    • Body contains only the encrypted hexadecimal string
  • JSON wrapper
    • Content-Type: application/json
    • Body format: {"encryptedBody": "hexadecimal_string"}

Decryption

Decryption is the process of converting the encrypted webhook payload back into its original, readable format. This step is essential to interpret and act on the transaction data securely delivered to your endpoint.

What you need to decrypt

To decrypt the payload, your system must use the same encryption parameters configured in the webhook setup. These include:
ComponentSource
Encrypted body In the HTTP request body (hexadecimal string or JSON wrapper)
Secret key Configured in the webhook settings (64-character hex string)
Initialization vector In HTTP header X-Initialization-Vector
Authentication tag In HTTP header X-Authentication-Tag
Algorithm AES-256-GCM (no padding)

Decryption steps

  1. Extract the encrypted body from the request (either raw or from the encryptedBody field in JSON).
  2. Read the initialization vector and authentication tag from the headers.
  3. Use the configured secret key to decrypt the payload using AES-256-GCM.
  4. Validate the authentication tag to ensure integrity.
  5. Parse the decrypted payload as JSON to access the event data.

Common pitfalls

  • Ensure the key format and length match the expected AES-256 requirements.
  • Use UTF-8 encoding when converting strings to bytes.
  • Validate the authentication tag to prevent tampered data.
  • Handle decryption errors gracefully to avoid processing invalid payloads.

Example - decryption

Response handling

When your system receives a webhook, it must respond with a 2xx HTTP status code (e.g., 200 OK). This confirms successful delivery and prevents retries.

If your server:

  • Returns a non-2xx status code, or
  • Fails to respond within 30 seconds,
the webhook is considered undelivered and will be retried according to the retry policy.

Protocol requirements

To decrypt the payload, your system must use the same encryption parameters configured in the webhook setup. These include:
ParameterRequirement
Protocol HTTPS (TLS 1.2 or higher)
Method POST
Content-type text/plain or application/json (based on wrapper)
SSL certificates Must be valid and trusted; self-signed certificates are not accepted in production

Best practices

  • Ensure your endpoint is always available and can respond quickly
  • Use asynchronous processing to avoid delays in response
  • Monitor for non-2xx responses and fix issues promptly
  • Validate that your SSL certificate chain is complete and trusted

See also