API Documentationeer

Overview

This document will guide you step by step to implement our API service. Here is the API flow with its example.

You may need to refer to these environment URLs:

Sandbox: For testing and integration. No real money is involved.

Production: For live transactions with real customers.

You can have a look at the general sequence diagram.

API Key

Step 1: Add API Key to RequestAdd th

You will need to add API Key field to Header of every Requests as following:

"x-api-key": "api_key"

User Registeration flow

With this flow follow User path

Step 1: User Register

You will need to make a POST request to /api/v1/user/register

POST /api/v1/user/register

Resquest
{
	email: "[email protected]",
	walletAddress: "abcd...feg234"
}

Response
{
  status: "success",
  message: "User registered successfully",
  user: { id: 18, email: "[email protected]" }
}

Step 2: User KYC

User need to be KYC-ed to be able to make a payment. You will need to make a POST request to /api/v1/kyc/link

POST /api/v1/kyc/link

Request
{
  email: "[email protected]",
}

Response
{
	success: true ,
	message: "KYC external link generated successfully",
	websdkUrl: "https://linktokyc/websdk/p/example.com",
}

Payment Flow

With this flow follow Payment path

Step 1: Place Order

You will need to make a POST request to /api/v1/placeOrder

To test with VND please use this QR String:

qrString: "00020101021138560010A0000007270126000697040701128888123456780208QRIBFTTA53037045802VN63042249"

To test with PHP please use this QR String:

qrString: "00020101021127590012com.p2pqrpay0111UBPHPHMMXXX02089996440304121096459500755204601653036085802PH5925Sophia Marie Chavez Dever6009SAN PEDRO63043708"
POST /api/v1/placeOrder

Request
{
  qrString: "qrString",
  amount: 51000, #Please test with the amount higher than 50,000 VND or 10 PHP
  fiatCurrency: "VND",
  cryptoCurrency: "USDC",
  chain: "Solana",
  fromAddress: "fromWalletAddress"
}

Response
{
  orderId: "order_id_string",
  status: "awating_crypto_transfer",
  qrString: "qrString",
  fiatAmount: 20000,
  fiatCurrency: "VND",
  cryptoAmount: 0.8,
  cryptoCurrency: "USDC",
  exchangeRate: 26000,
  qrInfo: {
    encodedString: "qrString",
    providerInfo: {
      name: "VIETQR",
      guid: "A000000727",
      service: "QRIBFTTA"
    },
    bankInfo: {
      bankBin: "123456",
      bankNumber: "567891"
    },
    amount: 0,
    additionalData: "GaianWithLove"
  },
  cryptoTransferInfo: {
    chain: "Solana",
    fromAddress: "fromWalletAddress",
    toAddress: "toWalletAddress",
    token: "USDCAddress",
    amount: 800000,
    encodedTransaction: "encodedTransactionInstruction",
    amountInDecimal: 0.8,
    feeInfo: {
      feeToken: "feeTokenAddress",
      feeAmount: "feeAmount",
      feeAmountInDecimal: "feeAmountInDecimal"
    }
  },
  timestamp: "timeStamp"
}

Step 2: Build and Sign the Transaction

This will need to be perform on your side. You will need a build instruction function, example in TypeScript:

  decodeTransaction = async (
    data: PlaceOrderResponse
  ): Promise<Transaction> => {
    if (!this.solanaConnection)
      throw new Error(Solana connection not defined);

    const { blockhash } = await this.solanaConnection.getLatestBlockhash(
      confirmed
    );

    const transferInstruction = await buildSolanaSendTransactionInstruction(
      new PublicKey(data.cryptoTransferInfo.fromAddress),
      new PublicKey(data.cryptoTransferInfo.toAddress),
      new PublicKey(data.cryptoTransferInfo.token),
      data.cryptoTransferInfo.amount
    );

    // Create Legacy Transaction instead of VersionedTransaction
    const transaction = new Transaction();
    transaction.add(transferInstruction);
    transaction.recentBlockhash = blockhash;
    transaction.feePayer = new PublicKey(data.cryptoTransferInfo.fromAddress);

    return transaction;
  };

Then sign and submit the transaction to chain.

Step 3: Verify Order

After submitting the transaction to chain, you will need to make a POST request with the transaction hash (tx_Hash) hash and order Id ( order_id_string), to /api/v1/verifyOrder

POST /api/v1/verifyOrder

Request
{
	orderId: "order_id_string",
	transactionProof: "tx_Hash"
}

Response
{
	orderId: "order_id_string",
	status: "verified" , #List of status: awaiting_crypto_transfer, verified, processing, failed or completed
	transactionHash: "tx_Hash",
	message: "Transaction verified and bank transfer queued", 
	bankTransferStatus: "queued"
}

Step 4: Polling the Status

After the order is verified , it will be auto-processing. Then you will need to make a polling function to make a GET request to /api/v1/status after an amount of time

GET /api/v1/status

Request
{
	orderId: "order_id_string"
}

