Skip to content
LitVMSwapDocs
Open app
Developers / Swap API
Developers · API

Swap API

Three endpoints: list the tokens, get a quote, get a transaction. The API checks the V2 and V3 pools, picks the best route and hands you calldata for the swap entrypoint. You never have to think about pools.

The ground rules

  • Base URL: https://www.litvmswap.com/api
  • Auth: none. CORS is open, so browsers can call it directly.
  • Amounts: human-readable decimal strings like "0.5". The API applies the token's decimals for you.
  • Native zkLTC: use 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE.
  • Tokens: the API covers the tokens in /partner/tokens. Anything else comes back as a 404.
  • Chain: chainId defaults to 4441. You can leave it out.

List tokens

GEThttps://www.litvmswap.com/api/partner/tokens

Every token the Swap API can route, in a shape that's easy to drop into a token picker.

Terminal
curl https://www.litvmswap.com/api/partner/tokens
JSON
{
  "chainId": 4441,
  "tokens": [
    {
      "address": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
      "symbol": "zkLTC",
      "name": "zkLTC",
      "decimals": 18,
      "logoURI": "https://s2.coinmarketcap.com/static/img/coins/64x64/2.png",
      "isNative": true
    },
    {
      "address": "0x315374AA9b5536037Cc1Efeea2439CCC0913A77e",
      "symbol": "wzkLTC",
      "name": "Wrapped zkLTC",
      "decimals": 18,
      "logoURI": "https://assets.coingecko.com/coins/images/2/standard/litecoin.png?1696501400",
      "isNative": false
    }
  ]
}

Need richer metadata (verified flags, on-chain names)? The Token List API has it.

Get a quote

GEThttps://www.litvmswap.com/api/partner/quote

A read-only price check. Use it while the user types.

Query paramRequiredWhat it is
fromTokenyesAddress you sell. Native placeholder for zkLTC
toTokenyesAddress you buy
amountyesHow much you sell, in human units ("0.5")
partnerFeeBpsnoYour integrator fee in basis points, 0 to 500. Defaults to 10, so pass 0 if you don't charge one
chainIdnoDefaults to 4441
Terminal
curl "https://www.litvmswap.com/api/partner/quote?fromToken=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE&toToken=0xdf69970B2fE416339187aA41D39882e864984CE9&amount=0.5&partnerFeeBps=0"
JSON
{
  "fromToken": { "address": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "symbol": "zkLTC", "decimals": 18 },
  "toToken": { "address": "0xdf69970B2fE416339187aA41D39882e864984CE9", "symbol": "ZKUSDC", "decimals": 18 },
  "fromAmount": "0.5",
  "toAmount": "126.450390772208070106",
  "exchangeRate": "252.90078154441613",
  "partnerFeeBps": 0,
  "partnerFeeAmount": "0",
  "route": {
    "dexName": "OurV2",
    "poolType": "v2",
    "poolAddress": "0x5Ab5906CFBc21642A7f526521318bA33262E3954"
  },
  "spender": "0xF664B56933f3cF0d7d69982b5A8eC9101b80059D"
}
FieldMeaning
toAmountWhat the user gets, after fees, in human units
exchangeRatetoAmount / fromAmount
routeWhich pool the best route uses. poolType is v2 or v3
spenderWho needs an allowance if fromToken is an ERC-20
fee fieldsA breakdown of fees that are already taken out of toAmount
priceImpactNot calculated yet, always 0. Don't build logic on it

Build a swap transaction

POSThttps://www.litvmswap.com/api/partner/swap

Returns a transaction you can hand straight to a wallet. Send a JSON body:

