NAV
python javascript php

Introduction

Welcome to HAYVN Pay API Documentation.

Endpoints:

SDK or API?

HAYVN Pay can be integrated into your website in either of two ways:

General Usage

Terminology

Term Meaning
Payment The core entity of HAYVN Pay.
A request for crypto from a merchant to a customer, which ultimately is converted to fiat.
Account Merchant Has customers who make deposits into their account
e.g. an FX trader
Purchase Merchant Has customers who buy goods and services
e.g. an online store,
  or bricks and mortar store with Point of Sale terminal
Tolerance Boundary for when crypto received is deemed to match required amount.
Only used by purchase merchants.
Expressed as a percentage of payment value.
e.g. I'll accept 0.25% below value as good enough.
   & anything 5% above is an overpayment.
Profiles Parts of a merchant's settings.
Controls how markups are applied and optionally specifies tolerances.

A typical payment lifecycle

Let's look at a simple crypto payment with HAYVN Pay.
This example uses the API, but the general flow applies equally to the SDK.

Suppose you are a merchant "Acme Corporation" with an online store, accepting payment in crypto.

  1. Your customer decides to buy an item for $100

  2. Your website gets the available crypto currencies + amounts to meet $100, shows to customer

  3. Customer chooses a currency and is shown a QR code to send crypto to

  4. Customer sends crypto from his wallet to that address

  5. HAYVN Pay notifies your website of the payment's progress

  6. Once complete, HAYVN Pay converts the crypto to fiat in your account & payment is Complete

  7. You can now take that $100 as a payout.

Crypto payment issues

Paying with crypto has considerations not found in traditional payment schemes.

This guide will talk through how you as a merchant can manage these considerations.

Market price movements

How you deal with price movements will depend on your type of business.

Market price movements for an account merchant

If you're an account merchant, accepting crypto to make deposits into a fiat account, you'll typically accept fiat at the current market price, regardless of whether this means an under or overpayment of the stated deposit amount.

To illustrate, suppose your customer decided to deposit $100 when bitcoin was at $1000/BTC.
He is told to transfer 0.1 BTC. However by the time the transfer has occurred, the price has dropped to $978/BTC.

The payment will still be deemed Complete, even though only $97.80 has been credited to the account. The customer will be informed of the final fiat value.

Market price movements for a purchase merchant

Price movements are a bigger problem if you're a purchase merchant.

An item being purchased has a given fiat value, regardless of any crypto pricing. You rely on the customer sending enough crypto to cover that fiat value, for the payment to be considered Complete. However, the customer should be insulated against minor price movements.

Minor price movements

To mitigate against minor changes, you may nominate tolerances on a HAYVN Pay profile.

Tolerances define a range of crypto that you will accept. If the market moves only within this range and the customer transfers the correct amount, the payment will be considered Complete.

For example, -1% / +5% means "Accept crypto 1% less than the payment value but more than 5% above the payment value is an overpayment".

You receive only $99.50, but it’s within tolerance so is close enough. The payment is Complete.

Adverse price drop

What if the market has dropped beyond the lower tolerance?

You cannot accept a fiat value well below the item price - instead, the customer is obliged to transfer further crypto.

After 0.1 BTC is initially sent, the payment is Incomplete.

If a further 0.002041 BTC is sent and the price doesn't change adversely, the payment will become Complete. Your account is credited with fiat using the current market price.

Large price rise

What if the market price has risen sharply?

If the value now exceeds the upper tolerance, HAYVN Pay will alert your website that the payment is now Overpaid.
How you deal with this is a commercial decision. The crypto is effectively held in escrow, waiting for your direction.

You may either:

  1. Refund the excess crypto back to the customer
  2. Refund all crypto back to the customer
  3. Manually convert all crypto to fiat, keeping the windfall
    or
  4. A mix of refunding crypto + converting to fiat

See the merchant console user guide for how to refund + convert to fiat manually.

Incorrect crypto transfers

Unlike conventional payment means (EFTPOS, credit card payments), we are reliant on the customer making the crypto transfer separately to the merchant's website.

This introduces some unique problems.

HAYVN Pay will send callbacks to your merchant website with as much information as possible to inform the customer of any problems.

