Waiting for the first launch or trade…

Public API

Launch and read Runitup tokens from a bot, an agent, or your own app.

Runitup has a public API so you can launch a token from a script, a trading bot, an AI agent, or your own front-end. A token launched this way is identical to one launched on the website: same factory contract, same 70/20/10 fee split, same permanently locked liquidity.

No API key. No sign-up. Nothing here moves money or exposes anything private, so there is nothing to gate.

We never touch your keys

The API builds your transaction. It does not send it. You sign with a key Runitup never sees and broadcast it yourself. There is no endpoint that launches a token for you, and there never will be — that would mean holding your private key, which would turn one break-in into everyone's loss.

Using it from an AI agent

There's a ready-made skill file — drop it into Claude Code, OpenCode, Hermes, OpenClaw or anything else that loads markdown skills, and the agent knows the whole flow without you explaining it:

https://runitup.fun/skills/runitup/SKILL.md

For Claude Code, save it as .claude/skills/runitup/SKILL.md in your project (or ~/.claude/skills/ to have it everywhere). Most other frameworks take the raw URL directly.

There's also an llms.txt at the root, which is what agents look for when they want to find their way around a site on their own.

The flow

  1. POST /api/v1/launch/prepare with your token's details
  2. Sign and send the approval transaction it returns, if there is one
  3. Sign and send the launch transaction
  4. Read the token address from the TokenLaunched event in the receipt
  5. Optionally POST an image and description to the metadata endpoint

Get the current rules

curl https://runitup.fun/api/v1/config

Returns the chain, contract addresses, and the live launch rules — the fee, the supply bounds, the starting market cap. Read these rather than hardcoding them; they're read from the contract on every request and can change.

Prepare a launch

curl -X POST https://runitup.fun/api/v1/launch/prepare \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "My Coin",
    "symbol": "MYC",
    "totalSupply": "1000000000",
    "creatorAddress": "0xYourWallet",
    "devBuyUsdc": "25",
    "venue": "uniswap-v3"
  }'
FieldRequiredNotes
nameyesUp to 64 characters
symbolyesUp to 16 characters
totalSupplyyesWhole tokens, as a string. "1000000000" is one billion
creatorAddressyesThe wallet that will sign
devBuyUsdcnoETH of your own token to buy at launch. "25" is $25
feeRecipientsnoDefaults to creatorAddress. Multiple addresses split evenly
venuenouniswap-v3 (default), sushi-v3 or uniswap-v4

Amounts are decimal strings, not raw integers — write "25" for $25, not "25000000". Values coming back are raw integers as strings, because a JSON number would silently round a supply of 1e21.

Pairing is not available through this endpoint

A launch made here is always quoted in ETH. There is no quoteToken field, and that is deliberate rather than an omission.

Pairing against USDG or a tokenized stock means the dev buy is paid in that asset, which the factory pulls with transferFrom — so the creator has to approve the spend in a separate transaction first. This endpoint returns one unsigned transaction and has no way to express "approve, then launch". Emitting a single transaction that reverts on a missing allowance would be worse than not offering it.

To launch against another quote asset, use the launch form, which sequences the approval for you. Tokens launched either way are identical afterwards.

You get back:

{
  "chainId": 5042002,
  "transactions": {
    "approval": { "to": "0x36…", "data": "0x095ea7b3…", "value": "0" },
    "launch":   { "to": "0x60…", "data": "0x1f6a5b96…", "value": "0" }
  },
  "cost": {
    "launchFeeUsdc": "1000000",
    "totalUsdcRequired": "26000000",
    "sufficientBalance": true
  }
}

approval is null when your allowance is already enough. When it isn't null, send it first and wait for it to confirm — the factory pulls ETH from your wallet, and the launch reverts with transfer amount exceeds allowance if you skip it.

sufficientBalance is reported, not enforced. If it's false the transaction is still built, on the assumption you're about to fund the wallet.

Send it

import { createWalletClient, http, parseEventLogs } from "viem";
import { privateKeyToAccount } from "viem/accounts";

const account = privateKeyToAccount(process.env.PRIVATE_KEY);
const wallet = createWalletClient({ account, transport: http(RPC_URL) });

const { transactions } = await fetch(".../api/v1/launch/prepare", { ... }).then(r => r.json());

if (transactions.approval) {
  const hash = await wallet.sendTransaction(transactions.approval);
  await publicClient.waitForTransactionReceipt({ hash });
}

const hash = await wallet.sendTransaction(transactions.launch);
const receipt = await publicClient.waitForTransactionReceipt({ hash });
// TokenLaunched in the receipt logs carries your new token's address

Add an image and description

These aren't on-chain, so they're a separate call after the launch confirms:

curl -X POST https://runitup.fun/api/tokens/0xYourToken/metadata \
  -H 'Content-Type: application/json' \
  -d '{ "name":"My Coin", "ticker":"MYC", "totalSupply":"1000000000000000000000000000",
        "creatorAddress":"0xYourWallet", "imageUrl":"https://…", "description":"…",
        "ammVenue":"uniswap-v3", "launchType":"quick" }'

Do this straight after launching. It makes your token appear on the site immediately rather than waiting for the indexer, and sets the venue so the first buys route correctly.

Reading data

These are open too, and need nothing:

EndpointReturns
GET /api/tokensEvery live token with price, market cap, volume
GET /api/tokens/{address}One token, plus holders and recent trades
GET /api/tokens/{address}/candles?interval=1hOHLC price history
GET /api/activityRecent launches and trades across the platform
GET /api/statisticsPlatform totals
GET /api/wallet/{address}/portfolioA wallet's holdings

Errors

Validation failures return 400 with the offending field named:

{ "error": "invalid_request", "field": "totalSupply",
  "message": "totalSupply must be between … raw units (18 decimals)." }

Parameters are checked against the live contract rules, so a request that returns 200 should not revert for a reason we could have caught. Gas, balance and network conditions are still yours to handle.