Transaction callback (Deposits and Withdrawals)#
Once a merchant has been enabled for customer payments within the XGateway system, incoming customer deposits are processed automatically. To keep you informed, a callback (webhook) is sent once a transaction reaches its final state - confirmed or failed.
Merchants can also request to receive processing-type callbacks. This may be useful in certain cases, for example, to notify users that processing started, but handling these callbacks is not required for proper transaction processing, and they are not enabled by default.
Prefer callbacks over polling; they are signed and retried. For high-risk operations, confirm state via API (see the risks and details on the Callbacks Handling page). API responses are the source of truth.
Set up the transaction callback endpoint#
To accept the KYC status updates you should configure the endpoint on your side and provide it during the integration setup.
It is always best to ensure that your callback endpoint is up and running so that the notifications can reach you. XGateway will retry failed requests up to 10 times.
All notifications (delivered or not) will be available on your dashboard. You can also see the error messages for failed notifications and investigate the issue on your side.
Crypto transactions are permanently recorded on the public blockchain as well as stored in our database. This data may be used for cross check and debugging.
Callback endpoint#
https://your-callback-url-here.com/handle-transaction This endpoint must properly handle deposit callbacks. If withdrawals requested - the same endpoint will be used to send the withdrawal transaction status, see the payload examples below.
Callback payload (deposits and withdrawals)#
All fields, including amount, are sent as a string to avoid unintended transformations during hash encoding and decoding. Optional fields can be null
XGateway supports multiple payment methods but uses a single, unified transaction callback format. As a result, some fields are optional and payment-method-specific. For example, rejectionReason applies only to credit card payments and will be null for other methods. Important fields for a specific payment method are typically documented on a dedicated page. All non-core fields are informational only and may change over time.
The core fields include:
- the
callbackType(transaction); - the transaction
type(depositorwithdraw); - fields used for callback validation
transactionIdcustomerIdamountcurrency
- signed with the
hash; - and the transaction
status(confirmed,failed, or, if explicitly set up,processing).
Callback body breakdown
| Name | Description |
|---|---|
| callbackType | The type of callback: transaction |
| amount | The transaction amount as sent by the customer |
| applicationId | The unique application ID in the merchant system |
| currency | The currency sent by the customer. See supported currencies for the full list |
| customerId | The unique customer ID in the merchant system |
| hash | Base64-encoded SHA-512 hash of: {transactionId}.{customerId}.{amount}.{currency}.{secretKey} |
| id | The unique transaction ID in the XGateway system |
| invoiceId | The unique invoice ID in the XGateway system |
| network | The blockchain network the transaction was made on |
| orderId | The unique order ID in the merchant system |
| status | The transaction status |
| transactionHash | The transaction hash on the blockchain |
| type | The transaction type |
| info | |
| info.exchangeRate | The exchange rate used for fiat-to-crypto conversion, if applicable |
| info.referenceAmount | The transaction amount in the reference currency set during sign-up |
| info.referenceCurrency | The reference currency set during sign-up |
| info.referenceExchangeRate | The exchange rate used for conversion from transaction currency to the reference currency |
| info.transactionAmount | The transaction amount received by the merchant after swaps |
| info.transactionCurrency | The transaction currency received by the merchant |
| info.invoiceBaseAmount | The amount as specified in the invoice |
| info.invoiceBaseCurrency | The currency as specified in the invoice |
| info.transactionAmountBaseCurrency | The actual transaction amount converted to the invoice currency |
| fees | |
| fees.processing | Processing fee in transaction currency |
| fees.technical | Technical fee in transaction currency |
| senderDetails | |
| senderDetails.senderIban | The sender IBAN used to initiate the deposit. This block is sent only for fiat-to-crypto deposits |
| additionalParams | |
| additionalParams.utr | UTR for UPI payments |
Here is an example of how the different currencies work. Let's say a merchant operates in USD (reference currency). A customer sends 10 EUR through SEPA Secure with a conversion to USDT on Polygon. In this case the callback will contain:
- Amount and currency field will contain 10 and EUR.
- Reference currency USD and amount of the transaction as 10 EUR converted to USD.
info.transactionAmountandinfo.transactionCurrencywill contain the amount inpUSDTafter swap topUSDT.
Callback example: deposit#
The callback you get after a confirmed or failed Deposit transaction might look like this:
Deposit callback
{
"callbackType": "transaction",
"amount": "200",
"applicationId": null,
"currency": "EUR",
"customerId": "000394",
"hash": "rpn1za+9YmGDKSZBMVBd...i8DjYOhiq51g==",
"id": "123486c2-4dbd-4a72-8be2-3338bef9a696",
"invoiceId": "edef7683-a900-4e6a-8973-24949910017c",
"network": null,
"orderId": null,
"status": "confirmed",
"transactionHash": "0x58f6...",
"type": "deposit",
"info": {
"exchangeRate": "1.03759",
"referenceAmount": "207.52",
"referenceCurrency": "USD",
"referenceExchangeRate": "1.000065",
"transactionAmount": "207.51518",
"transactionCurrency": "tUSDT",
"invoiceBaseAmount": "200",
"invoiceBaseCurrency": "EUR",
"transactionAmountBaseCurrency": "199.98"
},
"fees": {
"processing": "7.263031",
"technical": null
},
"eur": "200.12",
"usd": "207.52",
"senderDetails": {
"senderIban": "GB29NWBK60161331926819",
"senderAccountNumber": "31926819",
"senderSortCode": "601613"
},
"additionalParams": {
"utr": "111111111111"
},
"customer": {
"email": "string",
"fullname": "string"
},
"billingAddress": {
"city": "string",
"state": "string",
"postalCode": "string",
"addressLine": "string",
"countryCode": "string"
},
"paymentMethodDetails": {
"cardType": "string",
"cardExpiryYear": "string",
"cardholderName": "string",
"cardExpiryMonth": "string",
"customerAccountNumber": "string",
"cardIssuingCountryCode": "string"
},
"rejectionReason": null
}
Callback example: withdrawal#
The callback you get after a confirmed or failed Withdraw transaction might look like this:
Withdrawal callback
{
"callbackType": "transaction",
"senderDetails": null,
"amount": "1.71",
"applicationId": null,
"currency": "EUR",
"customerId": "sepa-secure-customer",
"hash": "FA5h8Ff4Onr...Ms7T2fjN/JybzwwMAjgg6g==",
"id": "1234c71f-70fa-407b-b532-c5a219d3eb74",
"invoiceId": "edefc865-2513-4409-a944-133b06011b4d",
"network": null,
"orderId": "order_test_prod",
"status": "confirmed",
"transactionHash": null,
"type": "withdrawal",
"createdAt": "2025-07-18T07:45:18.732Z",
"updatedAt": "2025-07-18T07:46:38.611Z",
"info": {
"exchangeRate": "1.162371703223256733",
"referenceAmount": "2",
"referenceCurrency": "USD",
"referenceExchangeRate": "1.000065",
"transactionAmount": "2",
"transactionCurrency": "tUSDT",
"invoiceBaseAmount":"1.71",
"invoiceBaseCurrency":"EUR",
"transactionAmountBaseCurrency":"1.92"
},
"additionalParams": {
"utr": "111111111111"
},
"fees": {
"processing": "0.08",
"technical": null
},
"eur": "1.72",
"usd": "2"
}
Response and data handling#
You may handle the payload information as needed. You do not need to send anything back other than a success status to confirm that the callback has been received and processed on your side.
FYI: Transaction Statuses#
Below is a non-exhaustive list of transaction statuses supported in the system. Callbacks are sent only for confirmed and failed statuses — and optionally for processing, if this was explicitly enabled during merchant setup. Other statuses (such as created or hold) are visible in the Merchant Back Office but are not sent as callbacks.
confirmed- the transaction has been successfully processedcreated- the transaction has been initiated and is awaiting further processingfailed- the transaction processing failedprocessing- the transaction is currently being processedhold- the transaction is temporarily paused and awaiting manual resolution