Sometimes you will be able to use the merchant console to resolve a problem. Other times the payment support team must be contacted. See Contact link on the merchant console.

Incomplete crypto

We cannot control how much crypto a customer sends. If an insufficient amount is sent to cover a purchase price (whether deliberately or accidentally), HAYVN Pay will re-calculate how much is outstanding. The customer is then informed of the remaining amount.

Once enough has been sent, the payment is Complete.

Wrong currency

A customer may choose one crypto currency, but accidentally send another.

Most of the time, HAYVN Pay is unable to detect these incorrect currencies. If not, the payment will simply never become Complete. The customer will not be informed of his payment progressing as HAYVN Pay cannot “see” the wrong currency. You may be able to resolve this dilemma with our support team’s help.

If HAYVN Pay is able to detect the incorrect currency transaction, it will notify of the mismatch. You may refund the incorrect currency. The customer is then free to transfer the correct crypto.

Reused destination address

Nothing prevents a customer from accidentally (or intentionally) sending crypto to an address that has already been used for a past payment.

You can configure how HAYVN Pay handles address reuse in your merchant profile.

If you are an account merchant, turning Reuse Address on is advised: If more payments are made to the address of already Complete payment, a new payment entry is created in the merchant console for each and the fiat deposited into your account. No errors are raised.

However if you are a purchase merchant you would normally have Reuse Address left off: Once an earlier purchase payment is Complete, sending more crypto to the same address will mark the earlier purchase as Address Reused, an error state. It will then be up you as merchant to deal with the matter.

You could refund the new crypto to the customer. Alternatively if the customer has made a second purchase, the second payment could manually be marked Complete and the new crypto converted to fiat.

Timeouts

Like all internet based services, HAYVN Pay is at the mercy of network outages. If HAYVN Pay cannot process a payment due to an outage, it will inform your website with a callback.

If the customer has already sent crypto, the support team should be consulted to resolve the matter.

Available currencies

SDK

Follow these steps to offer crypto payments using HAYVN Pay SDK:

<script type="text/javascript"
    src="https://static.hayvnpay.com/static/js/sdk.js"></script>
<button class="hayvnpay-button"
    data-product="Blue Suede Shoes"
    data-amount="100"
    data-currency="USD"
    data-passthrough="Order 12345"
    data-show-payment-url="true">
      Click to buy
</button>
HayvnPaySDK.setup({
    account: '<YOUR_ACCOUNT_ID>',
    profile: '<YOUR_PROFILE_ID>',
    apiEndpoint: 'https://console.hayvnpay.com/',

    // Callbacks
    // onOpen: onNewPayment,
    // onUpdate: onPaymentUpdate,
    // onSuccess: onPaymentSuccess,
    // onIncomplete: onPaymentIncomplete,
    // onCancel: onPaymentCancel
})

// Callback example: 
// function onPaymentOpen(data, code) {
//   console.log(code, data)
// }

Important Note! Never fully rely on JavaScript / client-side data provided in onSuccess, onUpdate and onIncomplete events as it can easily be manipulated. When it comes to transactions data processing you should fully trust only server to server callbacks.

onOpen, onUpdate, onIncomplete, onSuccess, onCancel.

HayvnPay.destroy()

Live SDK example

Try clicking this button:

API Authentication

To sign requests, you can use following code:

import time
import base64
import hashlib
import hmac
import json
import requests

API_URL = 'https://api.hayvnpay.com'
API_KEY = 'my_api_key'
API_SECRET = 'my_api_secret'


def encode_hmac(key, msg, digestmod=hashlib.sha256):
    return hmac.new(key.encode(), msg=msg, digestmod=digestmod).hexdigest()

def hayvn_api_request(endpoint: str, payload: dict = None, method: str = 'GET'):
    nonce = str(int(time.time() * 1000))
    request_path = '/v1/%s/' % endpoint

    if payload:
        payload = json.dumps(payload)

    # Create signature data object. Keep order of keys as specified: 
    signature_data = {'path': request_path, 
                      'nonce': nonce, 
                      'payload': payload or ''}

    # Convert signature data to json + base64 format and create signature using your API_SECRET
    signature_data = json.dumps(signature_data, separators=(',', ':')).encode()
    b64 = base64.b64encode(signature_data)
    signature = encode_hmac(API_SECRET, b64)

    # Add your API key, nonce and signature to following headers
    request_headers = {
        'X-HAYVNPAY-KEY': API_KEY,
        'X-HAYVNPAY-NONCE': nonce,
        'X-HAYVNPAY-SIGNATURE': signature,
    }

    # Make request using payload JSON string as request body
    response = requests.request(method, API_URL + request_path, 
                                data=payload, headers=request_headers)
    return response.json()

