XRPayDocs
SupportStart free
HomeDocumentationOn-Ramp API

Universal On-Ramp API

Convert your users’ fiat into XRP or RLUSD on the XRPL. One POST request.

How it works

  1. 1
    Send a checkout request

    POST to /api/v1/checkout with settlementCurrency and destinationAddress.

  2. 2
    Customer pays

    XRPay returns a hosted checkout URL. The customer pays via card or bank transfer.

  3. 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

NameTypeDescription
apiKeyrequiredstringYour publishable API key.
amountrequirednumberFiat amount to charge.
currencyrequiredstringFiat currency code (USD, EUR, GBP).
settlementCurrencyoptionalstring"XRP" or "RLUSD". Falls back to your org default.
destinationAddressoptionalstringCustomer’s XRPL r-address. If omitted, settles to your org wallet.
skipTrustlineCheckoptionalbooleanSkip the pre-flight trustline validation. Default: false.
orderIdoptionalstringYour internal order identifier.
customerEmailoptionalstringCustomer’s email for the receipt.
callbackUrloptionalstringRedirect URL after payment completes.
metadataoptionalobjectArbitrary key-value pairs. Returned in webhooks.

Example

Request
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"
  }'
Response 200 OK
{
  "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

StatusMeaning
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.

Register a webhook
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
{
  "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:

EventFires 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
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.