Response (Processing)
{
  id: 138,
  orderId: "order_id_string",
  status: "processing",
  fiatAmount: 20000,
  fiatCurrency: "VND",
  cryptoAmount: 0.8,
  cryptoCurrency: USDC,
  exchangeRate: 26000,
  qrInfo: {
    bankInfo: {
      bankBin: "123456",
      bankNumber: "567891"
    },
    providerInfo: {
      guid: "A000000727",
      name: "VIETQR",
      service: "QRIBFTTA"
    },
    encodedString: "qrString"
  },
  paymentMethod: "qr_code",
  expiresAt: "timeStamp",
  bankTransactionReference: {},
  createdAt: "timeStamp",
  updatedAt: "timeStamp",
  userId: null,
  transactionHash: "tx_Hash",
  pollCount: 24,
  lastChecked: "time"
}

Response (Completed)
{
  id: 138,
  orderId: "order_id_string",
  status: "completed",
  fiatAmount: 20000,
  fiatCurrency: "VND",
  cryptoAmount: 0.8,
  cryptoCurrency: USDC,
  exchangeRate: 26000,
  qrInfo: {
    bankInfo: {
      bankBin: "123456",
      bankNumber: "567891"
    },
    providerInfo: {
      guid: "A000000727",
      name: "VIETQR",
      service: "QRIBFTTA"
    },
    encodedString: "qrString"
  },
  paymentMethod: "qr_code",
  expiresAt: "timeStamp",
  bankTransactionReference: {
	  requestId: "require_id",
	  requestDate "timeStamp"
  },
  createdAt: "timeStamp",
  updatedAt: "timeStamp",
  userId: null,
  transactionHash: "tx_Hash",
  pollCount: 24,
  lastChecked: "time"
}

Additional API

Parse QR API

With this flow follow Payment path

You will need to make a POST request to /api/v1/parseQr

POST /api/v1/parseQr

Request
{
	qrString: "Qr_string",
	country: "VN"
}

Response
{
	success: true ,
	qrInfo: {
		isValid: true ,
		encodedString: "Qr_string",
		country: "VN",
		qrProvider: "VIETQR",
		bankBin:  "123456",
		accountNumber: "567891",
		currency: "704",
		nation: "VN",
		beneficiaryName: "NGUYEN VAN A",
		detailedQrInfo: {
			provider: {
			 fieldId:  "38",
			 guid:  "A000000727",
			 name:  "VIETQR",
			 data:  "data_string",
			 service:  "QRIBFTTA"
			},
			consumer: {
				bankBin:  "123456",
				bankNumber: "567891",
			},
			merchant: {
			
			},
			additionalData: {
			
			},
			version:  "01",
			initMethod:  "11",
			currency:  "704",
			nation:  "VN",
			crc:  "60C4"
		}
	},
}

Calculate Exchange

With this flow follow Payment path

Calculate cryptocurrency equivalent for fiat amount with current exchange rates

You will need to make a POST request to /api/v1/calculateExchange

POST /api/v1/calculateExchange

Request
{
  amount: 26000,
  country: "VN",
  chain: "Solana",
  token: "USDC"
}

Response
{
  success: true,
  exchangeInfo: {
    fiatAmount: 26000,
    fiatCurrency: "VND",
    cryptoAmount: "0.9846",
    cryptoCurrency: "USDC",
    exchangeRate: "26407.63793324218",
    chain: "Solana",
    token: "USDC",
    timestamp: "timeStamp",
    feeAmount: "fee_Amount"
  }
}

Get Transaction History

With this flow follow User path

By User Email

You will need to make a GET request to /api/v1/users/{User_Email}/orders

GET /api/v1/users/{User_Email}/orders

Request
{
	page: 1, (Optional)
	limit: 5, (Optional)
	status: "completed" (Optional)
}

Response
{
  status: "success",
  data: {
    user: {
      id: 12,
      email: "User_Email",
      walletAddress: "Wallet_Address",
      createdAt: "2025-09-15T04:28:20.451Z",
      updatedAt: "2025-09-15T05:33:57.873Z"
    },
    orders: {
      items: [], #Empty because there are no complete order
      pagination: {
        page: 1,
        limit: 5,
        total: 0,
        totalPages: 0,
        hasNext: false,
        hasPrev: false
      }
    }
  }
}

By User Wallet

You will need to make a GET request to /api/v1/users/wallet/{User_Wallet}/orders

GET /api/v1/users/wallet/{User_Wallet}/orders

Request
{
	page: 1, (Optional)
	limit: 5, (Optional)
	status: "completed" (Optional)
}

Response
{
  status: "success",
  data: {
    user: {
      id: 12,
      email: "User_Email",
      walletAddress: "Wallet_Address",
      createdAt: "2025-09-15T04:28:20.451Z",
      updatedAt: "2025-09-15T05:33:57.873Z"
    },
    orders: {
      items: [], #Empty because there are no complete order
      pagination: {
        page: 1,
        limit: 5,
        total: 0,
        totalPages: 0,
        hasNext: false,
        hasPrev: false
      }
    }
  }
}

API Reference

Register User

KYC User

Place Order

Verify Order

Get Order Status

Parse QR String

Calculate Exchange

Get User Transaction History

Last updated