> For the complete documentation index, see [llms.txt](https://docs.tylt.money/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.tylt.money/tylt-crossramp-fiat-crypto-solutions/philippines-php/qrph-payin-php-usdt/webhook-for-tylt-crossramp-pay-in.md).

# Webhook for Tylt CrossRamp (Pay-in)

#### Overview

Tylt provides a webhook mechanism for merchants to receive real-time updates on the status of their payment instance, whether for pay-ins or for pay-outs. Merchants can specify a `callBackUrl` in their API requests, and Tylt will send notifications to this URL whenever there is a status change in the transaction.

#### Setting Up the Webhook

1. **Implement a Callback Endpoint:** Merchants must set up an HTTP POST endpoint that can receive JSON payloads. This endpoint should be capable of processing the incoming webhook data and verifying its authenticity using HMAC-SHA256 signature validation.
2. **Insert the Callback URL:** While calling the Create Pay-in or Create Pay-out instance API's  , insert your endpoint URL in the `callBackUrl` field. Tylt will send updates to this URL whenever the transaction status changes.
3. **Status Updates:**  The life cycle of a payment instance is tracked via `eventId`. Below is the list of possible `eventId` values and their meanings:

<table><thead><tr><th width="124.421875">eventId</th><th>Description</th></tr></thead><tbody><tr><td><strong><code>1</code></strong></td><td>Instance Created</td></tr><tr><td><strong><code>2</code></strong></td><td>Order Created</td></tr><tr><td><strong><code>3</code></strong></td><td>Payment Processing</td></tr><tr><td><strong><code>4</code></strong></td><td>Payment Completed</td></tr><tr><td><strong><code>6</code></strong></td><td>Refund Processing</td></tr><tr><td><strong><code>7</code></strong></td><td>Payment Refunded</td></tr><tr><td><strong><code>8</code></strong></td><td>Payment Failed</td></tr><tr><td><strong><code>9</code></strong></td><td>Order Cancelled or Expired</td></tr><tr><td><strong><code>10</code></strong></td><td>KYC Failed</td></tr></tbody></table>

1. **Callback Validation:** To ensure the integrity and authenticity of the callback, Tylt signs each callback payload using HMAC-SHA256 with the merchant’s API secret key. This signature is sent in the HTTP header `X-TLP-SIGNATURE`.
2. **Acknowledge the Callback:** Upon receiving the callback, merchants must respond with an HTTP 200 status code and the text `"ok"` in the response body. This acknowledges the successful receipt of the callback. If the acknowledgment is not received, the webhook will not be retried automatically. Merchants can manually resend web-hooks from their Tylt dashboard.

#### Validating Callbacks

Merchants should validate the HMAC signature included in the `X-TLP-SIGNATURE` header to ensure the callback is from Tylt and has not been tampered with. The HMAC signature is generated using the raw POST data and the `MERCHANT_API_SECRET` as the shared key.

#### Example Web-hook Handling Code

{% tabs %}
{% tab title="JavaScript" %}

```javascript
const express = require('express');
const crypto = require('crypto');

const app = express();
const PORT = 3000;
const apiSecretKey = 'YOUR_TLP_API_SECRET_KEY'; // Replace with your actual API secret key

// Middleware to parse incoming JSON requests
app.use(express.json());

// Callback endpoint
app.post('/callback', (req, res) => {
    const data = req.body;

    // Calculate HMAC signature
    const tlpSignature = req.headers['x-tlp-signature'];
    const calculatedHmac = crypto
        .createHmac('sha256', apiSecretKey)
        .update(JSON.stringify(data)) // Use raw body string for HMAC calculation
        .digest('hex');

    if (calculatedHmac === tlpSignature) {
        // Signature is valid
        if (data.isBuying == 1) {
            console.log('Received pay-in callback:', data);
            // Process pay-in data here
        } 
        // Return HTTP Response 200 with content "ok"
        res.status(200).send('ok');
    } else {
        // Invalid HMAC signature
        res.status(400).send('Invalid HMAC signature');
    }
});

// Start the server
app.listen(PORT, () => {
    console.log(`Server listening on port ${PORT}`);
});

```

{% endtab %}
{% endtabs %}

Again, please note that these code snippets serve as examples and may require modifications based on your specific implementation and framework.

**Example of Web-hook Responses**

{% tabs %}
{% tab title="eventId: 1" %}

```json
{
  "data": {
    "accounts": {
      "MDR": 2,
      "fees": 0.46,
      "rate": 58,
      "fiatAmount": 580,
      "cryptoAmount": 10,
      "fiatCurrency": "PHP",
      "cryptoCurrency": "USDT"
    },
    "isBuying": 1,
    "instanceId": "443bd1a8-944b-4595-8dcf-21e274e6386c",
    "callBackUrl": "",
    "eventDetails": { "eventId": 1, "description": "Instance Created" },
    "merchantOrderId": "merchant-test-ANHOGoRiG3"
  }
}
```

{% endtab %}

{% tab title="eventId: 2" %}

```json
{
  "data": {
    "accounts": {
      "MDR": 2,
      "fees": 0.46,
      "rate": 58,
      "fiatAmount": 580,
      "cryptoAmount": 10,
      "fiatCurrency": "PHP",
      "cryptoCurrency": "USDT"
    },
    "isBuying": 1,
    "instanceId": "443bd1a8-944b-4595-8dcf-21e274e6386c",
    "callBackUrl": "",
    "eventDetails": { "eventId": 2, "description": "Order Created" },
    "merchantOrderId": "merchant-test-ANHOGoRiG3"
  }
}
```

Again, please note that these response snippets serve as examples and may require modifications based on your specific implementation and framework.
{% endtab %}

{% tab title="eventId: 3" %}

```json
{
  "data": {
     "accounts": {
      "MDR": 2,
      "fees": 0.46,
      "rate": 58,
      "fiatAmount": 580,
      "cryptoAmount": 10,
      "fiatCurrency": "PHP",
      "cryptoCurrency": "USDT"
    },
    "isBuying": 1,
    "instanceId": "443bd1a8-944b-4595-8dcf-21e274e6386c",
    "callBackUrl": "",
    "eventDetails": { "eventId": 3, "description": "Payment Processing" },
    "merchantOrderId": "merchant-test-ANHOGoRiG3"
  }
}
```

{% endtab %}

{% tab title="eventId: 4" %}

```json
{
  "data": {
    "accounts": {
      "MDR": 2,
      "fees": 0.46,
      "rate": 58,
      "fiatAmount": 580,
      "cryptoAmount": 10,
      "fiatCurrency": "PHP",
      "cryptoCurrency": "USDT"
    },
    "isBuying": 1,
    "instanceId": "443bd1a8-944b-4595-8dcf-21e274e6386c",
    "callBackUrl": "",
    "eventDetails": { "eventId": 4, "description": "Payment Completed" },
    "merchantOrderId": "merchant-test-ANHOGoRiG3"
  }
}
```

{% endtab %}

{% tab title="eventId: 9" %}

```jsonl
{
  "data": {
    "accounts": {
      "MDR": 2,
      "fees": 0.46,
      "rate": 58,
      "fiatAmount": 580,
      "cryptoAmount": 10,
      "fiatCurrency": "PHP",
      "cryptoCurrency": "USDT"
    },
    "isBuying": 1,
    "instanceId": "443bd1a8-944b-4595-8dcf-21e274e6386c",
    "callBackUrl": "",
    "eventDetails": { "eventId": 9, "description": "Order Cancelled or Expired" },
    "merchantOrderId": "merchant-test-ANHOGoRiG3"
  }
}
```

{% endtab %}

{% tab title="eventId: 10" %}

```json
{
  "data": {
    "accounts": {
      "MDR": 2,
      "fees": 0.46,
      "rate": 58,
      "fiatAmount": 580,
      "cryptoAmount": 10,
      "fiatCurrency": "PHP",
      "cryptoCurrency": "USDT"
    },
    "isBuying": 1,
    "instanceId": "443bd1a8-944b-4595-8dcf-21e274e6386c",
    "callBackUrl": "",
    "eventDetails": { "eventId": 10, "description": "KYC Failed" },
    "merchantOrderId": "merchant-test-ANHOGoRiG3"
  }
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
**Important Considerations**

* **Security:** Always verify the `X-TLP-SIGNATURE` header to ensure the callback originates from Tylt.
* **Response:** Always return an HTTP 200 response with `"ok"` in the body to acknowledge successful receipt of the web-hook.
* **Manual Retry:** In case of missed callbacks, use the tylt.money dashboard to manually resend the webhook.
  {% endhint %}
