Working examples that get you to the first live request faster

Use these snippets when you want to move from reading docs to sending a real request without rebuilding headers, payloads, and auth rules from scratch.

Runtime target: the snippets below are written for Node.js 18+ where fetch is already available.
How to pick the right snippet: use Lightning for fast server-side trading, Local Build when the wallet must sign, Agent Wallet when the agent should have limited access, and the dedicated transfer route only when transfer is explicitly enabled for that agent wallet.

1) Buy example

Minimal lightning buy request with server-side signing.

const BASE_URL = 'https://corto.fun'; // Corto.Fun API origin.
const API_KEY = 'YOUR_API_KEY'; // API key generated by the wallet endpoint.
const TOKEN_MINT = 'YOUR_TOKEN_MINT'; // SPL token mint you want to buy.

async function main() {
  const response = await fetch(`${BASE_URL}/api/v1/lightning/trade`, {
    method: 'POST', // Lightning trade is always a POST request.
    headers: {
      'X-API-Key': API_KEY, // Header credential for server-side signing mode.
      'content-type': 'application/json' // JSON payload type expected by the API.
    },
    body: JSON.stringify({
      action: 'buy', // buy means spend SOL and receive the target token.
      mint: TOKEN_MINT, // Token mint address to route the trade against.
      amount: 0.01, // Buy size in SOL because denominatedInSol is true.
      denominatedInSol: true, // true means amount is interpreted as SOL size.
      slippage: 5, // Max tolerated execution drift in percent.
      pool: 'auto', // auto lets the router select the best venue.
      memo: 'alpha entry', // Optional user memo. Branding suffix is appended only if both still fit the memo limit.
      jitoTip: 0.0003, // Optional direct Jito auction bid. Effective values start at 0.0002 SOL.
      projectId: 'alpha-campaign', // Optional analytics attribution key for one partner wallet serving multiple campaigns.
      ackMode: 'confirmed', // confirmed waits for a stricter acknowledgement state.
      maxRouteMs: 1200 // Routing search time budget in milliseconds.
    })
  });

  const body = await response.json(); // Parse the JSON response body.
  console.log(body); // Print the full response for inspection.
}

main().catch(console.error); // Surface network or runtime failures in the console.

2) Sell example

Minimal lightning sell request using a percentage-based amount.

const BASE_URL = 'https://corto.fun'; // Corto.Fun API origin.
const API_KEY = 'YOUR_API_KEY'; // API key generated by the wallet endpoint.
const TOKEN_MINT = 'YOUR_TOKEN_MINT'; // SPL token mint you want to sell.

async function main() {
  const response = await fetch(`${BASE_URL}/api/v1/lightning/trade`, {
    method: 'POST', // Lightning trade is always a POST request.
    headers: {
      'X-API-Key': API_KEY, // Header credential for server-side signing mode.
      'content-type': 'application/json' // JSON payload type expected by the API.
    },
    body: JSON.stringify({
      action: 'sell', // sell means exit the token position back into SOL.
      mint: TOKEN_MINT, // Token mint address you want to liquidate.
      amount: '25%', // Percentage string supported by lightning sell mode.
      denominatedInSol: false, // false means amount is not a SOL-denominated buy size.
      slippage: 8, // Extra room for fast-moving exits.
      pool: 'auto', // auto lets the router select the best venue.
      memo: 'profit exit', // Optional user memo. Branding suffix is appended only if both still fit the memo limit.
      jitoTip: 0.0003, // Optional direct Jito auction bid. Effective values start at 0.0002 SOL.
      projectId: 'alpha-campaign', // Optional analytics attribution key for one partner wallet serving multiple campaigns.
      ackMode: 'confirmed', // confirmed waits for a stricter acknowledgement state.
      maxRouteMs: 1200 // Routing search time budget in milliseconds.
    })
  });

  const body = await response.json(); // Parse the JSON response body.
  console.log(body); // Print the full response for inspection.
}

main().catch(console.error); // Surface network or runtime failures in the console.

3) Local buy transaction example

Build an unsigned local buy transaction that a wallet like Phantom can sign later.

