XPayr XPayr Merchant API v1
Official Documentation

XPayr Merchant API v1

Production-ready reference for merchant integrations: authentication, payment session lifecycle, webhook delivery, and balance reporting.

Base URL: https://xpayr.com/api/v1 Auth: Bearer sk_test_... / sk_live_... Format: JSON

Quick Start

1) Generate keys from merchant panel: /merchant/api-keys. 2) Use sk_test_... in Authorization header. 3) Create payment session. 4) Complete session and consume webhook.

curl -X GET "https://xpayr.com/api/v1/health"

Expected: {"status":"ok","version":"1.0.0" ...}

Authentication

All protected endpoints require an Authorization header.

Authorization: Bearer sk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Key Usage Notes
pk_test_... Public integrations Safe to expose where intended
sk_test_... Server-side API Never expose on frontend
pk_live_... Production public Generated in Live mode
sk_live_... Production server-side API Store in secret manager

Payments

POST/payments Create payment session

Required: amount, currency, network

{
  "amount": "9.99",
  "currency": "USDC",
  "network": "bsc-testnet",
  "order_id": "ORDER-1001",
  "description": "Test payment",
  "ipn_callback_url": "https://yourdomain.com/webhook/xpayr",
  "metadata": { "source": "api-doc" }
}
{
  "id": "ps_42f492dedc5b665b8511852de5ea0325",
  "invoice_id": 6265178012,
  "object": "payment_session",
  "amount": "9.99",
  "currency": "USDC",
  "network": "bsc-testnet",
  "status": "pending",
  "payment_url": "https://xpayr.com/pay/ps_42f492dedc5b665b8511852de5ea0325",
  "expires_at": "2026-02-12T16:00:00+00:00",
  "livemode": false
}
GET/payments List sessions with pagination
GET /payments?page=1&limit=25&status=pending&network=bsc-testnet
GET/payments/{id} Fetch session details
GET /payments/ps_42f492dedc5b665b8511852de5ea0325
POST/payments/{id}/complete Confirm payment after chain tx

Note: currently supports hosted checkout flow; tx fields required.

{
  "tx_hash": "0x1111111111111111111111111111111111111111111111111111111111111111",
  "from_address": "0x2222222222222222222222222222222222222222",
  "chain_id": 97
}

Merchant (Me)

GET/me

Returns merchant profile, public keys, status, plan and wallet.

GET/me/balance

Returns confirmed totals grouped by currency and network.

POST/me/keys/regenerate
{ "mode": "test" }

Response includes secret_key once. Save immediately.

GET/me/networks

Returns network + currency catalog for current key mode. Plugins use this to build dynamic Network/Currency dropdowns.

{
  "object": "network_catalog",
  "data": [
    {
      "network_key": "bsc-testnet",
      "network_name": "BSC Testnet",
      "is_testnet": true,
      "currencies": [
        { "symbol": "USDC", "display_name": "USDC", "decimals": 18 },
        { "symbol": "USDT", "display_name": "USDT", "decimals": 18 }
      ]
    }
  ],
  "livemode": false
}

AI Agent Commerce

Policy-driven bot payment flow for merchant-controlled agent transactions.

POST/agents Create agent identity + one-time secret key
{
  "name": "Auto Buyer Bot",
  "description": "Top-up automation",
  "mode": "test"
}
PUT/agents/{agent_public_id}/policy Configure limits + dynamic rule_set
{
  "allowed_tokens": ["USDT"],
  "allowed_networks": ["tron"],
  "max_tx_amount": 100,
  "daily_limit_amount": 500,
  "approval_threshold_amount": 50,
  "rule_set": [
    {
      "id": "block_high_risk",
      "priority": 10,
      "action": "reject",
      "categories": ["high_risk"],
      "reason_code": "blocked_high_risk_category"
    }
  ]
}
POST/agent-intents Runtime endpoint for agent keys (ag_test_*/ag_live_*)
{
  "amount": 20,
  "token": "USDT",
  "network": "tron",
  "target_ref": "order_123",
  "category": "normal"
}
{
  "object": "agent_intent_decision",
  "data": {
    "intent_id": "agi_xxx",
    "decision": "pending_approval",
    "reason_code": "manual_approval_required",
    "next_step": "awaiting_merchant_approval"
  }
}
POST/agent-approvals/{intent_id}/approve Approve and optionally auto-bridge to payment session
GET/agent-intents/summary Agent / intent / approval metrics summary

Full reference: /doc-api/agent-commerce-mode.md

Webhooks & IPN

Use webhooks for real-time payment status updates.

🚀 Multi-Store & Dynamic Webhooks (Recommended)
Instead of using a single global webhook URL, you can send an ipn_callback_url parameter when creating a payment session (POST /payments). If provided, XPayr will override your global webhook URL and send the IPN directly to this dynamic callback address. This allows a single Merchant Account to be used flawlessly across multiple websites (WooCommerce, Shopware, custom sites, etc.) simultaneously without webhook collisions.
POST/webhooks
{ "url": "https://yourdomain.com/webhooks/xpayr" }

