OOPPay API Documentation

OOPPay provides a simple, secure USDT-TRC20 payment solution. Integrate crypto payments into your application with our REST API in just a few minutes.

Quick Integration

Complete integration in 3 steps with real-time webhook notifications

Secure & Reliable

HMAC signature verification, 3-block confirmation, under 30 seconds

Low Fees

Only 0.5% transaction fee with network buffer

API Overview

Base URL:https://api.ooppay.io/api/v1
Confirmation time:Under 30 seconds (3 blocks)
Transaction fee:0.5%
Network buffer:~1.5 USDT

Authentication

OOPPay API uses API keys for authentication. You can manage your API keys in the merchant dashboard.

API Key Format

All API keys start with mk_MERCHANT_followed by a 32-character random string.

Authentication Example
Authorization: Bearer mk_MERCHANT_your_api_key_here

Security Notice

Keep your API keys secure and never expose them in client-side code. All API calls must be made over HTTPS.

Order Management

Create Payment Order

Create a new payment order. The system generates a unique payment address for each order.

Request

POST /api/v1/orders
POST /api/v1/orders
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json

{
  "merchant_order_id": "ORDER_20250122_001",
  "amount": "10.00",
  "callback_url": "https://your-site.com/webhook",
  "expire_minutes": 30
}

Response

200 - Success
{
  "order_id": "550e8400-e29b-41d4-a716-446655440000",
  "pay_address": "TN3W4H6rK2ce4vX9YnFQHwKENnHjoxb3m9",
  "pay_amount": "11.500000",
  "order_amount": "10.000000",
  "buffer_amount": "1.500000",
  "qr_code_url": "https://api.ooppay.io/qr/550e8400-e29b-41d4-a716-446655440000",
  "expire_at": 1737123456
}

Request Parameters

merchant_order_idYour order ID to associate with business orders
amountOrder amount in USDT (string format)
callback_url
Webhook URL for payment notifications
Recommended

Without this, you'll need to poll the order status API

expire_minutesOrder expiration time in minutes (default: 30)

Query Order Status

Query the current status of an order. We recommend using webhooks as the primary method for payment notifications, with queries as a backup.

GET /api/v1/orders/{order_id}
GET /api/v1/orders/550e8400-e29b-41d4-a716-446655440000
Authorization: Bearer mk_MERCHANT_your_api_key_here

Webhook Notifications

When payment status changes, we send webhook notifications to your specified callback_url. This is the recommended way to receive payment status updates.

Per-Order Webhook URLs

We use the callback_url from each order request. If no callback_url is provided, no webhook will be sent - you'll need to poll the order status API instead.

Webhook Format

Webhook Request
POST https://your-site.com/webhook
Content-Type: application/json
X-Signature: 5d41402abc4b2a76b9719d911017c592
X-Timestamp: 1737123456

{
  "order_id": "550e8400-e29b-41d4-a716-446655440000",
  "merchant_order_id": "ORDER_20250122_001",
  "status": "paid",
  "order_amount": "10.000000",
  "paid_amount": "11.500000",
  "net_amount": "9.950000",
  "fee_amount": "0.050000",
  "tx_hash": "7c2bb22f6d3c8c9b4fe8d3b4f5e6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4",
  "confirmations": 3,
  "paid_at": "2025-01-22T10:32:15Z"
}

Signature Verification

To ensure webhook security, we sign requests using HMAC-SHA256. You must verify the signature to ensure the request comes from OOPPay.

Signature Verification Code
const crypto = require('crypto');

function verifyWebhookSignature(payload, signature, timestamp, secret) {
  const { order_id, merchant_order_id, status } = payload;
  
  // Build signature data
  const data = order_id + merchant_order_id + status + timestamp;
  
  // Calculate expected signature
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(data)
    .digest('hex');
  
  return signature === expectedSignature;
}

// Handle Webhook
app.post('/webhook', express.json(), (req, res) => {
  const signature = req.headers['x-signature'];
  const timestamp = req.headers['x-timestamp'];
  
  if (!verifyWebhookSignature(req.body, signature, timestamp, WEBHOOK_SECRET)) {
    return res.status(400).send('Invalid signature');
  }
  
  if (req.body.status === 'paid') {
    // Handle successful payment
    console.log(`Order ${req.body.order_id} paid successfully`);
    deliverProduct(req.body.merchant_order_id, req.body.net_amount);
  }
  
  res.status(200).send('OK');
});

Best Practices

  • • Always verify webhook signatures
  • • Implement idempotent processing to avoid duplicates
  • • Return HTTP 200 status to acknowledge receipt
  • • Set appropriate timeout (recommend 5 seconds)

Error Handling

OOPPay API uses standard HTTP status codes to indicate request success or failure.

HTTP Status Codes

200Request successful
400Bad request parameters
401Invalid API key
404Resource not found
429Rate limit exceeded
500Internal server error

Error Response Format

Error Response Example
{
  "error": {
    "code": "invalid_request",
    "message": "Amount parameter must be positive",
    "details": {
      "field": "amount",
      "value": "-10.00"
    }
  }
}

Complete Integration Example

Here's a complete Node.js Express server example showing how to integrate OOPPay payment functionality.

server.js - Complete Example
const express = require('express');
const axios = require('axios');
const crypto = require('crypto');

const app = express();
app.use(express.json());

// Configuration
const CONFIG = {
  apiKey: 'YOUR_API_KEY',
  apiUrl: 'https://api.ooppay.io/api/v1',
  webhookSecret: 'YOUR_WEBHOOK_SECRET'
};

// Create payment order
app.post('/create-payment', async (req, res) => {
  try {
    const { orderId, amount } = req.body;
    
    const response = await axios.post(`${CONFIG.apiUrl}/orders`, {
      merchant_order_id: orderId,
      amount: amount.toString(),
      callback_url: 'https://your-domain.com/webhook',
      expire_minutes: 30
    }, {
      headers: {
        'Authorization': `Bearer ${CONFIG.apiKey}`,
        'Content-Type': 'application/json'
      }
    });
    
    res.json({
      success: true,
      data: response.data
    });
  } catch (error) {
    res.status(500).json({
      success: false,
      error: error.message
    });
  }
});

// Handle payment callback
app.post('/webhook', (req, res) => {
  const signature = req.headers['x-signature'];
  const timestamp = req.headers['x-timestamp'];
  
  // Verify signature
  if (!verifyWebhookSignature(req.body, signature, timestamp, CONFIG.webhookSecret)) {
    return res.status(400).send('Invalid signature');
  }
  
  // Handle successful payment
  if (req.body.status === 'paid') {
    console.log(`Payment successful for order ${req.body.order_id}`);
    console.log(`Net amount received: ${req.body.net_amount} USDT`);
    
    // Execute your business logic here
    deliverProduct(req.body.merchant_order_id, req.body.net_amount);
  }
  
  res.status(200).send('OK');
});

function verifyWebhookSignature(payload, signature, timestamp, secret) {
  const { order_id, merchant_order_id, status } = payload;
  const data = order_id + merchant_order_id + status + timestamp;
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(data)
    .digest('hex');
  return signature === expectedSignature;
}

function deliverProduct(orderId, amount) {
  // Implement your product delivery logic
  console.log(`Delivering product for order ${orderId}, amount: ${amount} USDT`);
}

app.listen(3000, () => {
  console.log('Server running on port 3000');
});

1. Install Dependencies

npm install express axios crypto

2. Start Server

node server.js