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;