URL must be HTTPS. Returns a webhook secret once.

GET/webhooks

Returns masked secret and supported event names.

POST/webhooks/test

Sends test payload to configured URL and stores delivery log.

DELETE/webhooks

Removes webhook URL and secret.

Signature Verification (PHP)

$payload = file_get_contents('php://input');
$header = $_SERVER['HTTP_X_XPAYR_SIGNATURE'] ?? '';
$secret = getenv('XPAYR_WEBHOOK_SECRET'); // from POST /webhooks response

$expected = 'sha256=' . hash_hmac('sha256', $payload, $secret);
if (!hash_equals($expected, $header)) {
    http_response_code(401);
    exit('Invalid signature');
}

http_response_code(200);
echo 'ok';

Plugins Integration

Use these patterns for WooCommerce, PrestaShop, OpenCart, Magento 2, Shopware 6, and Zen Cart modules.

Plugin Quickstart

1) Generate sk_test_... / sk_live_... key. 2) Pull dynamic catalog via GET /me/networks. 3) Create checkout via POST /payments. 4) Register callback via POST /webhooks. 5) Verify signature and map event status.

Recommended Callback URLs

Platform Callback URL
WooCommerce https://<domain>/?wc-api=wc_gateway_xpayr
PrestaShop https://<domain>/module/xpayr/ipn
OpenCart https://<domain>/index.php?route=extension/payment/xpayr/callback
Magento 2 https://<domain>/rest/V1/xpayr/ipn
Shopware 6 https://<domain>/api/xpayr/payment/notify
Zen Cart https://<domain>/ipn_xpayr.php

Canonical Create Session Payload

{
  "amount": "49.90",
  "currency": "USDC",
  "network": "bsc-testnet",
  "success_url": "https://merchant-site.com/success",
  "cancel_url": "https://merchant-site.com/cancel",
  "ipn_callback_url": "https://merchant-site.com/?wc-api=wc_gateway_xpayr",
  "metadata": {
    "source": "woocommerce",
    "order_id": "WOO-100045",
    "woocommerce_order_id": 100045,
    "customer_email": "[email protected]"
  }
}

Canonical Webhook Payload

{
  "id": "evt_xxxxxxxxxxxxx",
  "type": "payment.completed",
  "created": 1760000000,
  "livemode": false,
  "data": {
    "object": "payment_session",
    "session_id": "ps_42f492dedc5b665b8511852de5ea0325",
    "invoice_id": 6265178012,
    "status": "completed",
    "amount": "49.90",
    "currency": "USDC",
    "network": "bsc-testnet",
    "tx_hash": "0x1111...",
    "from_address": "0x2222...",
    "metadata": {
      "source": "woocommerce",
      "order_id": "WOO-100045"
    }
  }
}

Signature Verification

// Header:
// X-XPayr-Signature: sha256=<hmac>

$raw = file_get_contents('php://input');
$header = $_SERVER['HTTP_X_XPAYR_SIGNATURE'] ?? '';
$header = preg_replace('/^sha256=/', '', $header);
$expected = hash_hmac('sha256', $raw, $webhookSecret);

if (!hash_equals($expected, $header)) {
  http_response_code(401);
  exit('invalid signature');
}

Event Mapping (Recommended)

Event Target status
payment.completed, payment.confirmed Paid / Processing / Completed
payment.pending, payment.processing Pending (keep order open)
payment.failed Failed
payment.expired Cancelled / Expired

Fallback Sync & Idempotency

  • If webhook delivery fails, query GET /payments/{id} using stored session_id.
  • Store session_id and invoice_id on order/invoice meta at create time.
  • Before marking paid, check transaction id / session to avoid duplicate settlement.
  • Treat webhook callbacks as retryable; always return 2xx only after durable write.

Error Format

{
  "error": {
    "code": "validation_error",
    "message": "Missing required field: amount"
  }
}
HTTP Code Meaning
400 validation_error Invalid or missing payload field
401 authentication_required, invalid_api_key Auth missing/invalid
404 not_found Resource not found
422 webhook_delivery_failed style Business action failed
500 database_error, server_error Unhandled server issue

SDK-Style Examples

JavaScript (Node / Fetch)

const baseUrl = 'https://xpayr.com/api/v1';
const secretKey = process.env.XPAYR_SECRET_KEY; // sk_test_...

const res = await fetch(`${baseUrl}/payments`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${secretKey}`
  },
  body: JSON.stringify({
    amount: '19.99',
    currency: 'USDC',
    network: 'bsc-testnet',
    metadata: { order_id: 'ORDER-2026-001' }
  })
});
const data = await res.json();
console.log(data);

PHP (cURL)

$ch = curl_init('https://xpayr.com/api/v1/payments');
curl_setopt_array($ch, [
  CURLOPT_POST => true,
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => [
    'Content-Type: application/json',
    'Authorization: Bearer ' . $secretKey
  ],
  CURLOPT_POSTFIELDS => json_encode([
    'amount' => '19.99',
    'currency' => 'USDC',
    'network' => 'bsc-testnet'
  ])
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;