Developers · API v1

Launch tokens from code.
Your wallet signs. Always.

One API for every launchpad on TokenRouter. You send a token card; we return unsigned transactions; your wallet signs and sends them. TokenRouter never holds, receives or stores a private key.

  1. 01

    Prepare

    POST your token card. TokenRouter builds the unsigned launch transactions for your wallet.

    POST /api/v1/launch/prepare
  2. 02

    Sign in your wallet

    Your wallet signs and sends each step. Keys never leave your machine — TokenRouter never sees them.

    wallet.sign(step.tx)
  3. 03

    Confirm

    Send the transaction ids. TokenRouter verifies them on chain and returns your token.

    POST /api/v1/launch/confirm

Non-custodial

Only unsigned transactions leave our servers. API keys are bound to your wallet, and creator must be that wallet.

9 launchpads, one API

Solana, Robinhood Chain, Base, BNB Chain. Same request shape everywhere.

Built for agents

OpenAPI 3.1, llms.txt and an Agent Skill that teaches an agent to launch with its own wallet.

Quickstart

Create an API key on the Developers page while signed in with the wallet you launch from — the key is bound to that wallet. Then upload an image, prepare, sign in your wallet, confirm.

1 · Setup and image

tokenrouter.ts
const BASE = 'https://tokenrouter.fun/api/v1';
const KEY = process.env.TOKENROUTER_API_KEY; // tr_live_…
const auth = { authorization: `Bearer ${KEY}` };

async function api(path: string, body?: unknown) {
  const res = await fetch(BASE + path, {
    method: body ? 'POST' : 'GET',
    headers: { ...auth, 'content-type': 'application/json' },
    body: body ? JSON.stringify(body) : undefined
  });
  // errors: application/problem+json { code, detail }
  if (!res.ok) throw await res.json();
  return res.json();
}

// Image: raw bytes in, public URL out (≤ 5 MB)
const { url: imageUrl } = await fetch(BASE + '/uploads', {
  method: 'POST',
  headers: { ...auth, 'content-type': 'image/png' },
  body: await readFile('token.png')
}).then((r) => r.json());
launch-solana.ts
import { Connection, Keypair, VersionedTransaction } from '@solana/web3.js';

const wallet = Keypair.fromSecretKey(mySecretKey); // stays on your machine
const connection = new Connection(process.env.SOLANA_RPC_URL!);

const prep = await api('/launch/prepare', {
  pad: 'pumpfun',
  creator: wallet.publicKey.toBase58(), // must be the key's wallet
  card: {
    name: 'Router Cat',
    symbol: 'RCAT',
    imageUrl,
    links: { website: 'https://routercat.xyz', x: '@routercat', telegram: '@routercat' }
  },
  options: { devBuy: '0.1' }
});

const txIds: string[] = [];
for (const step of prep.steps) {
  const bytes = Buffer.from(step.tx.transaction, 'base64');
  const tx = VersionedTransaction.deserialize(bytes);
  tx.sign([wallet]); // keeps the single-use mint signature
  const sig = await connection.sendTransaction(tx);
  await connection.confirmTransaction(sig, 'confirmed');
  txIds.push(sig);
}

const launch = await api('/launch/confirm', {
  launchId: prep.launchId,
  txIds
});
console.log(launch.token, launch.padUrl);
  • Auth — Authorization: Bearer tr_live_… or a browser session. Keys are shown once and stored only as a hash.
  • Retries — send an Idempotency-Key header with prepare; confirm is safe to repeat.
  • Errors — application/problem+json with a machine-readable code, e.g. creator_mismatch, insufficient_funds.
  • Socials — card.links takes website, x, telegram, discord and farcaster; handles like @name work. See the table below for what each launchpad shows.
  • Expiry — sign before expiresAt (about a minute on Solana), otherwise prepare again.

Socials and pad fields

Put links in card.links. Handles work (@name becomes https://x.com/name); everything is normalised to https and checked against the platform's hosts. Each launchpad shows only some platforms — the others are left out and named in the quote notes. GET /api/v1/pads returns this table as fields.

Social links and fields per launchpad
LaunchpadWebsiteXTelegramDiscordFarcasterDescriptionExtras
pumpfunyesyesyes——≤ 1000—
paidyesyesyes——≤ 256—
bonkfunyesyesyes——≤ 512—
stonkfunyesyesyes——≤ 1000—
ponsyesyesyesyesyes≤ 256—
clankeryesyesyes—yes≤ 1000—
zora—————≤ 1000—
fourmemeyesyesyes——≤ 800extra.label Meme · AI · Defi · Games · Infra · DeSci · Social · Depin · Charity · Others
flapyesyesyes——≤ 1000—

Errors

Every error is application/problem+json — { type, title, status, code, detail }. Branch on code; show detail to people.

invalid_request400
The body or query failed validation. detail names the field.
unauthorized401
No browser session and no API key.
invalid_api_key401
The key is malformed, unknown or revoked.
insufficient_funds402
The creator wallet cannot pay for this launch.
creator_mismatch403
creator is not the authenticated wallet, or the pad runs on the other chain family.
tx_mismatch403
The transactions were not sent by the creator or did not create the prepared token.
session_required403
API keys are managed from a signed-in browser session.
cross_site403
A browser session was used from another site. Use an API key there.
not_found404
Unknown endpoint, or a launch / key that is not yours.
method_not_allowed405
The endpoint does not support this method.
already_confirmed409
The launch was confirmed with other transactions.
invalid_state409
The launch cannot take this action in its current status.
too_many_keys409
At most 10 active keys. Revoke one first.
expired410
The prepared transactions or the challenge expired. Prepare again.
payload_too_large413
Images up to 5 MB, JSON bodies up to 32 KB.
unsupported_media_type415
Send JSON, or a PNG, JPEG, WebP or GIF image.
unsupported422
The launchpad does not support this option or call.
idempotency_key_reused422
The Idempotency-Key was used with a different body.
rate_limited429
Too many requests. Wait for Retry-After seconds.
server_error500
Unexpected error on our side. Retry later.
upstream_error502
The launchpad or an RPC failed. Retry, or confirm again a few seconds later.
missing_env503
This launchpad is not available right now.
service_unavailable503
Accounts are temporarily unavailable.

API reference

Generated from openapi.json. Try requests with your API key.

Loading reference…