profiles = hayvn_api_request('profiles')
print(json.dumps(profiles, indent=2))
const axios = require('axios');
const Base64 = require('js-base64').Base64;
const crypto = require('crypto');

const API_URL = 'https://api.hayvnpay.com';
const API_KEY = 'my_api_key';
const API_SECRET = 'my_api_secret';

function encode_hmac(key, msg) {
    return crypto.createHmac('sha256', key).update(msg).digest('hex');
}

function hayvn_api_request(endpoint, payload = null, method = 'GET') {
    const request_path = '/v1/' + endpoint + '/'
    const nonce = (new Date).getTime().toString()

    payload = typeof (payload) === 'object' && Object.keys(payload).length ?
        JSON.stringify(payload) : ''

    // Create signature data object. Keep order of keys as specified: 
    var signature_data = {
      path: request_path,
      nonce: nonce,
      payload: payload,
    }

    // Convert signature data to json + base64 format and create signature using your API_SECRET
    signature_data = JSON.stringify(signature_data)
    const b64 = Base64.encode(signature_data)
    const signature = encode_hmac(API_SECRET, b64)

    // Add your API key, nonce and signature to following headers
    let request_headers = {
        'X-HAYVNPAY-KEY': API_KEY,
        'X-HAYVNPAY-NONCE': nonce,
        'X-HAYVNPAY-SIGNATURE': signature,
    }

    return axios({
        method: method,
        url: API_URL + request_path,
        data: payload,
        headers: request_headers,
    })
}

hayvn_api_request('profiles').then(function (response) {
    console.log(response)
}).catch(function (error) {
    console.log(error)
});
<?php
function hayvnpay_api_request($endpoint, $payload = [], $method = 'GET'){
    $API_URL = 'https://api.hayvnpay.com';
    $API_KEY = 'your_api_key';
    $API_SECRET = 'your_secret';

    $request_path = '/v1/' . $endpoint . '/';
    $nonce = (string)round(microtime(true) * 1000);
    $payload = $payload ? json_encode($payload) : '';

    // Create signature data object. Keep order of keys as specified: 
    $signature_data = array(
        'path' => $request_path, 
        'nonce' => $nonce,
        'payload' => $payload,
    );

    // Convert signature data to json + base64 format and create signature using your API_SECRET
    $signature_data = json_encode($signature_data, JSON_UNESCAPED_SLASHES);
    $b64 = base64_encode($signature_data);
    $signature = hash_hmac('sha256', $b64, $API_SECRET);

    // Add your API key, nonce and signature to following headers
    $request_headers = [
        'X-HAYVNPAY-KEY: ' . $API_KEY,
        'X-HAYVNPAY-NONCE: ' . $nonce,
        'X-HAYVNPAY-SIGNATURE: ' . $signature,
    ];

    $result = file_get_contents($API_URL . $request_path, null, stream_context_create(array(
        'http' => array(
            'method' => $method,
            'header' => implode("\r\n", $request_headers),
            'ignore_errors' => true,
            'content' => $payload)
        )
    ));

    return $result;
}

$response = hayvnpay_api_request('profiles');
var_dump($response);

You can obtain API Keys by logging in and creating a key in Settings > API Keys. This will give you both an "API Key" that will serve as your user name, and an "API Secret" that you will use to sign messages.

All requests must contain a nonce, a number that will never be repeated and must increase between requests. This is to prevent an attacker who has captured a previous request from simply replaying that request. We recommend using a timestamp at millisecond or higher precision.

PAYLOAD

The payload for the POST requests must be a JSON string and must be put in the request body. You'll find more detailed Signature generation code in the examples. The following three headers are required to make requests to HAYVN API.