const BASE_URL = 'https://corto.fun'; // Corto.Fun API origin.
const PUBLIC_KEY = 'YOUR_WALLET_PUBLIC_KEY'; // Wallet address that will pay fees and sign later.
const TOKEN_MINT = 'YOUR_TOKEN_MINT'; // SPL token mint you want to buy.

async function main() {
  const response = await fetch(`${BASE_URL}/api/v1/local/trade`, {
    method: 'POST', // Local build endpoint is also a POST request.
    headers: {
      'content-type': 'application/json' // JSON payload type expected by the API.
    },
    body: JSON.stringify({
      publicKey: PUBLIC_KEY, // Wallet that will receive the unsigned transaction for signing.
      action: 'buy', // buy means spend SOL and receive the target token.
      mint: TOKEN_MINT, // Token mint address to route the trade against.
      amount: 0.01, // Buy size in SOL because denominatedInSol is true.
      denominatedInSol: true, // true means amount is interpreted as SOL size.
      slippage: 5, // Max tolerated execution drift in percent.
      pool: 'auto', // auto lets the router select the best venue.
      memo: 'local buy note', // Optional user memo. Branding suffix is appended only if both still fit the memo limit.
      priorityFeeSol: 0.0001 // Optional explicit priority fee in SOL.
    })
  });

  const body = await response.json(); // Parse the JSON response body.
  console.log(body); // body.transaction is the unsigned base64 transaction.
}

main().catch(console.error); // Surface network or runtime failures in the console.

4) Local sell transaction example

Build an unsigned local sell transaction that a wallet signs and broadcasts client-side.

const BASE_URL = 'https://corto.fun'; // Corto.Fun API origin.
const PUBLIC_KEY = 'YOUR_WALLET_PUBLIC_KEY'; // Wallet address that will pay fees and sign later.
const TOKEN_MINT = 'YOUR_TOKEN_MINT'; // SPL token mint you want to sell.

async function main() {
  const response = await fetch(`${BASE_URL}/api/v1/local/trade`, {
    method: 'POST', // Local build endpoint is also a POST request.
    headers: {
      'content-type': 'application/json' // JSON payload type expected by the API.
    },
    body: JSON.stringify({
      publicKey: PUBLIC_KEY, // Wallet that will receive the unsigned transaction for signing.
      action: 'sell', // sell means exit the token position back into SOL.
      mint: TOKEN_MINT, // Token mint address you want to liquidate.
      amount: 1200, // Local sell uses token units, not percent strings.
      denominatedInSol: false, // false means amount is interpreted as token units.
      slippage: 8, // Extra room for fast-moving exits.
      pool: 'auto', // auto lets the router select the best venue.
      memo: 'local sell note', // Optional user memo. Branding suffix is appended only if both still fit the memo limit.
      priorityFeeSol: 0.0001 // Optional explicit priority fee in SOL.
    })
  });

  const body = await response.json(); // Parse the JSON response body.
  console.log(body); // body.transaction is the unsigned base64 transaction.
}

main().catch(console.error); // Surface network or runtime failures in the console.

5) Dedicated swap: SOL to USDC

Real exact-in swap request using the dedicated swap route.

const BASE_URL = 'https://corto.fun';
const API_KEY = 'YOUR_API_KEY';
const WSOL_MINT = 'So11111111111111111111111111111111111111112';
const USDC_MINT = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';

async function main() {
  const response = await fetch(`${BASE_URL}/api/v1/swap/execute`, {
    method: 'POST',
    headers: {
      'X-API-Key': API_KEY,
      'content-type': 'application/json'
    },
    body: JSON.stringify({
      inputMint: WSOL_MINT,
      outputMint: USDC_MINT,
      amount: 0.01,
      slippage: 5,
      pool: 'jupiter',
      ackMode: 'confirmed',
      maxRouteMs: 8000
    })
  });

  const body = await response.json();
  console.log(body.swap);
}

main().catch(console.error);

6) Dedicated swap: USDC to SOL

Spend token units from the input asset and receive SOL through the same route.

const BASE_URL = 'https://corto.fun';
const API_KEY = 'YOUR_API_KEY';
const WSOL_MINT = 'So11111111111111111111111111111111111111112';
const USDC_MINT = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';

