Insights

XRPL Swap API

Quote a swap, show the user the expected output, submit a Payment. This is the exact pipeline behind the xrpl.to swap widget, and you can call the same endpoints from your own app.

What the Swap API Solves

Raw XRPL gives you order books per pair and AMM pools per pair, but not a unified “what do I get if I sell X for Y” price that accounts for path-finding across both venues. That’s what /v1/dex/quote does — it walks the same path-finder the ledger will use at submission time and returns the expected output, price impact, and the route it picked. One call, one number, then render.

Two-Step Pipeline

  1. QuoteGET /v1/dex/quote returns expected output and impact for a proposed trade.
  2. Submit — sign a Payment with the quote’s numbers plus a slippage buffer, post to /v1/submit.

Quotes are free and cheap (10s edge cache). Submission always goes straight to the ledger through your signing flow — the API never touches a private key.

Get a Quote

GET https://api.xrpl.to/v1/dex/quote
  ?from=XRP
  &to=534F4C4F00000000000000000000000000000000.rsoLo2S1kiGeCcn6hCUXVrCpGMWLrRrLZz
  &amount=100

from and to use either XRP or currencyHex.issuer. amount is the input size. Typical response:

{
  "success":       true,
  "expectedOut":   "420.5",
  "priceImpact":   0.0041,        // 0.41%
  "route": [
    { "venue": "amm",   "pool": "rAMM...", "share": 0.72 },
    { "venue": "book",  "pair":  "XRP/SOLO", "share": 0.28 }
  ],
  "rate":          4.205,          // out per unit in
  "fresh_at":      1776519100
}

Build the Payment

Apply the user’s slippage tolerance (1% is a reasonable default, 0.1% for stables, 3%+ for thinly-traded tokens) and construct the tx. Set Amount to 2× the expected output to let path-finding consume all of SendMax without rounding dust — a safe pattern for MAX-style sells:

const slippage    = 0.01;
const expectedOut = parseFloat(quote.expectedOut);
const deliverMin  = expectedOut * (1 - slippage);

const tx = {
  TransactionType: 'Payment',
  Account:         userAddress,
  Destination:     userAddress,       // same-account = swap
  SendMax:         '100000000',       // 100 XRP in drops
  Amount: {
    currency: '534F4C4F00000000000000000000000000000000',
    issuer:   'rsoLo2S1kiGeCcn6hCUXVrCpGMWLrRrLZz',
    value:    String(expectedOut * 2) // 2x for safe routing
  },
  DeliverMin: {
    currency: '534F4C4F00000000000000000000000000000000',
    issuer:   'rsoLo2S1kiGeCcn6hCUXVrCpGMWLrRrLZz',
    value:    String(deliverMin)
  },
  Flags:     0x00020000,              // tfPartialPayment
  SourceTag: 161803                   // your platform tag
};

See the Payments engine spec for the full field reference including why the 2× Amount pattern works and which flags you need.

Sign and Submit

Sign client-side with xrpl.js, xrpl-py, or any wallet library. Never expose the seed to your server:

import { Wallet } from 'xrpl';

const wallet = Wallet.fromSeed(userSeed, {
  algorithm: userSeed.startsWith('sEd') ? 'ed25519' : 'secp256k1'
});
const signed = wallet.sign(tx);

await fetch('https://api.xrpl.to/v1/submit', {
  method:  'POST',
  headers: { 'Content-Type': 'application/json' },
  body:    JSON.stringify({ tx_blob: signed.tx_blob })
});

A 200 from /submit means the tx is in the mempool, not validated yet. Poll GET /v1/tx/<hash> until validated: true, then read meta.TransactionResulttesSUCCESS means settled.

Refresh Quotes as the User Types

Book prices move constantly. Re-quote when the input amount changes, when a token is re-selected, and on a 10s interval while the user is hovering the button. The quote endpoint is fast enough (typically <100ms) that debounce-on-input is unnecessary — fire on every keystroke past 2 characters.

Handling Edge Cases

  • tecPATH_DRY — no liquidity for the requested size. Show user “size too large” and suggest halving.
  • tecPATH_PARTIAL — partial fill when tfPartialPayment isn’t set. Re-submit with the flag on.
  • High price impact — if priceImpact > 3%, warn the user in the UI before signing.
  • Missing trustline on output token — detect by checking /v1/account/trustlines/<addr> and prompt a TrustSet first.

Rate Limits & Auth

Anonymous: 7 quotes/minute — enough to prototype. For any production app, get a free developer key (90/minute). Business and Enterprise tiers lift limits proportionally. The free tier covers most single-user wallets and small swap widgets out of the box.

Ship Your Swap Widget