Header Value
X-HAYVNPAY-KEY Your HAYVN API Key
X-HAYVNPAY-NONCE Nonce
X-HAYVNPAY-SIGNATURE hex(HMAC_SHA256(base64(signature_data), key=api_secret))

Payments

Payments are time-sensitive payment requests addressed to specific buyers or payers. Payment has a unique receiving address and fixed price, typically denominated in fiat currency. It also has a BTC equivalent price, calculated by HAYVN Pay, with an expiration time of about 15 minutes.

List Payments

payments = hayvn_api_request('payments')
hayvn_api_request('payments').then(function(response) {
    console.log(response);
}).catch(function(error) {
    console.log(error);
});
$response = hayvnpay_api_request('payments');
var_dump($response);

The above command returns JSON structured like this:

{
    "pagination": {
        "num_pages": 1,
        "count": 12,
        "page": 1,
        "next_page": null,
        "previous_page": null,
        "per_page": 25
    },
    "result": [
        {
            "id": "e4f78557-7fb4-42da-89b2-6874d235c70d",
            "created_at": "2022-01-17T22:15:05.859322+00:00",
            "confirmed_at": "2022-01-18T14:50:05+00:00",
            "completed_at": null,
            "profile_id": "deb23315-1eae-46fe-929f-6f3067292493",
            "payment_currency": "BTC",
            "payment_amount": "0.00094700",
            "requested_currency": "USD",
            "requested_amount": "9.47000000",
            "address": "tb1qcq9ne8jjgnss4xyt2cdn37g674ngmfy07yum2g",
            "addresses": {
              "BTC": "tb1qcq9ne8jjgnss4xyt2cdn37g674ngmfy07yum2g"
            },
            "status": "confirmed",
            "paid_amount": {
              "crypto": {
                "currency": "BTC",
                "amount": "0.00094700"
              },
              "fiat": {
                "currency": "USD",
                "amount": "9.47000000"
              }
            },
            "conversion_fee": "0.04000000",
            "notes": null,
            "passthrough": "{\"order_id\":1642457702}",
            "transactions": [
              {
                "id": "2ceeeec5-acbf-4fed-98f3-99c364532322",
                "txid": "c5020b9615eaff5586f595655a22e8d61cf64161172811406d9c3801bd1e7b90",
                "amount": {
                  "crypto": {
                    "currency": "BTC",
                    "amount": "0.00094700"
                  },
                  "fiat": {
                    "currency": "USD",
                    "amount": "9.47000000"
                  }
                },
                "currency": "BTC",
                "created_at": "2022-01-17T22:16:03.399328+00:00",
                "confirmed_at": null,
                "url": "https://blockstream.info/testnet/tx/c5020b9615eaff5586f595655a22e8d61cf64161172811406d9c3801bd1e7b90"
              }
            ]
        }
    ]
}

This endpoint retrieves all payments. Endpoint uses pagination and returns 25 payments per page. Payments are sorted by creation time in descending order.

HTTP Request

GET https://api.hayvnpay.com/v1/payments/

Query Parameters

Parameter Default Description
p None Page number.
txid None Filter payments by txid
address None Filter payments by receiving address
status None Filter by status. Available values specified in Payment Statuses.

Get Payment

payment = hayvn_api_request('payments/0baa1b12-1d05-4ca1-b0fd-4c391e9d3b9f')
hayvn_api_request('payments/0baa1b12-1d05-4ca1-b0fd-4c391e9d3b9f').then(function(response) {
    console.log(response);
}).catch(function(error) {
    console.log(error);
});
$response = hayvnpay_api_request('payments/0baa1b12-1d05-4ca1-b0fd-4c391e9d3b9f');
var_dump($response);

The above command returns JSON structured like this:

