Skip to main content

Webhook Notifications

Integrating webhook notifications is a significant step in the process, enabling your system to respond quickly to changes in payment status.

When registering in the system, specify the URL where transaction status notifications will be sent, both successful and unsuccessful. In the merchant account, you can configure a separate webhook for each terminal and select which types of webhook you wish to receive.

General Logic

Webhooks are used to synchronize statuses between WATA and the merchant system in real time.

Typical scenario:

  1. A payment transaction or refund status changes in WATA.
  2. WATA sends an HTTP request to the merchant webhook URL.
  3. The merchant system processes the notification.
  4. The merchant system must return an HTTP 200 OK response.

If the webhook was not delivered successfully, further behavior depends on the notification type.


Notification Types

Webhook notifications have three types:

Webhook typeWhen it arrivesWhat it is used for
Pre-paymentImmediately after the customer clicks "Pay", but before the request to the bankProduct availability check, price relevance check, fraud monitoring, or another merchant-side order check
Post-paymentAfter successful transaction confirmation by the bank or after a payment errorExecuting business logic: granting access, changing order status in the database, sending a receipt, and so on. In the merchant account terminal settings, you can disable receiving webhooks with the Declined status if needed
RefundAfter a successful refund or a refund errorBalance adjustment, order cancellation, or service deactivation

Processing Rules and Timeouts

Your server must return HTTP 200 OK for every webhook notification.

If no response is received or the response is not 200:

Webhook typeBehavior when response failsResponse timeout
Pre-paymentThe transaction is considered not approved and is automatically declined. The request to the bank is not sent10 seconds
Post-paymentWATA retries sending with an increasing interval for the next 32 hours1 minute
RefundWATA retries sending with an increasing interval for the next 32 hours1 minute

Webhook Notification Parameters

ParameterTypeComment
transactionTypeStringTransaction type: CardCrypto for ruble and foreign-currency cards, SBP for the Faster Payments System, TPay for the T-Bank method, SberPay for the Sberbank method
kindStringTransaction kind: Payment for payment, Refund for refund
idUUIDTransaction identifier in the WATA system. This is not the payment link identifier
transactionIdUUIDIdentifier of the created refund transaction in the WATA system
originalTransactionIdUUIDUsed for refunds. Identifier of the original transaction for which a partial or full refund is made
terminalPublicIdUUIDPublic identifier of the merchant terminal
transactionStatusStringTransaction status (Created, Pending, Paid, Declined). See Transaction Statuses
errorCodeStringError code for an unsuccessful request. See the error code reference
errorDescriptionStringError description for an unsuccessful request
terminalNameStringMerchant terminal name
amountNumberPayment amount. Up to 2 digits after the decimal point are allowed for kopecks or cents. Example: 1188.00
currencyStringPayment currency (RUB, USD, EUR)
orderIdStringUnique order identifier in the merchant system
orderDescriptionStringOrder description
commissionNumberTransaction fee
paymentTimeDateDate and time of transaction payment in UTC, meaning the transition to Paid or Declined
emailStringPayer email, if it was provided on the form
paymentLinkIdUUIDPayment link identifier in the WATA system
payerDataObjectContains payer information
payerData.payerIdStringMasked payer phone number for an SBP transaction

Security and Signature Verification

To guarantee that the notification was sent by WATA, each message contains an 'X-Signature' header featuring a digital RSA signature. This header can be used to verify that the notification was sent by WATA, ensuring the integrity and authenticity of the payload.

X-Signature: <signature>

Verification Algorithm

  1. Get the public key. Use the current key (PKCS1 format), available at: api.wata.pro/api/h2h/public-key.
  2. Prepare the data. Use raw JSON, the unprocessed request body received in the webhook, as the message.
  3. Verify. Use the SHA512withRSA algorithm to check that the signature from the X-Signature header matches the message body.

Use the raw request body exactly as received. If JSON was formatted, rebuilt, or changed by middleware, signature verification may fail.

PHP signature verification example

<?php

class SignatureVerificationService {
public static function verify($rawWebhookJson, $signature, $publicKey) {
$publicSignature = openssl_get_publickey($publicKey);
$signatureBytes = base64_decode($signature);

$result = openssl_verify($rawWebhookJson, $signatureBytes, $publicSignature, OPENSSL_ALGO_SHA512);
openssl_free_key($publicSignature);

return $result === 1;
}
}

Java signature verification example

import java.security.PublicKey;
import java.security.Signature;
import java.util.Base64;

import static java.nio.charset.StandardCharsets.UTF_8;

public class SignatureVerificationService {
public static boolean verify(String rawWebhookJson, String signature, PublicKey publicKey) throws Exception {
Signature publicSignature = Signature.getInstance("SHA512withRSA");
publicSignature.initVerify(publicKey);
publicSignature.update(rawWebhookJson.getBytes(UTF_8));

byte[] signatureBytes = Base64.getDecoder().decode(signature);

return publicSignature.verify(signatureBytes);
}
}

Getting the Public Key

The public key for signature verification can be received through the API:

GET https://api.wata.pro/api/h2h/public-key
Content-Type: application/json

Response example

{
"value": "-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----"
}

Webhook Notification Example

Content-Type: application/json
X-Signature: <signature>
{
"transactionType": "CardCrypto",
"kind": "Payment",
"id": "3a1cf611-abc6-8d30-c4cd-521c9f6eeeb0",
"transactionId": "3a16a4f0-27b0-09d1-16da-ba8d5c63eae3",
"transactionStatus": "Paid",
"terminalPublicId": "3b16a2f1-dead-4e5d-abff-90865d1e13b1",
"errorCode": null,
"errorDescription": null,
"terminalName": "string",
"amount": 1188.00,
"currency": "RUB",
"orderId": "string",
"orderDescription": "string",
"paymentTime": "2024-12-04T17:41:44.434598Z",
"commission": 10,
"email": null,
"paymentLinkId": null
}

Processing Recommendations

  • Return 200 OK only after successful notification processing.
  • Process webhook notifications idempotently: repeated delivery of the same event must not break business logic.
  • Store transactionId and transactionStatus for later reconciliation.
  • Verify the X-Signature header before executing any business logic.
  • Do not use polling as the main way to receive statuses. Use webhook notifications for status updates.

Technical Documentation