Web3 API

This page shows you how to integrate Merso using Web3. This means that your players with pay the NFT using tokens or cryptocurrencies.

🎯 Integration Overview

The Merso BNPL API provides three core endpoints for game integration:

  • /health - API health check

  • /merso-user-approval - Approve ERC20 token spending

  • /merso-buy-token - Purchase NFT using Merso BNPL

📋 Web3 API Endpoints

1. Health Check

Endpoint: GET /health

Purpose: Verify API connectivity and status

Request:

curl -X GET "https://api3.dev.merso.io/health"

Response:

{
  "success": true,
  "message": "Hello World, Merso BNPL Backend",
}

JavaScript Example:

async function checkAPIHealth() {
  try {
    const response = await fetch(`https://api3.dev.merso.io/health`, {
      method: 'GET',
      headers: headers
    });
    
    const data = await response.json();
    console.log('API Status:', data.status);
    return data;
  } catch (error) {
    console.error('Health check failed:', error);
  }
}

2. User Approval

Endpoint: POST /merso-user-approval

Purpose: Approve Merso BNPL to spend user's ERC20 tokens

Request :

curl -X POST "https://api3.dev.merso.io/merso-user-approval" \
  -H "Authorization: Bearer <your_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "userAddress": "VALID_USER_ADDRESS",
    "userEmail": "user@email.com",
    "tokenPrice": "PRICE_IN_WEI",
    "collectionAddress": "YOUR_GAME_ERC721_ADDRESS"
}'

Parameters:

  • userAddress (string): User's wallet address

  • userEmail (string): User's in-game email

  • amount (string): Amount to approve (in wei)

Response:

{
  "success": true,
  "txData": {
    "to": "YOUR_GAME_ERC20_ADDRESS",
    "from": "VALID_USER_ADDRESS",
    "data": "0xa9059cbb000000000000000000000000...",
    "gasPrice": "20000000000",
    "nonce": 5,
    "value": "0"
  },
}

JavaScript Example:

async function approveTokens(userAddress, userEmail, tokenPrice, collectionAddress) {
  try {
	const approvalResponse = await fetch(
        `https://api3.dev.merso.io/merso-user-approval`,
        {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
            Authorization: `Bearer ${jwtToken}`,
          },
          body: JSON.stringify({
            userAddress: userAddress,
            userEmail: userEmail,
            tokenPrice: tokenPrice,
            collectionAddress: collectionAddress
          }),
        }
      );
    
      if (!approvalResponse.ok) {
        throw new Error("Approval API request failed");
      }
      const approvalData: ApiResponse = await approvalResponse.json();
      
      // Execute approval transaction
      const approvalTx = await signer.sendTransaction({
        to: approvalData.txData.to,
        from: approvalData.txData.from,
        data: approvalData.txData.data,
        gasPrice: approvalData.txData.gasPrice,
        nonce: approvalData.txData.nonce,
        value: approvalData.txData.value,
      });

      // Wait for approval transaction to be mined
      await approvalTx.wait();

  } catch (error) {
    console.error('Approval failed:', error);
    throw error;
  }
}

3. Buy Token with Merso

Endpoint: POST /merso-buy-token

Purpose: Purchase NFT using BNPL functionality

Request:

curl -X POST "https://api3.dev.merso.io/merso-buy-token" \
  -H "Authorization: Bearer <your_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "userAddress": "VALID_USER_ADDRESS",
    "tokenId": "1",
    "tokenPrice": "PRICE_IN_WEI",
    "collectionAddress": "YOUR_GAME_ERC721_ADDRESS"
}'

Parameters:

  • userAddress (string): User's wallet address

  • tokenId (string): NFT token ID to purchase

  • tokenPrice (string): Total price in wei

  • collectionAddress (string): NFT collection contract address

Response:

{
  "success": true,
  "txData": {
    "to": "YOUR_BNPL_ADDRESS",
    "from": "VALID_USER_ADDRESS",
    "data": "0x...",
    "gasPrice": "20000000000",
    "nonce": 6,
    "value": "0"
  },
}

JavaScript Example:

async function buyNFTWithMerso(userAddress, tokenId, tokenPrice, collectionAddress) {
  try {
    const buyResponse = await fetch(`https://api3.dev.merso.io/merso-buy-token`, {
      method: 'POST',
      headers: {
            "Content-Type": "application/json",
            Authorization: `Bearer ${jwtToken}`,
          },
      body: JSON.stringify({
        userAddress: userAddres,
        tokenId: tokenId,
        tokenPrice: tokenPrice,
        collectionAddress: collectionAddress
      })
    });
    
      if (!buyResponse.ok) {
        throw new Error("Buy API request failed");
      }

      const buyData: ApiResponse = await buyResponse.json();
      
      // Execute buy transaction
      const buyTx = await signer.sendTransaction({
        to: buyData.txData.to,
        from: buyData.txData.from,
        data: buyData.txData.data,
        gasPrice: buyData.txData.gasPrice,
        nonce: buyData.txData.nonce,
        value: buyData.txData.value,
      });

      // Wait for buy transaction to be mined
      await buyTx.wait();
      
  } catch (error) {
    console.error('NFT purchase failed:', error);
    throw error;
  }
}