async function main() {
  const response = await fetch(`${BASE_URL}/api/v1/swap/execute`, {
    method: 'POST',
    headers: {
      'X-API-Key': API_KEY,
      'content-type': 'application/json'
    },
    body: JSON.stringify({
      inputMint: USDC_MINT,
      outputMint: WSOL_MINT,
      amount: 1,
      slippage: 5,
      pool: 'jupiter',
      ackMode: 'confirmed',
      maxRouteMs: 8000
    })
  });

  const body = await response.json();
  console.log(body.swap);
}

main().catch(console.error);

7) Dedicated swap: USDT to JUP

Token-to-token route without rewriting the request into buy/sell semantics.

const BASE_URL = 'https://corto.fun';
const API_KEY = 'YOUR_API_KEY';
const USDT_MINT = 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB';
const JUP_MINT = 'JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN';

async function main() {
  const response = await fetch(`${BASE_URL}/api/v1/swap/execute`, {
    method: 'POST',
    headers: {
      'X-API-Key': API_KEY,
      'content-type': 'application/json'
    },
    body: JSON.stringify({
      inputMint: USDT_MINT,
      outputMint: JUP_MINT,
      amount: 1,
      slippage: 5,
      pool: 'jupiter',
      ackMode: 'confirmed',
      maxRouteMs: 8000,
      memo: 'rotate treasury leg'
    })
  });

  const body = await response.json();
  console.log(body.routePlan);
}

main().catch(console.error);

8) Dedicated transfer with agent wallet execution

Use the dedicated transfer route with an agent execution key after transfer capability is explicitly enabled in agent wallet settings.

const BASE_URL = 'https://corto.fun';
const AGENT_EXECUTION_KEY = 'YOUR_AGENT_EXECUTION_KEY';
const IDEMPOTENCY_KEY = `agent-transfer-${Date.now()}`;
const DESTINATION = 'TARGET_PUBLIC_KEY';

async function main() {
  const response = await fetch(`${BASE_URL}/api/v1/transfer/execute`, {
    method: 'POST',
    headers: {
      'X-Agent-Execution-Key': AGENT_EXECUTION_KEY,
      'X-Idempotency-Key': IDEMPOTENCY_KEY,
      'content-type': 'application/json'
    },
    body: JSON.stringify({
      destination: DESTINATION,
      amountSol: 0.002,
      ackMode: 'confirmed',
      memo: 'agent transfer example'
    })
  });

  const body = await response.json();
  console.log(body);
}

main().catch(console.error);

9) Agent wallet lightning execution

Use the old lightning route with agent execution when the agent wallet policy enables lightningTrade.

const BASE_URL = 'https://corto.fun';
const AGENT_EXECUTION_KEY = 'YOUR_AGENT_EXECUTION_KEY';
const IDEMPOTENCY_KEY = `agent-lightning-${Date.now()}`;
const TOKEN_MINT = 'YOUR_TOKEN_MINT';

async function main() {
  const response = await fetch(`${BASE_URL}/api/v1/lightning/trade`, {
    method: 'POST',
    headers: {
      'X-Agent-Execution-Key': AGENT_EXECUTION_KEY,
      'X-Idempotency-Key': IDEMPOTENCY_KEY,
      'content-type': 'application/json'
    },
    body: JSON.stringify({
      action: 'buy',
      mint: TOKEN_MINT,
      amount: 0.001,
      denominatedInSol: true,
      slippage: 5,
      ackMode: 'confirmed'
    })
  });

  const body = await response.json();
  console.log(body);
}

main().catch(console.error);

10) Agent wallet settings read

Use the settings key only on control-plane routes such as profile, balances, stats, history, and policy updates.

const BASE_URL = 'https://corto.fun';
const SETTINGS_KEY = 'YOUR_SETTINGS_KEY';

async function main() {
  const response = await fetch(`${BASE_URL}/api/v1/agent-wallet/profile`, {
    method: 'GET',
    headers: {
      'X-Settings-Key': SETTINGS_KEY
    }
  });

  const body = await response.json();
  console.log(body.profile);
}

main().catch(console.error);

11) Token builder create example

Submit metadata, image, and create parameters in one multipart request. This example uses X-API-Key, but the route also accepts X-Agent-Execution-Key. Agent mode must also send X-Idempotency-Key.

