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
Infrastructure Modules
XPayr exposes merchant dashboard surfaces for advanced payment infrastructure. These modules
are designed around the non-custodial model: XPayr prepares, tracks, and reconciles payment operations while
merchant wallets remain responsible for signing and funding execution.
| Module |
Merchant panel |
Production note |
| Player Deposit Addresses |
/merchant/player-deposits |
Player mapping and webhook reconciliation first; dedicated address models require review. |
| Payout Hub |
/merchant/mass-payouts |
Batch preparation, browser-wallet signing, and tx hash tracking are available; server-side custody is not used. |
| Settlement Router |
/merchant/settlement-router |
Merchant preferences save to checkout runtime. Same-chain execution runs during checkout when a signed active route exists; cross-chain execution requires an active bridge route. |
| Fee Delegation |
/merchant/fee-delegation |
Merchant policy, relayer request queue, and ERC-2612 permit-based gasless settlement are available for supported token checkouts. Requests are accepted only when the policy is active and configured network, budget, and limit checks pass. |
| TRON USDT checkout |
tron-mainnet / USDT TRC-20 |
Hosted checkout uses the signed TRON split router. The payer wallet approves and sends USDT; TRON network fee and Energy are paid by the payer wallet, not by XPayr. XPayr records the 0.5% platform fee and merchant net settlement after confirmation. |
| Solana checkout |
solana-mainnet / SOL, USDC SPL, USDT SPL |
Hosted checkout uses the signed XPayr Solana split program. The payer signs a Solana wallet transaction; the program routes the 0.5% XPayr fee and merchant net amount on-chain to configured wallets. The payer wallet covers Solana network fees. |
| Fee Delegation Queue |
POST /payments/{session_id}/fee-delegation-request |
Creates a relayer request only when the merchant policy is active and network/budget limits pass. Merchant relayer and account-abstraction modes are auto-approved for merchant-side execution. |
| Gasless Settlement |
POST /payments/{session_id}/gasless-settlement |
Executes a relayed token settlement when the payer signs an EIP-2612 permit, a gasless router is deployed for the network, and the merchant Fee Delegation policy allows the payment. |
| Recurring Billing |
/merchant/recurring-billing |
Payment-link reminders first; wallet-authorized recurring billing is an advanced flow. |
For licensed iGaming, betting, poker, tournament, contest, or other high-risk merchants,
testnet access is open but mainnet activation remains controlled through merchant review.
Gasless settlement scope: full gasless checkout is available only for
token payments where the token supports ERC-2612 permit-style approvals and the merchant has an active
Fee Delegation policy. If the token does not support permit, hosted checkout automatically falls back to
the standard wallet transaction flow. If Fee Delegation is disabled for the merchant, the gasless option is
not shown in checkout.
TRON Energy note: TRON USDT checkout requires TRON Energy or TRX in the
payer wallet because USDT approval and split-router payment are on-chain contract calls. In the standard
checkout flow, XPayr does not pay this network cost per customer payment. Merchants need TRX or Energy only
for merchant-initiated actions such as their own swaps, payouts, contract administration, or sponsored-fee
programs.
Solana fee note: Solana SOL, USDC, and USDT checkout is executed by the
signed XPayr Solana split program. The payer wallet signs the payment transaction and pays the Solana
network fee. XPayr does not custody merchant funds or operate a withdrawal wallet for merchant settlement.
Settlement Router
Settlement Router lets a merchant define a preferred settlement asset, such as USDT, while
checkout still accepts the enabled token/network catalog. When an active reviewed route exists, hosted
checkout can prepare a signed router transaction that sends the merchant amount directly to the merchant
wallet and the XPayr platform fee directly to the configured platform wallet.
| Item |
Current behavior |
| Fee model |
Default platform fee is 50 bps, equal to 0.5% of the successful payment. |
| Custody |
XPayr does not hold merchant funds. Router execution settles on-chain to configured wallets. |
| TRON Energy |
For TRON USDT checkout, the payer wallet covers Energy/TRX for approval and payment. XPayr does not sponsor customer gas unless a separate merchant-sponsored fee program is enabled. |
| Solana network fees |
For Solana SOL, USDC, and USDT checkout, the payer wallet covers the Solana transaction fee. The signed split program routes fee and merchant net settlement on-chain. |
| Route controls |
Auto-convert routes require a deployed router contract, live liquidity, and slippage limits. Cross-chain routes require an active bridge route. |
| Ledger |
Router attempts and confirmed executions are logged in the settlement execution ledger for admin and merchant review. |
Hosted Checkout Runtime
When a payment session has a usable settlement route, the hosted checkout config includes
settlement_router. Merchants using the hosted page do not need to call this manually; custom
integrations can read it as execution metadata.
{
"settlement_router": {
"enabled": true,
"route_id": 20,
"source_currency": "USDC",
"target_currency": "USDT",
"source_network": "polygon-mainnet",
"target_network": "polygon-mainnet",
"execution_contract_address": "0x6cA4C9b1eD4d8E269FaE34775A83e333C818a975",
"router_address": "0xedf6066a2b290C185783862C7F4776A2C8077AD1",
"amount_in": "1000000",
"amount_out_min": "990000",
"platform_fee_bps": 50,
"merchant_wallet": "0x...",
"platform_wallet": "0x..."
}
}
Completion Payload
Hosted checkout posts normal transaction data to /payments/{id}/complete. If a
router route was used, router metadata is included and reconciled server-side.
{
"tx_hash": "0x...",
"from_address": "0x...",
"chain_id": 137,
"settlement_execution": {
"type": "settlement_router",
"route_id": 20,
"status": "submitted"
}
}
Production note: Same-chain swap routes are enabled only after quote
quality and contract compatibility checks. Cross-chain routing requires an active bridge route before
production activation for each merchant and network.
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;