CryptPal x402

API Documentation v1.0

← Back to App

πŸ“š Introduction

CryptPal x402 is a gasless payment system for digital content using USDC on Binance Smart Chain (BSC). It implements the HTTP 402 Payment Required status code to gate access to content behind cryptocurrency payments.

⚑

Gasless Payments

Users can pay without gas fees using deposited balance

πŸ”’

HTTP 402

Standard web protocol for payment-gated content

πŸ’Ž

USDC on BSC

Stable payments with low transaction costs

πŸš€ Quick Start

For Content Creators:

  1. Connect your BSC wallet
  2. Enter content URL and price in USDC
  3. Generate payment link
  4. Share link with customers
  5. Receive payments instantly

For Customers:

  1. Click payment link
  2. Connect wallet
  3. Choose payment method:
    • Gasless: From deposited balance (no gas fees)
    • Normal: Direct from wallet (~$0.10 gas)
  4. Access content immediately after payment

πŸ—οΈ Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Creator   │────1───▢│   Server    │────2───▢│  Database   β”‚
β”‚  (Wallet)   β”‚         β”‚  (Node.js)  β”‚         β”‚ (In-Memory) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                               β”‚
                               β”‚ 3. Payment Link
                               β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Customer   │────4───▢│   Relayer   │────5───▢│ Blockchain  β”‚
β”‚  (Wallet)   β”‚         β”‚   Wallet    β”‚         β”‚    (BSC)    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Flow:
1. Creator creates payment link
2. Server stores link data
3. Customer receives link
4. Customer deposits USDC to relayer
5. Relayer executes gasless payment on blockchain

πŸ”Œ API Endpoints

GET /

Serves the main application interface for creating payment links.

Response: HTML page

GET /pay?code={CODE}

Serves the payment interface with the specified payment code.

Query Parameters:

  • code (string, required): Unique payment identifier

Response: HTML payment page

GET /api/relayer-address

Returns the relayer wallet address for deposits.

Response:

{
  "address": "0x61C8A88dCE90C4Dc2EF04464b920C1f7299907db"
}
GET /api/balance?address={ADDRESS}

Returns the gasless balance for a specific wallet address.

Query Parameters:

  • address (string, required): BSC wallet address (0x...)

Response:

{
  "balance": 10.50
}
POST /api/create

Creates a new payment link for content.

Request Body:

{
  "content": "https://example.com/premium-content.pdf",
  "amount": 1.50,
  "wallet": "0x61C8A88dCE90C4Dc2EF04464b920C1f7299907db"
}

Response:

{
  "code": "abc123",
  "link": "http://localhost:3000/pay?code=abc123"
}
POST /api/deposit

Registers a USDC deposit to user's gasless balance.

Request Body:

{
  "address": "0x61C8A88dCE90C4Dc2EF04464b920C1f7299907db",
  "amount": 10.00,
  "txHash": "0x1234...abcd"
}

Response:

{
  "success": true,
  "balance": 10.00
}
POST /api/relay

Executes a gasless payment using deposited balance.

Request Body:

{
  "code": "abc123",
  "from": "0x61C8A88dCE90C4Dc2EF04464b920C1f7299907db"
}

Response:

{
  "success": true,
  "txHash": "0x5678...efgh",
  "newBalance": 8.50
}

Note: Deducts payment amount from user's gasless balance.

GET /api/pay?code={CODE}

Retrieves payment information or verifies payment completion.

Query Parameters:

  • code (string, required): Payment code

Request Headers (optional):

  • x402-payment (string): Transaction hash to verify payment

Response (without payment):

HTTP 402 Payment Required

{
  "amount": 1.50,
  "token": "USDC",
  "address": "0x61C8A88dCE90C4Dc2EF04464b920C1f7299907db",
  "network": 56,
  "message": "Payment required"
}

Response (with valid payment):

HTTP 200 OK

<!DOCTYPE html>
<html>
  <!-- Success page with content access -->
</html>

πŸ’° Payment Flow

Option 1: Gasless Payment

1. Customer deposits USDC to relayer
   POST /api/deposit
   { address, amount, txHash }
   
2. Server credits user's gasless balance
   USER_DEPOSITS[address] += amount
   
3. Customer initiates payment
   POST /api/relay
   { code, from: address }
   
4. Server deducts from balance
   USER_DEPOSITS[address] -= payment_amount
   
5. Relayer sends USDC on-chain
   relayerWallet.transfer(recipient, amount)
   (Server pays gas fees ~$0.20)
   
6. Server verifies and grants access
   GET /api/pay?code=xyz
   Headers: { x402-payment: txHash }
   
7. Customer receives content

Option 2: Normal Payment (with gas)

1. Customer initiates payment
   Direct USDC transfer via MetaMask
   