import { readFile } from 'node:fs/promises';

const BASE_URL = 'https://corto.fun'; // Corto.Fun API origin.
    const API_KEY = 'YOUR_API_KEY'; // Ordinary wallet example. X-Agent-Execution-Key also works.

async function main() {
  const imageBytes = await readFile('./token-image.png'); // Read the image from local disk.
  const form = new FormData();

  form.set('platform', 'pump'); // Use pump or letsbonk.
  form.set('name', 'Corto Nova'); // Token name shown in metadata.
  form.set('symbol', 'NOVA'); // Token ticker symbol.
  form.set('description', 'Example launch from Corto token builder'); // Token description.
  form.set('website', 'https://example.com'); // Optional project website.
  form.set('cashbackEnabled', 'true'); // pump-only cashback accounting flag.
  form.set('image', new Blob([imageBytes], { type: 'image/png' }), 'token-image.png'); // Image is sent in the same multipart body.

  const response = await fetch(`${BASE_URL}/api/v1/token-builder/create`, {
    method: 'POST',
    headers: {
      'X-API-Key': API_KEY // Example header for the ordinary wallet flow.
    },
    body: form
  });

  const body = await response.json();
  console.log(body); // body contains txSignature or txSignatures plus mint and metadataUri.
}

main().catch(console.error);

12) Token builder claim example

Claim pump cashback or letsbonk creator fees through the shared claim endpoint. This example uses X-API-Key, but the route also accepts X-Agent-Execution-Key. Agent mode must also send X-Idempotency-Key.

const BASE_URL = 'https://corto.fun'; // Corto.Fun API origin.
    const API_KEY = 'YOUR_API_KEY'; // Ordinary wallet example. X-Agent-Execution-Key also works.

async function main() {
  const response = await fetch(`${BASE_URL}/api/v1/token-builder/claim-cashback`, {
    method: 'POST',
    headers: {
      'X-API-Key': API_KEY, // Example header for the ordinary wallet flow.
      'content-type': 'application/json'
    },
    body: JSON.stringify({
      platform: 'letsbonk' // Use pump for cashback or letsbonk for creator fee claim.
    })
  });

  const body = await response.json();
  console.log(body); // body.claimKind tells you whether the claim was cashback or creator_fee.
}

main().catch(console.error);

13) Developer analytics example

Fetch partner analytics with a rolling frame and optionally narrow the response to one project inside the same verified partner scope.

const BASE_URL = 'https://corto.fun'; // Corto.Fun API origin.
const API_KEY = 'YOUR_API_KEY'; // API key generated together with the partner wallet.
const PARTNER_ADDRESS = 'PUBLIC_KEY_FROM_THE_SAME_GENERATED_WALLET'; // Must match the wallet restored from API_KEY.

async function main() {
  const response = await fetch(`${BASE_URL}/api/v1/dev/analytics/trades`, {
    method: 'POST', // Developer analytics endpoint is a POST request.
    headers: {
      'X-API-Key': API_KEY, // Same header auth model as lightning mode.
      'content-type': 'application/json' // JSON payload type expected by the API.
    },
    body: JSON.stringify({
      frame: '7h', // Rolling frame. Supported values: 1..24h or 1..30d.
      partnerAddress: PARTNER_ADDRESS, // Required and must match the decoded API key owner.
      projectId: 'alpha-campaign' // Optional extra filter inside that partner scope.
    })
  });

  const body = await response.json(); // Parse the JSON response body.
  console.log(body.summary); // Totals and time window metadata.
  console.table(body.rows); // Per-user aggregated rows.
}

main().catch(console.error); // Surface network or runtime failures in the console.

14) Wallet generation example

Generate a new wallet package with public key, private key, API key, and API key version.

const BASE_URL = 'https://corto.fun'; // Corto.Fun API origin.

