# Webhook

We can notify a merchant about the statuses of off-ramp orders associated with him.

We will make a **POST** request to a provided webhook URL with the next **application/json** contents:

**Webhook V1:**[**​**](https://docs.fonbnk.com/docs/offramp/webhook#webhook-v1)

<pre class="language-typescript"><code class="lang-typescript">type WebhookRequest = {
  data: {
    orderId: string,
    offrampType: "bank",
    status: OfframpStatus,
    date: string,
    cashout: {
      localCurrencyAmount: number, // how much the user will receive in local currency
      usdAmount: number, // how much user must send in USD
      feeAmountUsd: number, // total fee amount in USD
      feeAmountUsdFonbnk: number, // fee amount in USD for Fonbnk
      feeAmountUsdPartner: number, // fee amount in USD for partner
      feeAmountLocalCurrency: number, // total fee amount in local currency
      feeAmountLocalCurrencyFonbnk: number, // fee amount in local currency for Fonbnk
      feeAmountLocalCurrencyPartner: number, // fee amount in local currency for partner
    },
    exchangeRate: number,
    network: "AVALANCHE" | "POLYGON" | "CELO",
    asset: "USDC" | "CUSD",
    fromAddress: string,
    toAddress: string,
    userEmail: string,
    requiredFields: { label: string, type: 'number' | 'string' | 'date' | 'boolean' | 'email' | 'phone', value: string }[],// user account data
    orderParams?: string, // contents of orderParams query parameter during order creation
    countryIsoCode: string,
    currencyIsoCode: string,
  },
  hash: string,
};

enum OfframpStatus  {
  INITIATED = 'initiated', 
  VALIDATING_TRANSACTION = 'validating_transaction', // user has sent us a transaction hash, waiting it to appear in a blockchain
  TRANSACTION_INVALID = 'transaction_invalid', // submited transaction hash is invalid (wrong amount, wrong creation time etc.)
  AWAITING_TRANSACTION_CONFIRMATION = 'awaiting_transaction_confirmation', //waiting for transaction confirmation
  TRANSACTION_CONFIRMED = 'transaction_confirmed', // user transaction was confirmed
  TRANSACTION_FAILED = 'transaction_failed', // user transaction is not confirmed in the blockchain
  OFFRAMP_SUCCESS = 'offramp_success',  // user has received the funds
<strong>  OFFRAMP_RETRY = "offramp_retry", // we are retrying the off-ramp after a failed attempt
</strong>  TRANSACTION_FAILED = 'transaction_failed', // user transaction failed
  OFFRAMP_PENDING = 'offramp_pending', // offramp in progress
  OFFRAMP_FAILED = 'offramp_failed', // offramp failed
  REFUNDING = 'refunding', // offramp failed, refund in progress
  REFUNDED = 'refunded', // offramp failed, refund was successful
  REFUND_FAILED = 'refund_failed', // offramp failed, refund failed
  EXPIRED = 'expired', // user did not send us a transaction hash in time
  CANCELLED = "cancelled" // user cancelled an order
}
</code></pre>

**Webhook V2:**[**​**](https://docs.fonbnk.com/docs/offramp/webhook#webhook-v2)

Instead of sending hash inside - **WebhookRequest**, we will send it as a request **x-signature** header

```
Request headers:
x-signature: hash (string)
```

**Webhook verification:**[**​**](https://docs.fonbnk.com/docs/offramp/webhook#webhook-verification)

We send a hash field in our webhook to protect merchants from fraudulent requests. Each request should be verified by a secret provided in the dashboard.

Here is how it should be checked in pseudocode:

```
request.body.hash === SHA256(stringify(request.body.data), secret)
```

Here is how it should be checked in Node.js:

For Webhook V1 version:

```javascript
import { createHash } from 'crypto';

request.body.hash === createHash('sha256')
   .update(JSON.stringify(request.body.data))
   .update(createHash('sha256').update(__SECRET__, 'utf8').digest('hex'))
   .digest('hex');
```

For Webhook V2 version:

```javascript
import { createHash } from 'crypto';

request 'x-signature' header === createHash('sha256')
   .update(JSON.stringify(request.body))
   .update(createHash('sha256').update(__SECRET__, 'utf8').digest('hex'))
   .digest('hex');
```

{% hint style="info" %}
You can see how to make a signature in multiple programming languages [HERE](/v1/reference/signing-requests.md#request-examples)
{% 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.fonbnk.com/v1/off-ramp/webhook.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.
