Skip to content

Callbacks#

A callback (webhook) mechanism is provided for notifying merchants about final order statuses in the payment system.

Request Structure#

If the merchant specified the callbackURL field when creating the order, a POST request is sent to the specified URL at the moment the order transitions to one of the trigger statuses.

Headers:

  • Content-Type: application/json
  • X-Api-Version: v3 - format version marker
  • X-Signature: <SIGNATURE> - request body signature. See the "Verification" section below

The request body is the OrderOut order model (see "General Information"); for P2P it includes the paymentDetails block:

{
  "id": "9c37e448-84b5-4639-9ffa-29558f8f2567",
  "createdAt": "2026-08-31T16:08:06.310479Z",
  "updatedAt": "2026-08-31T16:12:41.825346Z",
  "type": "PayIn",
  "direction": "PayIn",
  "status": "succeeded",
  "merchantOrderID": "TX-1",
  "clientID": "C1",
  "methodID": 9,
  "paymentDetails": {
    "requisiteTypeCode": "card",
    "recipientName": "Ivan Ivanov",
    "recipientNumber": "7777777777777777",
    "recipientBank": "SBER"
  },
  "currencyCode": "AZN",
  "amount": 10,
  "merchantCommission": 0.5,
  "amountUSDT": 5.617978,
  "merchantCommissionUSDT": 0.280899,
  "exchangeRate": 1.78,
  "trafficType": "mixed"
}

Trigger Statuses#

The webhook is sent when the order transitions to one of the statuses:

  1. succeeded
  2. expired
  3. succeeded_by_appeal
  4. failed_by_appeal
  5. failed_by_terminal
  6. all_terminals_failed

Verification#

A body signature is sent with each request so that the merchant can verify its authenticity.

Signature algorithm:

  1. Compute the SHA256 hash of the request body
  2. Sign it with the private RSA (PKCS #1 v1.5) key
  3. Encode with base64 std encoding

The resulting signature is sent in the X-Signature header.

Verification Algorithm#

Upon receiving a request on the webhook endpoint, verify its signature using the following algorithm:

  1. Decode the X-Signature header value from base64
  2. Compute the SHA256 hash of the received request body
  3. Verify the signature with the RSA public key
Go implementation example
package main

import (
    "crypto"
    "crypto/rsa"
    "crypto/sha256"
    "crypto/x509"
    "encoding/base64"
    "encoding/pem"
    "fmt"
)

func VerifyRSASignature(publicKey *rsa.PublicKey, data []byte, signatureBase64 string) error {
    signature, err := base64.StdEncoding.DecodeString(signatureBase64)
    if err != nil {
        return err
    }

    hash := sha256.Sum256(data)

    err = rsa.VerifyPKCS1v15(publicKey, crypto.SHA256, hash[:], signature)
    if err != nil {
        return err
    }

    return nil
}

func main() {
    data := []byte(`<HTTP-REQUEST-BODY>`)
    signature := "<X-SIGNATURE-HEADER-VALUE>"
    pubKeyPEM := `<PUBLIC-KEY>`

    block, _ := pem.Decode([]byte(pubKeyPEM))
    if block == nil || block.Type != "PUBLIC KEY" {
        panic("failed to decode public key")
    }

    pubKeyInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
    if err != nil {
        panic(err)
    }

    pubKey, ok := pubKeyInterface.(*rsa.PublicKey)
    if !ok {
        panic("failed to cast key to *rsa.PublicKey")
    }

    err = VerifyRSASignature(pubKey, data, signature)
    if err != nil {
        fmt.Println("Signature is invalid:", err)
    } else {
        fmt.Println("Signature is valid!")
    }
}

Public RSA Keys#

Public keys for signature verification are provided by the payment system technical specialists during integration - separately for the stage and prod environments. See the "Integration Process" page.