2. User confirms transaction
   (Pays ~$0.10 gas in BNB)
   
3. Transaction confirmed on-chain
   
4. Server verifies payment
   GET /api/pay?code=xyz
   Headers: { x402-payment: txHash }
   
5. Customer receives content

πŸ“œ Smart Contract Details

Token:

USDC (USD Coin)

Contract Address (BSC Mainnet):

0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d

Decimals:

6 (1 USDC = 1,000,000 units)

Network:

Binance Smart Chain (BSC) - Chain ID: 56

Used Functions:

// Transfer USDC from one address to another
function transfer(address to, uint256 amount) returns (bool)

// Check USDC balance of an address
function balanceOf(address account) view returns (uint256)

⚠️ Error Codes

400 Bad Request

Missing or invalid parameters

402 Payment Required

Content requires payment to access

500 Internal Server Error

Server-side error (relayer issues, blockchain errors)

Common Error Messages:

// Insufficient gasless balance
{
  "error": "Insufficient deposit. Need 1.5, have 0.5"
}

// Invalid payment code
{
  "error": "Invalid code"
}

// Relayer not configured
{
  "error": "Relayer not configured"
}

// Missing data in request
{
  "error": "Missing data"
}

βš™οΈ Configuration

Server Configuration (server.js):

// BSC RPC endpoint
const BSC_RPC = 'https://bsc-dataseed.binance.org/';

// USDC contract address on BSC
const USDC_ADDRESS = '0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d';

// Relayer wallet private key (funds gasless transactions)
const RELAYER_PRIVATE_KEY = '0xYOUR_PRIVATE_KEY_HERE';

// Server port
const PORT = 3000;

Frontend Configuration (dapp.html):

// USDC contract address
const USDC_ADDRESS = "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d";

// BSC Chain ID (hex)
const BSC_CHAIN_ID = "0x38";

// API endpoints
const API_URL = "/api/pay";
const CREATE_URL = "/api/create";
const RELAY_URL = "/api/relay";
const BALANCE_URL = "/api/balance";
const DEPOSIT_URL = "/api/deposit";

πŸ”’ Security Considerations

⚠️ Private Key Security

  • Never commit relayer private key to version control
  • Use environment variables for production
  • Keep minimal BNB balance (~0.1) for gas
  • Use a dedicated wallet only for relayer operations

πŸ’‘ Rate Limiting

Implement rate limiting to prevent abuse:

npm install express-rate-limit

const rateLimit = require('express-rate-limit');
const limiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 20
});

app.post('/api/relay', limiter, async (req, res) => {
  // ...
});

βœ… Transaction Verification

  • Always verify transaction hash on-chain before granting access
  • Check that transaction recipient matches expected address
  • Verify transaction amount matches payment requirement
  • Ensure transaction is confirmed (not pending)

🚨 Production Database

Current implementation uses in-memory storage. For production, use persistent database:

// Example with PostgreSQL
const { Pool } = require('pg');
const pool = new Pool({
  connectionString: process.env.DATABASE_URL
});

// Store deposit
await pool.query(
  'INSERT INTO deposits (address, balance) VALUES ($1, $2) ON CONFLICT (address) DO UPDATE SET balance = deposits.balance + $2',
  [address, amount]
);

πŸ’» Code Examples

JavaScript: Create Payment Link

const createPaymentLink = async () => {
  const response = await fetch('http://localhost:3000/api/create', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      content: 'https://example.com/premium-video.mp4',
      amount: 2.50,
      wallet: '0x61C8A88dCE90C4Dc2EF04464b920C1f7299907db'
    })
  });
  
  const data = await response.json();
  console.log('Payment link:', data.link);
  // Output: http://localhost:3000/pay?code=abc123
};

Python: Check Payment Status

import requests

def check_payment(code):
    response = requests.get(
        f'http://localhost:3000/api/pay',
        params={'code': code}
    )
    
    if response.status_code == 402:
        data = response.json()
        print(f"Payment required: {data['amount']} {data['token']}")
        return False
    elif response.status_code == 200:
        print("Payment completed! Content accessible")
        return True
    else:
        print(f"Error: {response.status_code}")
        return False

check_payment('abc123')

cURL: Register Deposit

curl -X POST http://localhost:3000/api/deposit \
  -H "Content-Type: application/json" \
  -d '{
    "address": "0x61C8A88dCE90C4Dc2EF04464b920C1f7299907db",
    "amount": 10.00,
    "txHash": "0x1234567890abcdef..."
  }'

πŸ§ͺ Testing

BSC Testnet Configuration:

// Use BSC Testnet for testing
const BSC_TESTNET_RPC = 'https://data-seed-prebsc-1-s1.binance.org:8545/';
const USDC_TESTNET = '0x...' // Deploy test token or use existing

