Skip to main content

Documentation Index

Fetch the complete documentation index at: https://developers.zerion.io/llms.txt

Use this file to discover all available pages before exploring further.

What you’ll build:
  • Get swap quotes from multiple liquidity sources in a single call
  • Receive ready-to-sign approve and swap transactions — no separate quote/execute steps
  • Bridge assets across chains (EVM ↔ EVM, EVM ↔ Solana)
Swap 0.05 ETH → DAI on Ethereum

  Quote 1 (Relay):
    Output:           128.45 DAI
    Min after slip:   125.88 DAI
    Net of fees:      $128.10
    ✅ Transaction ready to sign

  Quote 2 (LI.FI):
    Output:           128.12 DAI
    Min after slip:   125.56 DAI
    Net of fees:      $127.78
    ✅ Transaction ready to sign
Time: ~15 minutes

Prerequisites

  • A Zerion API key (get one here)
  • A wallet address with tokens to swap

How it works

Unlike most swap APIs that require separate quote and execute endpoints, the Zerion API combines both into a single call:
  1. Call GET /v1/swap/quotes/ with the sender, recipient, input asset, output asset, and amount
  2. Receive multiple quotes — each includes the expected output, fees, and (when executable) ready-to-sign transaction_approve and transaction_swap payloads
  3. Pick a quote and sign the transactions with your wallet
Quotes are returned best-first, sorted by the fiat value of output_amount_after_fees.
1
Get swap quotes
2
Use the swap and bridge quotes endpoint.
3
JavaScript
const API_KEY = process.env.ZERION_API_KEY;
const headers = {
  accept: "application/json",
  authorization: `Basic ${btoa(API_KEY + ":")}`,
};

// Swap 0.05 ETH → DAI on Ethereum
const wallet = "0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B";
const params = new URLSearchParams({
  from: wallet,
  to: wallet,
  "input[chain_id]": "ethereum",
  "input[fungible_id]": "eth",
  "input[amount]": "0.05", // human-readable decimal, not wei
  "output[fungible_id]": "0x6B175474E89094C44Da98b954EedeAC495271d0F", // DAI
});

const response = await fetch(
  `https://api.zerion.io/v1/swap/quotes/?${params}`,
  { headers }
);
const { data } = await response.json();

for (const quote of data) {
  const {
    liquidity_source,
    output_amount,
    minimum_output_amount,
    output_amount_after_fees,
    network_fee,
    error,
  } = quote.attributes;
  console.log(`\nQuote from ${liquidity_source.name}:`);
  console.log(`  Output:         ${output_amount.quantity}`);
  console.log(`  Min after slip: ${minimum_output_amount.quantity}`);
  console.log(`  Net of fees:    ${output_amount_after_fees.value} ${output_amount_after_fees.currency ?? ""}`);
  console.log(`  Network fee:    ${network_fee?.amount?.value ?? "n/a"}`);
  if (error) console.log(`  ⚠️  ${error.code}: ${error.message ?? error.hint}`);
}
Python
import os, requests

api_key = os.environ["ZERION_API_KEY"]
wallet = "0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B"

# Swap 0.05 ETH → DAI on Ethereum
response = requests.get(
    "https://api.zerion.io/v1/swap/quotes/",
    params={
        "from": wallet,
        "to": wallet,
        "input[chain_id]": "ethereum",
        "input[fungible_id]": "eth",
        "input[amount]": "0.05",  # human-readable decimal, not wei
        "output[fungible_id]": "0x6B175474E89094C44Da98b954EedeAC495271d0F",  # DAI
    },
    auth=(api_key, ""),
)

for quote in response.json()["data"]:
    attrs = quote["attributes"]
    print(f"\nQuote from {attrs['liquidity_source']['name']}:")
    print(f"  Output:         {attrs['output_amount']['quantity']}")
    print(f"  Min after slip: {attrs['minimum_output_amount']['quantity']}")
    after_fees = attrs["output_amount_after_fees"]
    print(f"  Net of fees:    {after_fees.get('value')} {after_fees.get('currency', '')}")
    if "error" in attrs:
        err = attrs["error"]
        print(f"  Note: {err['code']}{err.get('message') or err['hint']}")
cURL
curl -g -u "YOUR_API_KEY:" \
  "https://api.zerion.io/v1/swap/quotes/?from=0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B&to=0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B&input[chain_id]=ethereum&input[fungible_id]=eth&input[amount]=0.05&output[fungible_id]=0x6B175474E89094C44Da98b954EedeAC495271d0F"