Body fieldRequiredWhat it is
fromTokenyesAddress you sell
toTokenyesAddress you buy
amountyesAmount to sell, human units, as a string
userAddressyesThe wallet that signs. Bought tokens go here
slippagenoMax price movement you accept, in percent. Default 0.5
partnerFeeBpsnoYour fee, 0 to 500. Default 10
referrerAddressnoWhere your fee goes. No referrerAddress, no fee paid
chainIdnoDefaults to 4441
Terminal
curl -X POST https://www.litvmswap.com/api/partner/swap \
  -H 'content-type: application/json' \
  -d '{
    "fromToken": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
    "toToken": "0xdf69970B2fE416339187aA41D39882e864984CE9",
    "amount": "0.5",
    "userAddress": "0xYourWalletAddress",
    "slippage": 0.5,
    "partnerFeeBps": 0
  }'
JSON
{
  "transaction": {
    "to": "0xF664B56933f3cF0d7d69982b5A8eC9101b80059D",
    "data": "0xce1e7030…",
    "value": "500000000000000000",
    "chainId": 4441
  },
  "estimate": {
    "fromAmount": "0.5",
    "toAmount": "126.32",
    "minAmountOut": "125.69",
    "partnerFeeBps": 0
  },
  "spender": "0xF664B56933f3cF0d7d69982b5A8eC9101b80059D"
}
FieldMeaning
transaction.to / data / valueSend exactly these. value is in wei, as a string
estimate.toAmountExpected output after fees. This is the number to show before signing
estimate.minAmountOutThe least the user can receive. Below that, the swap reverts instead
spenderApprove this address when selling an ERC-20

The estimate object also carries a fee breakdown. Like with quotes, fees are already taken out of toAmount.

Quote vs swap numbers

/partner/quote is for live price display. /partner/swap is built for one exact transaction, so when the two differ a little, trust the /partner/swap estimate.

Wrapping and unwrapping

Swapping native zkLTC to wzkLTC (or back) skips routing. You get a direct deposit() or withdraw(uint256) call on the wzkLTC contract, 1:1, no fees.

Integrator fees

Building a wallet, bot or dApp? You can take a small cut of the swaps you send:

  1. Pass partnerFeeBps (basis points, 100 = 1%, max 500).
  2. Pass referrerAddress, the wallet that should receive it.

The fee comes out of the output token and lands in referrerAddress in the same transaction. Nothing to claim later. The contract refuses anything above 500 bps.

TypeScript
body: JSON.stringify({
  fromToken, toToken, amount, userAddress,
  partnerFeeBps: 25, // 0.25%
  referrerAddress: '0xYourFeeWallet',
})

Be upfront with your users about the fee. It shows up in estimate.toAmount either way.

Errors

Errors come back as JSON with an error field (and sometimes a message).

StatuserrorWhat to do
400Missing required parameters: ...Add the missing field
400Invalid partnerFeeBps: must be between 0 and 500 (5%)Keep it in range
400Invalid amount / Invalid userAddressCheck the format. Amount must be a positive number string
404Token not foundThe token isn't routed by the API. Check /partner/tokens
404No route found / No liquidity or route found for this pairNo pool path with enough liquidity. Try a smaller amount
500Internal server errorSomething on our side. Retry with backoff, then ping us

TypeScript types

Copy these if you like typed fetches:

TypeScript
export type ApiToken = { address: `0x${string}`; symbol: string; decimals: number }

export type QuoteResponse = {
  fromToken: ApiToken
  toToken: ApiToken
  fromAmount: string
  toAmount: string
  exchangeRate: string
  partnerFeeBps?: number // missing on wrap and unwrap quotes
  partnerFeeAmount?: string
  route: { dexName: string; poolType: 'v2' | 'v3' | string; poolAddress: `0x${string}` } | string
  spender: `0x${string}`
}

export type SwapResponse = {
  transaction: { to: `0x${string}`; data: `0x${string}`; value: string; chainId: number }
  estimate?: { fromAmount: string; toAmount: string; minAmountOut: string; partnerFeeBps: number }
  spender: `0x${string}`
}

export type ApiError = { error: string; message?: string }

route is the string "Direct (Wrap/Unwrap)" for wrap and unwrap quotes, and estimate is missing on wrap and unwrap transactions.