async function main() {
  const response = await fetch(`${BASE_URL}/api/v1/wallet/generate`, {
    method: 'POST', // Wallet generation endpoint is a POST request.
    headers: {
      'content-type': 'application/json' // JSON payload type expected by the API.
    },
    body: JSON.stringify({}) // Empty object is enough because generation is fully server-side.
  });

  const body = await response.json(); // Parse the JSON response body.
  console.log('publicKey:', body.publicKey); // Wallet address the user can fund and monitor.
  console.log('privateKey:', body.privateKey); // One-time private key delivery that must be stored offline.
  console.log('apiKey:', body.apiKey); // Encrypted trading credential for lightning mode.
  console.log('apiKeyVersion:', body.apiKeyVersion); // Versioned keyring slot used for this API key.
}

main().catch(console.error); // Surface network or runtime failures in the console.

15) API key verification example

Check the version of an API key after an incident and compare it against your announced minimum safe version.

const BASE_URL = 'https://corto.fun'; // Corto.Fun API origin.
const API_KEY = 'YOUR_API_KEY'; // API key you want to validate.
const MIN_SAFE_VERSION = 2; // Lowest version you still consider safe after a rotation event.

async function main() {
  const response = await fetch(`${BASE_URL}/api/v1/verify`, {
    method: 'POST', // Verify endpoint is a POST request.
    headers: {
      'X-API-Key': API_KEY // Header credential used by the verification endpoint.
    }
  });

  const body = await response.json(); // Parse the JSON response body.
  console.log(body); // Print publicKey and apiKeyVersion for inspection.

  if (body.success && body.apiKeyVersion < MIN_SAFE_VERSION) { // Compare against your public safety threshold.
    console.log('This key is older than the minimum safe version. Generate a new wallet.');
  }
}

main().catch(console.error); // Surface network or runtime failures in the console.

16) Telegram bot example in one file

Single-file Telegram bot example with direct placeholders instead of environment variables.

// Install dependency first: npm install telegraf

    import { Markup, Telegraf } from 'telegraf';

const BASE_URL = 'https://corto.fun'; // Corto.Fun API origin.
const API_KEY = 'YOUR_API_KEY'; // API key used for lightning trading.
const TELEGRAM_BOT_TOKEN = 'YOUR_TELEGRAM_BOT_TOKEN'; // Telegram bot token from BotFather.
const DEFAULT_POOL = 'auto'; // Default venue routing policy for all trades.

const bot = new Telegraf(TELEGRAM_BOT_TOKEN); // Telegram bot client instance.
const sessions = new Map(); // In-memory chat session store keyed by Telegram user id.

function parseMint(input) { // Extract a Solana mint from raw text or a token URL.
  const text = String(input || '').trim();
  if (/^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(text)) {
    return text;
  }
  const embedded = text.match(/[1-9A-HJ-NP-Za-km-z]{32,44}/);
  return embedded ? embedded[0] : null;
}

async function fetchJson(path, options) { // Normalize API error handling for bot replies.
  const response = await fetch(`${BASE_URL}${path}`, options);
  const body = await response.json();
  if (!response.ok || body?.success === false) {
    throw new Error(body?.error?.message || `HTTP ${response.status}`);
  }
  return body;
}

async function tradeAndStatus(payload) { // Submit a trade and immediately fetch its status.
  const trade = await fetchJson('/api/v1/lightning/trade', {
    method: 'POST', // Lightning trade is always a POST request.
    headers: {
      'X-API-Key': API_KEY, // Header credential for server-side signing mode.
      'content-type': 'application/json' // JSON payload type expected by the API.
    },
    body: JSON.stringify({
      ...payload, // Action-specific trade fields injected by the callback handler.
      jitoTip: 0.0003, // Optional direct Jito auction bid when you explicitly want auction participation.
      projectId: 'alpha-campaign', // Optional analytics attribution key for segmenting one partner wallet.
      ackMode: 'confirmed', // Wait for a stricter acknowledgement state before replying.
      maxRouteMs: 1200 // Routing search time budget in milliseconds.
    })
  });

  const status = await fetchJson(`/api/v1/tx/${trade.txSignature}/status`, { method: 'GET' }); // Query the final tx status.
  return { trade, status };
}

bot.start((ctx) => ctx.reply('Send a Solana mint address or a URL that contains a mint.')); // Start message for a new chat.