🔄 Integration Flow

Complete Purchase Flow

  const handleBuy = async (tokenId: number, userEmail: string, price: string) => {

	if (!window.ethereum || !walletAddress) return;
    setIsLoading(true);
    setError("");

	try {
      const provider = new ethers.BrowserProvider(window.ethereum as any);
      const signer = await provider.getSigner();
      const tokenPrice = ethers.parseEther(price).toString();

      // Step 1: Call your API for approval transaction
      const approvalResponse = await fetch(
        `https://api3.dev.merso.io/merso-user-approval`,
        {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
	    Authorization: `Bearer ${jwtToken}`
          },
          body: JSON.stringify({
            userAddress: walletAddress,
            userEmail: userEmail,
            tokenPrice: tokenPrice,
            collectionAddress: YOUR_ERC721_ADDRESS,
          }),
        }
      );

      if (!approvalResponse.ok) {
        throw new Error("Approval API request failed");
      }

      const approvalData: ApiResponse = await approvalResponse.json();

      if (!approvalData.success) {
        throw new Error("Approval API returned error");
      }

      // Execute approval transaction
      const approvalTx = await signer.sendTransaction({
        to: approvalData.txData.to,
        from: approvalData.txData.from,
        data: approvalData.txData.data,
        gasPrice: approvalData.txData.gasPrice,
        nonce: approvalData.txData.nonce,
        value: approvalData.txData.value,
      });

      // Wait for approval transaction to be mined
      await approvalTx.wait();
      console.log("Approval transaction confirmed:", approvalTx.hash);

	  // Step 2: Call your API for buy transaction
      const buyResponse = await fetch(
        `https://api3.dev.merso.io/merso-buy-token`,
        {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
	    Authorization: `Bearer ${jwtToken}`
          },

          body: JSON.stringify({
            userAddress: walletAddress,
            tokenId: tokenId,
            tokenPrice: tokenPrice,
            collectionAddress: MOCK_ERC721_ADDRESS, 
          }),
        }
      );

      if (!buyResponse.ok) {
        throw new Error("Buy API request failed");
      }

      const buyData: ApiResponse = await buyResponse.json();

      if (!buyData.success) {
        throw new Error("Buy API returned error");
      }

      // Execute buy transaction
      const buyTx = await signer.sendTransaction({
        to: buyData.txData.to,
        from: buyData.txData.from,
        data: buyData.txData.data,
        gasPrice: buyData.txData.gasPrice,
        nonce: buyData.txData.nonce,
        value: buyData.txData.value,
      });

      // Wait for buy transaction to be mined
      await buyTx.wait();
      console.log("Buy transaction confirmed:", buyTx.hash);

    } catch (err: any) {
      setError(
        "Transaction failed: " +
          (err?.reason || err?.message || "Unknown error")
      );
      console.error(err);
    }
    setIsLoading(false);
  };

🪄 Optional endpoints

Endpoint: GET /user-loans

Purpose: Retrieves loan information for a specific user

Request:

curl -X GET "https://api3.dev.merso.io/user-loans?userEmail=USER_EMAIL" \
  -H "Authorization: Bearer <your_token>"

Parameters:

  • userId (string): User's ID

Response:

{
    "loans": [
        {
            "id": "67829bea-00ef-45eb-bc23-0d6798e048f5",
            "user_id": "USER_ID",
            "collection_id": "19d210ae-5836-4cf0-ad7a-8d8a6b0f08b3",
            "nft_id": "nftCromo2",
            "initial_payment_usd": 250,
            "splits_left_no": 4,
            "price_usd": 500,
            "paid_status": 1,
            "game_id": "e6d8a143-3d70-45e2-9e4c-75ff7805e0fd",
            "initial_splits_payments": 2,
            "initial_payment_token": 2500000000000000000,
            "price_token": 5000000000000000000,
            "wallet_address": "0x1234567890ABCDEF1234567890ABCDEF12345678",
            "created_at": "2025-07-28T08:02:57.744Z",
            "paid_date": "2025-07-29T05:00:54.838Z"
        }
    ]
}

Example Usage

Here's an example of how you can call the GET /user-loans endpoint using JavaScript:

const fetchUserLoans = async (userId, jwtToken) => {
  try {
    const response = await fetch(`https://api3.dev.merso.io/user-loans?userEmail=${userEmail}`, {
      method: 'GET',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${jwtToken}`
      }
    });

    if (!response.ok) {
      throw new Error(`Error: ${response.statusText}`);
    }

    const data = await response.json();
    console.log('User Loans:', data);
    return data;
  } catch (error) {
    console.error('Failed to fetch user loans:', error);
    throw error;
  }
};

// Example usage
const userEmail = 'USER_EMAIL';
const jwtToken = 'YOUR_JWT_TOKEN';

fetchUserLoans(userId, jwtToken)
  .then(loans => {
    console.log('Loans data:', loans);
  })
  .catch(error => {
    console.error('Failed to get loans:', error);
  });

Last updated