# Webhook

Webhook is a kind of feedback method for payment information.  
When invoice status changes, a POST request is sent to the url\_callback specified when creating the invoice.

## Response

### Response parameters

| Name | Definition |
| --- | --- |
| type | Invoice type (wallet / payment) |
| uuid | uuid of the payment |
| order\_id | Order ID in your system (to identify the order) |
| amount | The amount of the invoice |
| payment\_amount | Amount actually paid by client |
| payment\_amount\_usd | Amount actually paid by client in USD |
| merchant\_amount | The amount added to the merchant's balance, with all commissions subtracted. |
| commission | Heleket commission amount |
| is\_final | Whether the invoice is finalized. When invoice is finalized it is impossible to pay an invoice (it's either paid or expired) |
| status | Payment status<br>Available options:<br>• confirm\_check<br>• paid<br>• paid\_over<br>• fail<br>• wrong\_amount<br>• cancel<br>• system\_fail<br>• refund\_process<br>• refund\_fail<br>• refund\_paid|
| from | Payer's wallet address |
| wallet\_address\_uuid | uuid of the static wallet |
| network | The blockchain network in which the payment is made |
| currency | Invoice currency |
| payer\_currency | The currency that the client actually paid with |
| additional\_data | Additional information string that you provided when creating an invoice |
| convert | Information about the currency to which the payment will be automatically swapped. Conversion is performed from _payer\_currency_ to USDT<br>The _convert_ field will not exist if you have not enabled the automatic conversion function for _payer\_currency_ (e.g. auto convert BTC to USDT)<br>[Structure](https://doc.heleket.com/methods/payments/webhook.md#convert) |
| txid | Transaction hash on the blockchain.<br>The txid field will not exist if<br>1) payment was paid by p2p (The payer withdrew funds from his Heleket account to the address indicated in the invoice and the payment was made without blockchain, only in our system)<br>2) Payment was not paid<br>3) Something was wrong with the payment or the client made a mistake and we marked it as ‘paid’ manually|
| sign | Signature |

### Structure of _convert_

| Name | Definition |
| --- | --- |
| to\_currency | The currency code to which the payment will be swapped |
| commission | Conversion fee |
| rate | Conversion rate |
| amount | Swap amount in to\_currency that was added to the merchant's balance, with all commissions subtracted.<br>amount here equals merchant\_amount \* rate|

### Response example (response\_example)

```
{
  "type": "payment",
  "uuid": "62f88b36-a9d5-4fa6-aa26-e040c3dbf26d",
  "order_id": "97a75bf8eda5cca41ba9d2e104840fcd",
  "amount": "3.00000000",
  "payment_amount": "3.00000000",
  "payment_amount_usd": "0.23",
  "merchant_amount": "2.94000000",
  "commission": "0.06000000",
  "is_final": true,
  "status": "paid",
  "from": "THgEWubVc8tPKXLJ4VZ5zbiiAK7AgqSeGH",
  "wallet_address_uuid": null,
  "network": "tron",
  "currency": "TRX",
  "payer_currency": "TRX",
  "additional_data": null,
  "convert": {
    "to_currency": "USDT",
    "commission": null,
    "rate": "0.07700000",
    "amount": "0.22638000"
  },
  "txid": "6f0d9c8374db57cac0d806251473de754f361c83a03cd805f74aa9da3193486b",
  "sign": "a76c0d77f3e8e1a419b138af04ab600a"
}
```

## Webhook verification

Since by receiving webhooks you are releasing products or crediting your users' balances, you need to make sure that you are receiving webhooks from Heleket and not from anyone else.

We recommend you to check it both ways:

-   use the ip address whitelist and allow requests to url\_callback only from our ips. We send webhooks from ip. 31.133.220.8
-   Verify signature in every webhook that is coming to your url\_callback, read more about this below.

## Verifying webhook signature

Your api keys are secret and no one except you and Heleket should know them. So, when verifying the signature, you will be sure that the webhook was sent by Heleket.

We create a sign using this algorithm. MD5 hash of the body of the POST request encoded in base64 and combined with your API key.

As the signature comes in the body of the request, to verify it, you need to extract the sign from the response body, generate a hash from the body and your API KEY and match it with the sign parameter.

### An example in php:

To receive a json data sent by post to your webhook handler:

```
$data = file_get_contents('php://input');
$data = json_decode($data, true);
```

Lets say we received webhook with data in [this](https://doc.heleket.com/methods/payments/webhook.md#response_example) array  
First, we need to extract the sign from the array:

```
$sign = $data['sign'];
unset($data['sign']);
```

Now lets generate a sign using our api payment key:

```
$hash = md5(base64_encode(json_encode($data, JSON_UNESCAPED_UNICODE)) . $apiPaymentKey);
```

Finally, we can check if the sign we generated with our API payment key equals the sign that came to webhook.

```
if (!hash_equals($hash, $sign)) {
   return new InvalidHashException();
}

// or

if ($hash !== $sign) {
   return new InvalidHashException();
}
```

At this point, you can be sure that the webhook was from Heleket and that you received all the data correctly

> There is a difference when encoding an array of data in php and other languages. PHP does escape slashes and some other languages don’t. Therefore, you may encounter a sign mismatch. You have to escape slashes with backslash to make it work properly.

in php:

```
//  data array
$data = [
    'amount' => '20',
    'currency' => 'USDT',
    'network' => 'tron',
    'txid' => 'someTxidWith/Slash'
];

// json data we send to webhooks
$data = json_encode($data, true);
echo $data;
// Outputs a string, slash in txid is escaped, pay attention to this.
// we send a webhook data with all escaped slashes
// {"amount":"20","currency":"USD","network":"btc","txid":"someTxidWith\/Slash"}
```

in js:

```
const data = {
    amount: '20',
    currency: 'USDT',
    network: 'tron',
    txid: 'someTxidWith/Slash'
};

const jsonData = JSON.stringify(data);
console.log(jsonData);
// {"amount":"20","currency":"USDT","network":"tron","txid":"someTxidWith/Slash"}
// slash in txid is not escaped and you will get error checking sign.
// Instead, you should do it like this:
// const jsonData = JSON.stringify(data).replace(/\//mg, "\/");
```
