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.
- 01
Prepare
POST your token card. TokenRouter builds the unsigned launch transactions for your wallet.
POST /api/v1/launch/prepare - 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) - 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
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());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-Keyheader with prepare; confirm is safe to repeat. - Errors —
application/problem+jsonwith a machine-readablecode, e.g.creator_mismatch,insufficient_funds. - Socials —
card.linkstakes website, x, telegram, discord and farcaster; handles like@namework. See the table below for what each launchpad shows. - Expiry — sign before
expiresAt(about a minute on Solana), otherwise prepare again.
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.
API reference
Generated from openapi.json. Try requests with your API key.