Universal On-Ramp API Convert your users’ fiat into XRP or RLUSD on the XRPL. One POST request.
How it works 1 Send a checkout request POST to /api/v1/checkout with settlementCurrency and destinationAddress.
2 Customer pays XRPay returns a hosted checkout URL. The customer pays via card or bank transfer.
3 Funds settle on XRPL Settlement lands in the customer’s XRPL wallet as XRP or RLUSD.
Authentication Pass your publishable key in the apiKey body field. Test keys start with pk_test_, live keys with pk_live_.
Get your keys from Dashboard → API Keys .
Request POST /api/v1/checkout
Parameters Name Type Description apiKeyrequired string Your publishable API key. amountrequired number Fiat amount to charge. currencyrequired string Fiat currency code (USD, EUR, GBP). settlementCurrencyoptional string "XRP" or "RLUSD". Falls back to your org default. destinationAddressoptional string Customer’s XRPL r-address. If omitted, settles to your org wallet. skipTrustlineCheckoptional boolean Skip the pre-flight trustline validation. Default: false. orderIdoptional string Your internal order identifier. customerEmailoptional string Customer’s email for the receipt. callbackUrloptional string Redirect URL after payment completes. metadataoptional object Arbitrary key-value pairs. Returned in webhooks.
Example curl -X POST https://xrpay.it/api/v1/checkout \
-H "Content-Type: application/json" \
-d '{
"apiKey": "pk_test_abc123",
"amount": 50.00,
"currency": "USD",
"settlementCurrency": "RLUSD",
"destinationAddress": "rN7d471K2GfBkGQ2mNEjpg1C5e5w3KsMfq",
"orderId": "user-purchase-001"
}'
{
"sessionId": "txn_abc123",
"paymentUrl": "https://xrpay.it/pay/txn_abc123",
"settlementCurrency": "RLUSD",
"destinationAddress": "rN7d471K2GfBkGQ2mNEjpg1C5e5w3KsMfq",
"fiatAmount": 50.00,
"fiatCurrency": "USD",
"amount": 50.00,
"expiresAt": "2026-05-28T18:30:00.000Z",
"livemode": false
}
Trustline requirements Settling in RLUSD requires the destination wallet to have an active trustline to the RLUSD issuer before the checkout is created. Without it, the API returns 400.
If your app pre-validates trustlines, pass skipTrustlineCheck: true to bypass this check. XRP settlements don’t require trustlines.
Error codes Status Meaning 400Invalid currency, malformed address, or missing trustline. 401Invalid or missing API key. 500Internal server error.
Settlement notifications Two ways to know when funds land in the destination wallet.
1. Webhooks (recommended) Register an HTTPS endpoint to receive real-time events. Uses your secret key (sk_test_ / sk_live_), not your publishable key.
curl -X POST https://xrpay.it/api/v1/webhooks/register \
-H "Authorization: Bearer sk_test_your_secret_key" \
-H "Content-Type: application/json" \
-d '{
"url": "https://yourapp.com/webhooks/xrpay",
"events": ["payment.confirmed", "payment.failed"]
}'
When the XRPL transaction is validated, XRPay sends a payment.confirmed POST to your URL:
payment.confirmed payload Copy {
"event": "payment.confirmed",
"timestamp": "2026-05-28T18:32:14.000Z",
"webhook_id": "wh_abc123",
"data": {
"transaction_id": "txn_abc123",
"order_id": "user-purchase-001",
"fiat_amount": 50.00,
"fiat_currency": "USD",
"crypto_amount": 50.0,
"crypto_currency": "RLUSD",
"tx_hash": "A1B2C3D4E5F6...",
"from_address": "rXRPayHotWallet...",
"status": "confirmed",
"paid_amount": 50.0,
"paid_currency": "RLUSD"
}
}
The tx_hash is the on-ledger XRPL transaction hash. Verify it independently on any XRPL explorer or via the tx RPC command.
Available events for on-ramp flows:
Event Fires when payment.createdCheckout session created, awaiting customer payment. payment.confirmedXRPL transaction validated. Funds are in the destination wallet. payment.failedSession expired or payment could not be verified.
HMAC verification Every webhook carries an X-XRPay-Signature header. Verify it with the whsec_ secret returned at registration:
Node.js signature verification Copy const crypto = require("crypto");
function verifySignature(rawBody, signature, secret) {
const expected = "sha256=" +
crypto.createHmac("sha256", secret)
.update(rawBody)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
2. Status polling (fallback) If you can’t receive webhooks, poll the status endpoint:
GET /api/v1/status?paymentId=txn_abc123
Returns the current payment status. Poll every 5–10 seconds until status is confirmed or failed.
Try the live API in the interactive playground .