Skip to main content

Documentation Index

Fetch the complete documentation index at: https://neilyan.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

XPayLabs authenticates every API request using HMAC-SHA256 request signing. Unlike traditional Bearer token authentication, XPayLabs requires each request to include a cryptographic signature computed over the request payload. This ensures request integrity and prevents replay attacks.

How It Works

Every API request includes a ReqPayload wrapper with four fields:
FieldTypeDescription
signstringHMAC-SHA256 signature of the stringified data object
timestampintegerUnix timestamp (seconds) of when the request was created
noncestringA unique random string, never reused
dataobjectThe actual request payload
The sign field is computed using your merchant token as the HMAC secret key.

Computing the Signature

Algorithm

  1. Serialize the data object as a JSON string (no pretty-printing, no extra whitespace).
  2. Compute HMAC-SHA256(data_json, merchant_token).
  3. Convert the result to a lowercase hex string.
  4. Set this value as the sign field.

Node.js

import crypto from "crypto";

const MERCHANT_TOKEN = process.env.XPAYLABS_MERCHANT_TOKEN;

function signRequest(data) {
  const json = JSON.stringify(data);   // compact JSON, no extra whitespace
  return crypto
    .createHmac("sha256", MERCHANT_TOKEN)
    .update(json, "utf8")
    .digest("hex");
}

const request = {
  sign: signRequest({ amount: "100.00", symbol: "USDT", chain: "TRON" }),
  timestamp: Math.floor(Date.now() / 1000),
  nonce: crypto.randomUUID(),
  data: { amount: "100.00", symbol: "USDT", chain: "TRON" },
};

Python

import hmac
import hashlib
import json
import time
import uuid

MERCHANT_TOKEN = "your-merchant-token"

def sign_request(data: dict) -> str:
    json_str = json.dumps(data, separators=(",", ":"))  # compact JSON
    return hmac.new(
        MERCHANT_TOKEN.encode("utf-8"),
        json_str.encode("utf-8"),
        hashlib.sha256,
    ).hexdigest()

request = {
    "sign": sign_request({"amount": "100.00", "symbol": "USDT", "chain": "TRON"}),
    "timestamp": int(time.time()),
    "nonce": str(uuid.uuid4()),
    "data": {"amount": "100.00", "symbol": "USDT", "chain": "TRON"},
}

Go

package main

import (
    "crypto/hmac"
    "crypto/sha256"
    "encoding/hex"
    "encoding/json"
    "fmt"
    "time"
    "github.com/google/uuid"
)

func signRequest(data interface{}, token string) string {
    jsonBytes, _ := json.Marshal(data)
    mac := hmac.New(sha256.New, []byte(token))
    mac.Write(jsonBytes)
    return hex.EncodeToString(mac.Sum(nil))
}

func main() {
    data := map[string]interface{}{
        "amount":  "100.00",
        "symbol":  "USDT",
        "chain":   "TRON",
    }
    request := map[string]interface{}{
        "sign":      signRequest(data, "your-merchant-token"),
        "timestamp": time.Now().Unix(),
        "nonce":     uuid.New().String(),
        "data":      data,
    }
    fmt.Printf("%+v\n", request)
}
The JSON serialization must be compact — no spaces, no newlines between key-value pairs. Different JSON serializers may produce different output; always test your signature computation against a known working example.

Timestamp and Nonce Requirements

The timestamp and nonce fields prevent replay attacks:
  • Timestamp: Your server clock must be within 5 minutes of XPayLabs server time. Requests with timestamps older than 5 minutes are rejected.
  • Nonce: Each request must use a unique nonce. XPayLabs tracks used nonces and rejects duplicates. UUIDs or cryptographically random strings work well.

Verification (Server-Side)

XPayLabs verifies every request by recomputing the HMAC-SHA256 signature using your stored merchant token. If the signatures don’t match, or if the timestamp is outside the tolerance window, the request is rejected with a 401 Unauthorized response.

Keeping Your Merchant Token Secure

  • Store your merchant token in an environment variable or secrets manager.
  • Never hardcode the token in source code or client-side applications.
  • Rotate the token periodically and update your configuration.
  • The token is a shared secret between your merchant server and the XPayLabs gateway. It is not sent over the network in API requests.