Fonbnk Docs
  • Intro
  • Integration Guide
  • On-ramp
    • How it works
    • URL Parameters
    • Webhook
  • Off-ramp
    • How it works
    • URL Parameters
    • Webhook
  • Reference
    • Servers
    • Signing requests
    • Endpoints
      • On-ramp
        • Assets
        • Order
        • Orders
        • Price
        • Providers
        • Limits
      • Off-ramp
        • Order
        • Orders
        • Best offer
        • Limits
        • Countries
        • Wallets
        • Validate fields
        • Create order
        • Confirm order
      • Util
        • Check address
        • Assets
      • Kyc
        • State
        • Submit
    • Specification
Powered by GitBook
On this page
  1. Off-ramp

Webhook

PreviousURL ParametersNextServers

Last updated 2 months ago

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:

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,
    userPhoneNumber: 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
  OFFRAMP_RETRY = "offramp_retry", // we are retrying the off-ramp after a failed attempt
  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
}

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

Request headers:
x-signature: hash (string)

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:

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:

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');

Webhook V2:

Webhook verification:

You can see how to make a signature in multiple programming languages

​
​
​
HERE