📋 Overview

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

🎯 Integration Overview

The Merso 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 System

📋 Web3 API Endpoints

1. Health Check

Endpoint: GET /health
Purpose: Verify API connectivity and status

Request:

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

Response:

JSON
{
    "status": "ok",
    "timestamp": "2026-01-05T12:00:00.000Z"
}

JavaScript Example:

JavaScript
async function checkHealth() {
  const response = await fetch('https://api3.dev.merso.io/health');
  const data = await response.json();
  console.log('API Status:', data.status);
}

2. User Approval

Endpoint: POST /merso-user-approval
Purpose: Approve Merso System to spend user's ERC20 tokens. You can choose between PNPL or Upfront approve.

Request:

cURL
curl -X POST https://api3.dev.merso.io/merso-user-approval \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -d '{
    "userAddress": "0x...",
    "userEmail": "player@example.com",
    "tokenPrice": "1000000000000000000",
    "collectionAddress": "0x...",
    "paymentMode": "BNPL",
    "chainId": 137,
    "tokenAddress": "0x..."
  }'

Parameters:

Parameter Type Required Description
userAddress string Yes User's wallet address
userEmail string Yes User's in-game email
tokenPrice string Yes Amount to approve (in wei)
collectionAddress string Yes NFT collection contract address
paymentMode string No Payment mode: "BNPL" or "UPFRONT". Default: "BNPL"
chainId int No EVM chain ID. Uses default from game registration if not provided
tokenAddress string No ERC-20 token contract address. Uses default from game registration if not provided

Response:

JSON
{
    "success": true,
    "txData": {
        "to": "0x...",
        "from": "0x...",
        "data": "0x...",
        "gasPrice": "50000000000",
        "nonce": 42,
        "value": "0"
    }
}

JavaScript Example:

JavaScript
async function approveTokenSpending(userAddress, userEmail, tokenPrice, collectionAddress) {
  try {
    const response = await fetch('https://api3.dev.merso.io/merso-user-approval', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${jwtToken}`
      },
      body: JSON.stringify({
        userAddress,
        userEmail,
        tokenPrice,
        collectionAddress,
        paymentMode: 'BNPL'
      })
    });
    
    const approvalData = await response.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
    });
    
    await approvalTx.wait();
    console.log('Approval confirmed:', approvalTx.hash);
    
  } catch (error) {
    console.error('Approval failed:', error);
  }
}

3. Buy Token with Merso

Endpoint: POST /merso-buy-token
Purpose: Purchase NFT using Merso functionality. You can choose between PNPL or Upfront payment.

Request:

cURL
curl -X POST https://api3.dev.merso.io/merso-buy-token \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -d '{
    "userAddress": "0x...",
    "tokenId": "123",
    "tokenPrice": "1000000000000000000",
    "collectionAddress": "0x...",
    "paymentMode": "BNPL",
    "chainId": 137,
    "tokenAddress": "0x..."
  }'

Parameters:

Parameter Type Required Description
userAddress string Yes User's wallet address
tokenId string Yes NFT token ID to purchase
tokenPrice string Yes Total price in wei
collectionAddress string Yes NFT collection contract address
paymentMode string No Payment mode: "BNPL" or "UPFRONT". Default: "BNPL"
chainId int No EVM chain ID. Uses default from game registration if not provided
tokenAddress string No ERC-20 token contract address. Uses default from game registration if not provided

Response:

JSON
{
    "success": true,
    "txData": {
        "to": "0x...",
        "from": "0x...",
        "data": "0x...",
        "gasPrice": "50000000000",
        "nonce": 43,
        "value": "0"
    }
}

JavaScript Example:

JavaScript
async function buyNFTWithMerso(userAddress, tokenId, tokenPrice, collectionAddress, paymentMode, tokenAddress, chainId) {
  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,
        tokenId,
        tokenPrice,
        collectionAddress,
        paymentMode,
        tokenAddress,
        chainId
      })
    });

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

    const buyData = 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();
    console.log('Buy transaction confirmed:', buyTx.hash);

  } catch (error) {
    console.error('NFT purchase failed:', error);
  }
}

🔄 Integration Flow

Complete Purchase Flow

The complete flow involves two steps: first approve the token spending, then execute the purchase.

JavaScript
async function completePurchaseFlow(walletAddress, tokenId, tokenPrice, collectionAddress, paymentMode, tokenAddress, chainId) {
  try {
    // Step 1: Call 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: collectionAddress,
        paymentMode: paymentMode,
        tokenAddress: tokenAddress,
        chainId: chainId
      })
    });

    const approvalData = 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 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: collectionAddress,
        paymentMode: paymentMode,
        tokenAddress: tokenAddress,
        chainId: chainId
      })
    });

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

    const buyData = 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) {
    console.error('Transaction failed:', err.reason || err.message || 'Unknown error');
  }
}