{
    "result": {
        "id": "e4f78557-7fb4-42da-89b2-6874d235c70d",
        "created_at": "2022-01-17T22:15:05.859322+00:00",
        "confirmed_at": "2022-01-18T14:50:05+00:00",
        "completed_at": null,
        "profile_id": "deb23315-1eae-46fe-929f-6f3067292493",
        "payment_currency": "BTC",
        "payment_amount": "0.00094700",
        "requested_currency": "USD",
        "requested_amount": "9.47000000",
        "address": "tb1qcq9ne8jjgnss4xyt2cdn37g674ngmfy07yum2g",
        "addresses": {
           "BTC": "tb1qcq9ne8jjgnss4xyt2cdn37g674ngmfy07yum2g"
        }, 
        "status": "confirmed",
        "paid_amount": {
          "crypto": {
            "currency": "BTC",
            "amount": "0.00094700"
          },
          "fiat": {
            "currency": "USD",
            "amount": "9.47000000"
          }
        },
        "conversion_fee": "0.04000000",
        "notes": null,
        "passthrough": "{\"order_id\":1642457702}",
        "transactions": [
              {
                "id": "2ceeeec5-acbf-4fed-98f3-99c364532322",
                "txid": "c5020b9615eaff5586f595655a22e8d61cf64161172811406d9c3801bd1e7b90",
                "amount": {
                  "crypto": {
                    "currency": "BTC",
                    "amount": "0.00094700"
                  },
                  "fiat": {
                    "currency": "USD",
                    "amount": "9.47000000"
                  }
                },
                "currency": "BTC",
                "created_at": "2022-01-17T22:16:03.399328+00:00",
                "confirmed_at": null,
                "url": "https://blockstream.info/testnet/tx/c5020b9615eaff5586f595655a22e8d61cf64161172811406d9c3801bd1e7b90"
              }
            ]
    }
}

This endpoint retrieves a specific payment.

HTTP Request

GET https://api.hayvnpay.com/v1/payments/<ID>/

URL Parameters

Parameter Description
ID The ID of the payment to retrieve.

Create Payment

import json

payload = {
    "requested_currency": "USD",
    "requested_amount": "10",
    "payment_currency": "BTC",
    "profile_uuid": "deb23315-1eae-46fe-929f-6f3067292493",
    "passthrough": json.dumps({"order_id": 1642457702}),
    "notes": "this is demo"
}
payment = hayvn_api_request('payments', payload, 'POST')
print(json.dumps(payments, indent=2))
var payload = {
    "requested_currency": "USD",
    "requested_amount": "10",
    "payment_currency": "BTC",
    "profile_uuid": "deb23315-1eae-46fe-929f-6f3067292493",
    "passthrough": JSON.stringify({"order_id": 1642457702}),
    "notes": "this is demo"
}
hayvn_api_request('payments', payload, 'POST').then(function(response) {
    console.log(response);
}).catch(function(error) {
    console.log(error);
});
$payload = array(
    'requested_currency' => 'USD',
    'requested_amount' => '10',
    'payment_currency' => 'BTC',
    'profile_uuid' => 'deb23315-1eae-46fe-929f-6f3067292493',
    'passthrough' => json_encode(array('order_id' => 1642457702)),
    'notes' => 'this is demo',
);
$response = hayvnpay_api_request('payments/0baa1b12-1d05-4ca1-b0fd-4c391e9d3b9f');
var_dump($response);

JSON response for Create Payment endpoint:

{
    "result": {
        "id": "e4f78557-7fb4-42da-89b2-6874d235c70d",
        "created_at": "2022-01-17T22:15:05.859322+00:00",
        "confirmed_at": "2022-01-18T14:50:05+00:00",
        "completed_at": null,
        "profile_id": "deb23315-1eae-46fe-929f-6f3067292493",
        "payment_currency": "BTC",
        "payment_amount": "0.00094700",
        "requested_currency": "USD",
        "requested_amount": "9.47000000",
        "address": "tb1qcq9ne8jjgnss4xyt2cdn37g674ngmfy07yum2g",
        "addresses": {
          "BTC": "tb1qcq9ne8jjgnss4xyt2cdn37g674ngmfy07yum2g"  
        },
        "status": "confirmed",
        "paid_amount": {
          "crypto": {
            "currency": "BTC",
            "amount": "0"
          },
          "fiat": {
            "currency": "USD",
            "amount": "0"
          }
        },
        "conversion_fee": "0",
        "notes": null,
        "passthrough": "{\"order_id\":1642457702}",
        "transactions": []
    }
}

This endpoint creates an payment. Response is identical to Get Payment endpoint response.

HTTP Request

POST https://api.hayvnpay.com/v1/payments/