4
Each quote includes:
5
  • liquidity_source — provider id, display name, and icon
  • input_amount / output_amount — what you’re sending and the estimated amount you’ll receive before slippage (quantity is the human-readable decimal; value / usd_value are fiat conversions when available)
  • minimum_output_amount — guaranteed output after slippage
  • output_amount_after_fees — net output once protocol, bridge, and network fees are subtracted; this is the field quotes are ranked by
  • slippage_percent — actual slippage applied (the slippage_percent query parameter when provided, otherwise auto-chosen)
  • protocol_fee / bridge_fee / network_fee — fee breakdown; each carries amount and an included_in_rate flag (whether already deducted from the rate)
  • transaction_approve — ERC-20 approve transaction to sign first. Absent when not needed (Solana, EVM native-asset input, or sufficient allowance already granted)
  • transaction_swap — swap transaction to sign. Absent when the quote is informational only (e.g. error is set)
  • error — present when the quote can’t be executed as-is (e.g. not_enough_input_asset_balance)
  • estimated_time_seconds — typically present on bridge routes
  • 6
    Pick a quote and check for errors
    7
    Quotes are returned best-first. Before signing, check whether the chosen quote has an error and a transaction_swap.
    8
    const quote = data[0]; // best by output_amount_after_fees
    const { error, transaction_approve, transaction_swap } = quote.attributes;
    
    if (error) {
      console.log(`Cannot execute: ${error.code} (hint: ${error.hint})`);
      process.exit(1);
    }
    if (!transaction_swap) {
      console.log("No transaction payload — informational quote only");
      process.exit(1);
    }
    
    9
    error.hint is a machine-readable next step (topup, increase_input_amount, unspecified) you can surface in your UI to guide the user.
    10
    Sign the approve transaction (if present)
    11
    If transaction_approve is present, sign and confirm it before submitting the swap. It’s a complete EVM transaction — no manual approve(spender, amount) call needed.
    12
    import { ethers } from "ethers";
    
    const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
    const signer = new ethers.Wallet(process.env.PRIVATE_KEY, provider);
    
    async function sendEVM(payload) {
      // EVM numeric fields are hex strings — ethers accepts them directly
      const tx = await signer.sendTransaction({
        type: parseInt(payload.type, 16),
        to: payload.to,
        data: payload.data,
        value: payload.value,
        gasLimit: payload.gas,
        nonce: parseInt(payload.nonce, 16),
        chainId: parseInt(payload.chain_id, 16),
        ...(payload.max_fee
          ? { maxFeePerGas: payload.max_fee, maxPriorityFeePerGas: payload.max_priority_fee }
          : { gasPrice: payload.gas_price }),
      });
      return tx.wait();
    }
    
    if (transaction_approve?.evm) {
      console.log("Sending approval...");
      await sendEVM(transaction_approve.evm);
      console.log("Approval confirmed");
    }
    
    13
    transaction_approve is omitted for Solana, for EVM swaps where the input is the chain’s native asset (ETH, MATIC, etc.), and when the wallet already has sufficient allowance.
    14
    Sign and send the swap transaction
    15
    const receipt = await sendEVM(transaction_swap.evm);
    console.log(`Confirmed in block ${receipt.blockNumber}`);
    
    16
    For Solana quotes, transaction_swap.solana.raw is a base64-encoded raw transaction that you decode and sign with the Solana wallet of your choice (e.g. @solana/web3.js).
    17
    Bridge assets across chains
    18
    To bridge tokens between chains, set a different output[chain_id]. The to parameter is the recipient on the destination chain — set it to your wallet on that chain (use a base58 Solana address when bridging to Solana).
    19
    # Bridge 1 USDC from Ethereum to Polygon
    curl -g -u "YOUR_API_KEY:" \
      "https://api.zerion.io/v1/swap/quotes/?from=YOUR_WALLET&to=YOUR_WALLET&input[chain_id]=ethereum&input[fungible_id]=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48&input[amount]=1&output[chain_id]=polygon&output[fungible_id]=0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359"
    
    20
    Use the List fungibles available for bridging endpoint to discover which tokens can be bridged between two specific chains before requesting quotes.

    Key parameters

    ParameterDescription
    fromWallet performing the swap. Must match the chain type of input[chain_id] (EVM hex or Solana base58). Required.
    toRecipient of the output asset. Must match the chain type of output[chain_id]. For a same-chain swap to the same wallet, set equal to from. Required.
    input[chain_id]Source chain (e.g., ethereum, polygon, solana). Required.
    input[fungible_id]Input asset’s fungible ID — either a Zerion fungible ID (e.g., eth) or the token contract address. Required.
    input[amount]Human-readable input amount as a decimal string (e.g., "0.05"), not the smallest unit. Required.
    output[chain_id]Destination chain. Defaults to input[chain_id] (same-chain swap).
    output[fungible_id]Output asset’s fungible ID or token contract address. Required.
    slippage_percentMaximum acceptable slippage in percent. Auto-chosen when omitted.
    currencyCurrency for fiat values in the response (e.g., usd). Defaults to usd.