# 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>Order Processing</td></tr><tr><td><strong><code>4</code></strong></td><td>Payment Processing</td></tr><tr><td><strong><code>5</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": 1.3,
      "fiatAmount": 30,
      "cryptoAmount": 23.08,
      "fiatCurrency": "EUR",
      "cryptoCurrency": "USDC"
    },
    "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": 1.3,
      "fiatAmount": 30,
      "cryptoAmount": 23.08,
      "fiatCurrency": "EUR",
      "cryptoCurrency": "USDC"
    },
    "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": 1.3,
      "fiatAmount": 30,
      "cryptoAmount": 23.08,
      "fiatCurrency": "EUR",
      "cryptoCurrency": "USDC"
    },
    "isBuying": 1,
    "instanceId": "443bd1a8-944b-4595-8dcf-21e274e6386c",
    "callBackUrl": "",
    "eventDetails": { "eventId": 3, "description": "Order Processing" },
    "merchantOrderId": "merchant-test-ANHOGoRiG3"
  }
}
```

{% endtab %}

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

```json
{
  "data": {
    "accounts": {
      "MDR": 2,
      "fees": 0.46,
      "rate": 1.3,
      "fiatAmount": 30,
      "cryptoAmount": 23.08,
      "fiatCurrency": "EUR",
      "cryptoCurrency": "USDC"
    },
    "isBuying": 1,
    "instanceId": "443bd1a8-944b-4595-8dcf-21e274e6386c",
    "callBackUrl": "",
    "eventDetails": { "eventId": 4, "description": "Payment Processing" },
    "merchantOrderId": "merchant-test-ANHOGoRiG3"
  }
}
```

{% endtab %}

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

```jsonl
{
  "data": {
    "accounts": {
      "MDR": 2,
      "fees": 0.46,
      "rate": 1.3,
      "fiatAmount": 30,
      "cryptoAmount": 23.08,
      "fiatCurrency": "EUR",
      "cryptoCurrency": "USDC"
    },
    "isBuying": 1,
    "instanceId": "443bd1a8-944b-4595-8dcf-21e274e6386c",
    "callBackUrl": "",
    "eventDetails": { "eventId": 5, "description": "Payment Completed" },
    "merchantOrderId": "merchant-test-ANHOGoRiG3"
  }
}
```

{% endtab %}

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

```jsonl
{
  "data": {
    "accounts": {
      "MDR": 2,
      "fees": 0.46,
      "rate": 1.3,
      "fiatAmount": 30,
      "cryptoAmount": 23.08,
      "fiatCurrency": "EUR",
      "cryptoCurrency": "USDC"
    },
    "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": 1.3,
      "fiatAmount": 30,
      "cryptoAmount": 23.08,
      "fiatCurrency": "EUR",
      "cryptoCurrency": "USDC"
    },
    "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 %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.tylt.money/introduction/tylt-crossramp-fiat-crypto-solutions/eu-open-banking/open-banking-payin-eur-gbp-usdc/webhook-for-tylt-crossramp-pay-in.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