Payload Parameters

Parameter Description Required
profile_uuid Profile ID to use for settings, callback and wallet address generation. Yes
requested_currency Currency for the specified payment amount. Available values: USD, AED, AUD Yes
requested_amount Quoted decimal payment amount. Yes
payment_currency Currency for the specified payment amount. Available values: BTC, ETH, USDT. Yes
passthrough String. Meta-data you wish to store with the payment. Will be sent alongside all callbacks associated with the payment. No
notes Can be product or service name or any other notes. Visible in dashboard and in public payment link. No

Payment Statuses

Status Description
new A new payment has been created and a deposit address has been generated for the client to send their Crypto.
pending Transactions are found and are awaiting confirmations.
converting The Crypto amount received is within the accepted threshold and the conversion of the Crypto to FIAT has been initiated.
canceled_ The payment has been manually set to canceled by the user.
completed Payment conversion has finished and payment is now complete.
complete_ The payment has been manually set to complete by the user.
incomplete A Crypto deposit was made by the client, but the received amount is below the accepted threshold.
overpay A Crypto deposit was made by the client, but the received amount is above the accepted threshold.
address_reuse A Crypto deposit has been made to a wallet address that was used on a previously completed payment. It will require manual handling. This will only occur on profiles that do not allow address re-use.
conversion_failed Conversion from crypto to fiat has failed. Requires manual handling.

Payment Callbacks

Callbacks provide same exact response format as in Get Payment API endpoint in result field plus three extra fields specified in Callbacks Documentation.

You can view history of callbacks (if any) in HAYVN Pay in Payment detail view.

Payment Callback Statuses

Status Description
payment_pending Payment matches requested amount, has zero confirmations on blockchain (BTC only).
payment_converting Payment is received and it matches requested amount, conversion process from crypto into fiat has started.
payment_complete Conversion has finished and payment is now complete.
payment_incomplete Payment amount doesn't match profile "Allowed Difference" range. Requires manual handling.
payment_address_reuse Already previously complete payment address receives a new transaction and "Address Reuse" parameter for related profile is not enabled. Requires manual handling.
payment_conversion_failed Conversion from crypto to fiat has failed. Requires manual handling.

Payouts

Payouts are Fiat currency withdrawals or payments to External Bank Account.

List Payouts

payouts = hayvn_api_request('payouts')
hayvn_api_request('payouts').then(function (response) {
    console.log(response);
}).catch(function (error) {
    console.log(error);
});

This endpoint retrieves all payouts. Endpoint uses pagination and returns 25 payouts per page. Payouts are sorted by creation time in descending order.

HTTP Request

GET https://api.hayvn.com/v1/payouts/

Query Parameters

Parameter Default Description
p None Page number.

Get Payout

payout = hayvn_api_request('payouts/42dbee1d-8659-44c3-aab2-6e414c5825a5')
hayvn_api_request('payouts/42dbee1d-8659-44c3-aab2-6e414c5825a5').then(function (response) {
    console.log(response);
}).catch(function (error) {
    console.log(error);
});

This endpoint retrieves a specific payout.

HTTP Request

GET https://api.hayvn.com/v1/payouts/<ID>/

URL Parameters

Parameter Description
ID The ID of the payout to retrieve.

Create Payout

import json

payload = {
    "amount": "35.00000000",
    "currency": "USD",
    "notes": "Payout notes",
}
payout = hayvn_api_request('payouts', payload, 'POST')
print(json.dumps(payout, indent=2))

var payload = {
    "amount": "35.00000000",
    "currency": "USD",
    "notes": "Payout notes",
}

hayvn_api_request('payouts', payload, 'POST').then(function (response) {
    console.log(response);
}).catch(function (error) {
    console.log(error);
});

JSON response for Create Payout endpoint:

{
    "result": [
        {
            "id": "205eac49-963d-46b0-bac0-b41af5615c65",
            "remote_uuid": "8afd0ade-fbcd-49ed-be2e-0c4011bf12d8",
            "reference": "CHZ68OY0R3",
            "created_at": "2022-01-07T14:04:44+00:00",
            "from_wallet_uuid": "7c2c7e53-307d-40e1-90b9-275c583934b9",
            "to_wallet_uuid": "b00f8b70-36ac-4f84-9d79-62e88e939767",
            "amount": "35.00000000",
            "currency": "USD",
            "status": "pending",
            "notes": null
        }
    ]
}

