> For the complete documentation index, see [llms.txt](https://docs.nabla.fi/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.nabla.fi/developers/swap-api.md).

# Swap API

## Overview <a href="#overview" id="overview"></a>

The [**Nabla Finance Swap API**](https://swap-api.nabla.fi/) provides an efficient on-chain routing system that enables users and developers to perform token swaps directly through the [**Nabla Portal**](/developers/contract-interfaces/nablaportal.md) smart contracts. Unlike centralized or custodial aggregators, Nabla operates entirely on-chain — ensuring transparent, verifiable execution and predictable pricing.

The API serves as a simple interface layer to generate calldata and quotes for Nabla Portal transactions. It leverages live price feeds streamed from the **Nabla Antenna** to ensure that all swaps are priced against the most recent on-chain oracle data.

### **Key benefits**

* **Accurate real-time pricing:** The API uses Nabla’s live price update feed to provide the freshest oracle-signed price data for all supported tokens.
* **Single-hop efficiency:** Swaps are executed directly through the Nabla Portal without routing across multiple DEXes, minimizing gas usage and reducing latency.
* **Secure execution:** All calldata is generated server-side using verified price data and passed directly to the Nabla smart contracts — ensuring transparent, deterministic execution.
* **Developer-friendly design:** The REST interface provides standardized endpoints for quoting swaps, generating calldata, and retrieving supported tokens, making it easy to integrate Nabla into bots, frontends, or backends.
* **Predictable pricing and slippage control:** The API includes built-in parameters for slippage tolerance and maximum trade deviation, ensuring consistent execution even in volatile markets.

### Supported networks <a href="#supported-networks" id="supported-networks"></a>

* Arbitrum One (chain id: 42161)
* Base (chain id: 8453)
* Berachain (chain id: 80094)
* Hyperliquid (chain id: 999)

### API reference <a href="#api-reference" id="api-reference"></a>

For detailed information about each endpoint, refer to the Nabla Finance Swap API swagger docs:

{% embed url="<https://swap-api.nabla.fi/docs>" %}

***

## Quick Start <a href="#quick-start" id="quick-start"></a>

#### Script

Example swap from USDC to WETH on Arbitrum One.

```javascript
// swap.js
const { ethers } = require("ethers");
const dotenv = require("dotenv");
const fetch = require("node-fetch"); // ensure installed: npm install node-fetch@2

// Load .env from the same directory
dotenv.config({ path: "./.env" });

// === ENVIRONMENT CHECKS ===
const required = [
  "WALLET_ADDRESS",
  "PRIVATE_KEY",
  "RPC_URL",
  "API_URL", // Nabla Finance Swap API (https://swap-api.nabla.fi)
];
for (const key of required) {
  if (!process.env[key]) {
    console.error(`Missing required environment variable: ${key}`);
    process.exit(1);
  }
}

// === CONFIG ===
const config = {
  apiBase: process.env.API_URL,
  chainId: 42161,
  walletAddress: process.env.WALLET_ADDRESS.toLowerCase(),
  privateKey: process.env.PRIVATE_KEY,
  rpcUrl: process.env.RPC_URL,

  // Tokens
  fromToken: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831", // USDC on Arbitrum
  toToken: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1", // WETH on Arbitrum

  // Amounts & Slippage
  amountToSwap: 500_000_000, // 500 USDC (6 decimals)
  slippage: 0.5,
};

// === SETUP WALLET & PROVIDER ===
const provider = new ethers.JsonRpcProvider(config.rpcUrl);
const wallet = new ethers.Wallet(config.privateKey, provider);

// === HELPERS ===
function buildQuery(params) {
  return new URLSearchParams(params).toString();
}

async function fetchJson(url) {
  const response = await fetch(url);
  if (!response.ok) {
    const text = await response.text();
    throw new Error(`Fetch failed (${response.status}): ${text}`);
  }
  return response.json();
}

// === APPROVAL LOGIC ===
async function approveWhenNeeded(amount) {
  console.log("Checking approval...");

  const query = buildQuery({
    tokenAddress: config.fromToken,
    walletAddress: config.walletAddress,
  });
  const url = `${config.apiBase}/chains/${config.chainId}/approve/allowance?${query}`;
  
  const data = await fetchJson(url);

  if (data.allowance >= amount) {
    console.log("Sufficient allowance, no approval needed.");
    return;
  }
  
  console.log("Insufficient allowance — requesting approval...");
  await approve(amount);
}

async function approve(amount) {
  const query = buildQuery({
    tokenAddress: config.fromToken,
    amount: amount,
  });
  const url = `${config.apiBase}/chains/${config.chainId}/approve/transaction?${query}`;

  const data = await fetchJson(url);
 
  const tx = {
    to: data.tx.to,
    data: data.tx.data,
    value: data.tx.value || 0,
    gasLimit: data.tx.gas || undefined,
    gasPrice: data.tx.gasPrice || undefined,
  };

  const sentTx = await wallet.sendTransaction(tx);
  console.log("Approval TX Hash:", sentTx.hash);

  const receipt = await sentTx.wait();
  console.log("Approval confirmed in block:", receipt.blockNumber);
}

// === SWAP LOGIC ===
async function executeSwap(tx) {
  const transaction = {
    to: tx.to,
    data: tx.data,
    value: tx.value || 0,
    gasLimit: tx.gas || undefined,
    gasPrice: tx.gasPrice || undefined,
  };

  console.log("Sending swap transaction...");
  const sentTx = await wallet.sendTransaction(transaction);
  console.log("Swap TX Hash:", sentTx.hash);

  const receipt = await sentTx.wait();
  console.log("Swap confirmed in block:", receipt.blockNumber);
  
  return receipt;
}

async function performSwap() {
  console.log("Performing swap...");

  const query = buildQuery({
    tokenIn: config.fromToken,
    tokenOut: config.toToken,
    amountIn: config.amountToSwap,
    maxSlippage: config.slippage,
    fromAddress: config.walletAddress,
  });

  const url = `${config.apiBase}/chains/${config.chainId}/swap?${query}`;
  const data = await fetchJson(url);

  await executeSwap(data.tx);
}

// === MAIN ===
(async function main() {
  try {
    await approveWhenNeeded(config.amountToSwap);
    await performSwap();
  } catch (err) {
    console.error("Error:", err.message || err);
    process.exit(1);
  }
})();
```

#### &#x20;**`.env` (place in same directory)**

```
WALLET_ADDRESS=
PRIVATE_KEY=
RPC_URL=https://arb1.arbitrum.io/rpc
API_URL=https://swap-api.nabla.fi
```