bot.on('text', async (ctx) => {
  const mint = parseMint(ctx.message.text); // Parse the mint from the incoming chat message.
  if (!mint) {
    return ctx.reply('Mint not recognized. Send a valid Solana mint or a token URL.');
  }

  sessions.set(ctx.from.id, { mint }); // Store the last detected mint for this Telegram user.
  return ctx.reply(
    `Mint detected: ${mint}\nChoose action.`,
    Markup.inlineKeyboard([
      [Markup.button.callback('Buy', 'ACTION_BUY')],
      [Markup.button.callback('Sell', 'ACTION_SELL')]
    ])
  );
});

bot.action('ACTION_BUY', async (ctx) => {
  await ctx.answerCbQuery(); // Close the Telegram loading state on the tapped button.
  return ctx.reply(
    'Choose buy amount in SOL.',
    Markup.inlineKeyboard([
      [Markup.button.callback('0.01', 'BUY_0.01'), Markup.button.callback('0.02', 'BUY_0.02')],
      [Markup.button.callback('0.05', 'BUY_0.05'), Markup.button.callback('0.1', 'BUY_0.1')],
      [Markup.button.callback('0.3', 'BUY_0.3'), Markup.button.callback('0.5', 'BUY_0.5')]
    ])
  );
});

bot.action('ACTION_SELL', async (ctx) => {
  await ctx.answerCbQuery(); // Close the Telegram loading state on the tapped button.
  return ctx.reply(
    'Choose sell percentage.',
    Markup.inlineKeyboard([
      [Markup.button.callback('10%', 'SELL_10'), Markup.button.callback('20%', 'SELL_20')],
      [Markup.button.callback('30%', 'SELL_30'), Markup.button.callback('50%', 'SELL_50')],
      [Markup.button.callback('75%', 'SELL_75'), Markup.button.callback('100%', 'SELL_100')]
    ])
  );
});

for (const amount of ['0.01', '0.02', '0.05', '0.1', '0.3', '0.5']) {
  bot.action(`BUY_${amount}`, async (ctx) => {
    await ctx.answerCbQuery('Submitting buy...'); // Show immediate feedback in Telegram.
    const mint = sessions.get(ctx.from.id)?.mint; // Recover the last mint selected by this user.
    if (!mint) {
      return ctx.reply('No mint found in session. Send the token again first.');
    }

    try {
      const result = await tradeAndStatus({
        action: 'buy', // buy means spend SOL and receive the target token.
        mint, // Token mint address selected by the user in chat.
        amount: Number(amount), // SOL-sized buy amount from the pressed quick button.
        denominatedInSol: true, // true means amount is interpreted as SOL size.
        slippage: 5, // Max tolerated execution drift in percent.
        pool: DEFAULT_POOL // Default router policy for venue selection.
      });

      return ctx.reply(`Buy success\nSignature: ${result.trade.txSignature}\nStatus: ${JSON.stringify(result.status)}`);
    } catch (error) {
      return ctx.reply(`Buy failed: ${error.message}`);
    }
  });
}

for (const percent of ['10', '20', '30', '50', '75', '100']) {
  bot.action(`SELL_${percent}`, async (ctx) => {
    await ctx.answerCbQuery('Submitting sell...'); // Show immediate feedback in Telegram.
    const mint = sessions.get(ctx.from.id)?.mint; // Recover the last mint selected by this user.
    if (!mint) {
      return ctx.reply('No mint found in session. Send the token again first.');
    }

    try {
      const result = await tradeAndStatus({
        action: 'sell', // sell means exit the token position back into SOL.
        mint, // Token mint address selected by the user in chat.
        amount: `${percent}%`, // Percentage-based lightning sell amount.
        denominatedInSol: false, // false means amount is not a SOL-denominated buy size.
        slippage: 8, // Extra room for fast-moving exits.
        pool: DEFAULT_POOL // Default router policy for venue selection.
      });

      return ctx.reply(`Sell success\nSignature: ${result.trade.txSignature}\nStatus: ${JSON.stringify(result.status)}`);
    } catch (error) {
      return ctx.reply(`Sell failed: ${error.message}`);
    }
  });
}

bot.launch(); // Start polling Telegram updates.
console.log('Telegram bot example is running.'); // Log startup for local debugging.
Previous Page Docs
Current Page Examples
Next Page Why Corto