This endpoint creates a payout. Response is identical to Get Payout endpoint response.

HTTP Request

POST https://api.hayvn.com/v1/payouts/

Payload Parameters

Parameter Description Required
currency Currency for the specified payout amount. Available values: USD, AED, AUD Yes
amount Quoted decimal payout amount. Yes
notes Optional notes on Payout No

Payout Statuses

Status Description
pending Payout is created and not settled.
completed Payout is settled.

Withdrawals

Withdrawals are Fiat currency withdrawals to External Digital Wallet.

List Withdrawals

withdrawals = hayvn_api_request('withdrawals')
hayvn_api_request('withdrawals').then(function (response) {
    console.log(response);
}).catch(function (error) {
    console.log(error);
});

This endpoint retrieves all withdrawals. Endpoint uses pagination and returns 25 withdrawals per page. Withdrawals are sorted by creation time in descending order.

HTTP Request

GET https://api.hayvn.com/v1/withdrawals/

Query Parameters

Parameter Default Description
p None Page number.

Get Withdrawal

withdrawal = hayvn_api_request('withdrawal/42dbee1d-8659-44c3-aab2-6e414c5825a5')
hayvn_api_request('withdrawal/42dbee1d-8659-44c3-aab2-6e414c5825a5').then(function (response) {
    console.log(response);
}).catch(function (error) {
    console.log(error);
});

This endpoint retrieves a specific withdrawal.

HTTP Request

GET https://api.hayvn.com/v1/withdrawal/<ID>/

URL Parameters

Parameter Description
ID The ID of the withdrawal to retrieve.

Create Withdrawal

import json

payload = {
    "fiat_currency": "USD",
    "fiat_amount": "500",
    "address": "2NCmwGXjgs822C1jXHJrUNda3DJu45YJ2jr",
    "currency": "BTC",
    "network": "BTC",
    "notes": "some notes",
}
withdrawal = hayvn_api_request('withdrawal', payload, 'POST')
print(json.dumps(withdrawal, indent=2))

var payload = {
    "fiat_currency": "USD",
    "fiat_amount": "500",
    "address": "2NCmwGXjgs822C1jXHJrUNda3DJu45YJ2jr",
    "currency": "BTC",
    "network": "BTC",
    "notes": "some notes",
}

hayvn_api_request('withdrawal', payload, 'POST').then(function (response) {
    console.log(response);
}).catch(function (error) {
    console.log(error);
});

JSON response for Create Withdrawal endpoint:

{
    "result": [
        {
            "id": "205eac49-963d-46b0-bac0-b41af5615c65",
            "remote_uuid": "8afd0ade-fbcd-49ed-be2e-0c4011bf12d8",
            "reference": "CHZ68OY0R3",
            "created_at": "2022-01-07T14:04:44+00:00",
            "profile_id": "deb23315-1eae-46fe-929f-6f3067292493",
            "address": "2NCmwGXjgs822C1jXHJrUNda3DJu45YJ2jr",
            "txid": null,
            "from_wallet_uuid": "7c2c7e53-307d-40e1-90b9-275c583934b9",
            "to_wallet_uuid": "b00f8b70-36ac-4f84-9d79-62e88e939767",
            "fiat_amount": "35.00000000",
            "fiat_currency": "USD",
            "currency": "BTC",
            "network": "BTC",
            "status": "pending",
            "notes": "some notes"
        }
    ]
}

This endpoint creates a withdrawal. Response is identical to Get Withdrawal endpoint response.

HTTP Request

POST https://api.hayvn.com/v1/withdrawals/

Payload Parameters

Parameter Description Required
fiat_currency Currency for the specified withdrawal amount. Available values: USD, EUR, GBP Yes
fiat_amount Quited decimal withdrawal amount. Yes
profile_id Profile ID for settings and callbacks. No
address Address of the recipient. Yes
currency Recipient address currency. BTC, ETH, USDT. Yes
network Recipient address network. BTC, ETH, BSC, TRX Yes
notes Optional notes on Withdrawal No