// Add testnet to MetaMask:
Network Name: BSC Testnet
RPC URL: https://data-seed-prebsc-1-s1.binance.org:8545/
Chain ID: 97
Symbol: BNB
Block Explorer: https://testnet.bscscan.com

Getting Test BNB:

Local Testing:

# Start server
node server.js

# Open browser
http://localhost:3000

# Create payment link
1. Connect MetaMask
2. Fill form with test data
3. Generate link

# Test payment
1. Open payment link in new tab
2. Connect wallet
3. Deposit test USDC
4. Complete payment

πŸš€ Deployment

Prerequisites:

Installation:

# Clone repository
git clone https://github.com/your-repo/cryptpal-x402.git
cd cryptpal-x402

# Install dependencies
npm install express cors ethers@5.7.2

# Configure environment
cp .env.example .env
nano .env

# Set relayer private key
RELAYER_PRIVATE_KEY=0xYOUR_KEY_HERE
PORT=3000

# Start server
node server.js

Production with PM2:

# Install PM2
npm install -g pm2

# Start with PM2
pm2 start server.js --name cryptpal-x402

# Enable startup on boot
pm2 startup
pm2 save

# View logs
pm2 logs cryptpal-x402

# Monitor
pm2 monit

Nginx Configuration:

server {
    listen 80;
    server_name your-domain.com;
    
    # Redirect to HTTPS
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name your-domain.com;
    
    ssl_certificate /etc/ssl/certs/your-cert.pem;
    ssl_certificate_key /etc/ssl/private/your-key.pem;
    
    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

❓ FAQ

Q: Why BSC instead of Ethereum?

BSC offers lower transaction fees (~$0.10-0.20) compared to Ethereum ($5-50), making it more practical for small payments.

Q: How does gasless payment work?

Users deposit USDC to the relayer wallet once. The server then executes payments on their behalf using these deposits, paying the gas fees itself.

Q: Is my deposited USDC safe?

The relayer wallet is controlled by the server operator. Only deposit amounts you're comfortable with for gasless payments. For larger purchases, use the normal payment method.

Q: Can I get my deposited USDC back?

In the current version, deposits are stored in-memory and used for payments. For production, implement a withdrawal feature.

Q: What happens if a payment fails?

For gasless payments, the amount is refunded to your balance. For normal payments, the transaction simply fails and no USDC is deducted.

Q: Can I use other tokens besides USDC?

Yes, modify the USDC_ADDRESS constant to any BEP-20 token contract address. Adjust decimals accordingly (USDC uses 6, most tokens use 18).

Q: How much does the relayer need for gas?

Each gasless transaction costs ~$0.20 in BNB. With 0.1 BNB (~$60), you can process approximately 300 gasless payments.

Q: Can I customize the success page?

Yes, modify the HTML template in the server.js file under the `/api/pay` endpoint response.

πŸ”§ Troubleshooting

❌ "MetaMask not found"

  • Install MetaMask browser extension
  • Refresh the page after installation
  • Enable MetaMask for the site

❌ "Insufficient USDC"

  • Check your USDC balance in MetaMask
  • Ensure you're on BSC Mainnet (Chain ID: 56)
  • Add USDC token to MetaMask: 0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d
  • Buy USDC on Binance or PancakeSwap

❌ "Relayer not configured"

  • Set RELAYER_PRIVATE_KEY in server.js
  • Ensure private key starts with "0x"
  • Restart the server after configuration
  • Fund relayer wallet with ~0.1 BNB for gas

❌ Transaction fails / reverts

  • Check relayer has enough BNB for gas
  • Verify USDC contract address is correct
  • Ensure user has approved sufficient amount
  • Check BSC network status (bscscan.com)

❌ Balance shows incorrect amount

  • USDC uses 6 decimals (divide by 1,000,000)
  • Check the code uses: balance / 1e6
  • Use parseInt() before division to avoid floating point errors
  • Refresh the page to update balances

⚠️ "Deposit not showing up"

  • Wait for transaction confirmation (usually 5-10 seconds)
  • Check transaction on BSCScan
  • Verify you sent to correct relayer address
  • Deposits are stored in-memory - will reset on server restart

πŸ“‹ Changelog

v1.0.0 October 2025
  • Initial release
  • Gasless payment support via deposit system
  • Normal payment option with gas
  • HTTP 402 implementation
  • USDC on BSC support
  • Payment link generation
  • Balance tracking
v1.1.0 Planned
  • Persistent database (PostgreSQL)
  • Withdrawal feature for deposited funds
  • Multi-token support (BUSD, DAI, etc.)
  • Payment history dashboard
  • Webhook notifications
  • Rate limiting

πŸ“š Resources

βš–οΈ License

CryptPal x402 is released under the MIT License.

MIT License

Copyright (c) 2025 CryptPal

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.