Withdrawal Statuses

Status Description
draft Withdrawal is created and not settled.
converting Converting fiat currency into desired cryptocurrency.
pending Waiting for withdrawal to be settled.
complete Withdrawal has been settled.
requires_confirmation Withdrawal made through API requires confirmation in Console app.
failed Withdrawal process failed.

Withdrawal Callbacks

Callbacks provide same exact response format as in Get Withdrawal API endpoint in result field plus three extra fields specified in Callbacks Documentation.

Withdrawal Callback Statuses

Status Description
withdrawal_pending Waiting for withdrawal to be settled.
withdrawal_converting Converting fiat currency into desired cryptocurrency.
withdrawal_complete Withdrawal has been settled.
withdrawal_requires_confirmation Withdrawal made through API requires confirmation in Console app.
withdrawal_failed Withdrawal process failed.

Callbacks

Callbacks are POST (as JSON encoded request body) requests made by HAYVN Pay to URL endpoint specified in Profile that was used for related payment creation.

Callback expects HTTP 200 OK success status response code. For any other status code or timeout it will try to reach endpoint again with exponential time increase between retries. If after 72 hours endpoint will be still unreachable callback sender will stop trying.

You can view history of callbacks in HAYVN App under every instance that have callbacks.

Callbacks Verification

import hashlib
import hmac
import json

# You will find your callback token under Settings
CALLBACK_TOKEN = 'your_callback_token'

# You can reuse same method used in API auth signature generation
def encode_hmac(key, msg, digestmod=hashlib.sha256):
    return hmac.new(key.encode(), msg=msg, digestmod=digestmod).hexdigest()

# Decode request json body
payload = json.loads(request.body)

# Get signature and callback_id fields from provided data
signature = payload['signature']
callback_id = payload['callback_id']

# Compare signatures
is_valid = signature == encode_hmac(CALLBACK_TOKEN, callback_id.encode())
assert is_valid, 'Failed to verify HAYVN Callback signature.'

# Debug callback data
print(json.dumps(payload, indent=2))
const Base64 = require('js-base64').Base64;
const crypto = require('crypto');

// You will find your callback token under Settings
const CALLBACK_TOKEN = 'your_callback_token';

// You can reuse same method used in API auth signature generation
function encode_hmac(key, msg) {
    return crypto.createHmac('sha256', key).update(msg).digest('hex');
}

// Decode request json body
var payload = JSON.parse(request.body);

// Get signature and callback_id fields from provided data
const signature = payload['signature'];
const callback_id = payload['callback_id'];

// Compare signatures
const is_valid = signature === encode_hmac(CALLBACK_TOKEN, callback_id);
if(!is_valid) {
    throw new Error('Failed to verify HAYVN Callback signature.');
}

// Debug callback data
console.log(payload);

To verify callback and make sure it really comes from HAYVN Pay you must use Callback Token which you can find in HAYVN App under Settings > API Keys.

Always verify if signature provided in callback POST data matches the one you generate on your own by signing callback_id value with callback_token using following hashing algorithm:

signature = hex(HMAC_SHA256(<callback_id>, key=<callback_token>))

Callbacks Response

All callbacks have these fields in common:

Key Meaning
callback_id Unique callback ID. If callback fails to reach endpoint, it will retry with the same ID.
callback_status Callback status identifying specific event.
signature HAYVN Signature for verification.

For event specific response documentation see Callback section under specific endpoint.

Errors

Error payload

Example of error response:

{
    "result": "error",
    "reason": "ObjectNotFound",
    "message": "Object by specified ID not found"
}

In the event of an error, a non-200 error code will be returned, and the response body will be a json object with three fields:

  1. result – which will always be "error".
  2. reason – which will be one of the string constants.
  3. message – a human-readable string with additional error information.

HTTP error codes

Error Code Meaning
400 Bad Request – Your request is invalid.
401 Unauthorized – Your API key or signature is wrong.
403 Forbidden – Not enough permissions.
404 Not Found – The specified page could not be found.
405 Method Not Allowed – You tried to access endpoint with an invalid method.
500 Internal Server Error – We had a problem with our server.
503 Service Unavailable – We're temporarily offline for maintenance.