STARC
ARC·TESTNET

Builders & agents

Developers

Free public read API for indexed STARC data. Launch and trade with your own wallet on Arc — there is no custodial write API. Protocol fees stay the product revenue; this API is infrastructure for bots and agents.

Model

  • Read — HTTP JSON under /api/v1
  • Write — on-chain only (Factory / market / SwapHelper)
  • Addresses — always load GET /api/v1/config first (redeploys change them)
  • Quote — create/buy with native USDC (18 dec, msg.value); pool swaps use ERC-20 USDC (6 dec)
Safety

Anon Supabase only. Cap limits (markets ≤50, trades ≤100). IP rate limits: 60/min global, 30/min on heavy routes (trades, search, profile). Short CDN/cache TTLs. Upload is rate-limited separately (same as /api/logo).

Endpoints

MethodPathNotes
GET/api/v1/configChain, addresses, fees — no DB
GET/api/v1/markets?kind=&sort=&limit=&offset=
GET/api/v1/markets/:idlaunch_id or market 0x
GET/api/v1/markets/:id/tradesHeavy · max 100
GET/api/v1/search?q=Heavy · name/symbol
GET/api/v1/statsCached 30s
GET/api/v1/position/:market/:walletIndexed position
GET/api/v1/profile/:addressHeavy · created + positions
POST/api/v1/uploadLogo multipart (creator, file)
GET/api/v1/openapiOpenAPI 3 JSON

OpenAPI: /api/v1/openapi. CORS is open for browser clients.

Quick read

const base = "https://starc.run/api/v1";

const config = await fetch(`${base}/config`).then((r) => r.json());
const markets = await fetch(`${base}/markets?kind=livo&limit=20`).then((r) =>
  r.json(),
);
const one = await fetch(`${base}/markets/${markets.items[0].id}`).then((r) =>
  r.json(),
);

Agents: launch & trade

No server-side signing. Your agent holds keys (or a wallet RPC), reads config, then submits transactions. Creation fees (native USDC): Discovery / Fuse 1, LIVO 10.

1 — Create Discovery

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

const cfg = await fetch(base + "/config").then((r) => r.json());
const account = privateKeyToAccount(process.env.PK);
const client = createWalletClient({
  account,
  chain: {
    id: cfg.chain.id,
    name: cfg.chain.name,
    nativeCurrency: cfg.chain.nativeCurrency,
    rpcUrls: { default: { http: cfg.chain.rpc } },
  },
  transport: http(cfg.chain.rpc[0]),
});

const factoryAbi = [{
  type: "function",
  name: "create",
  stateMutability: "payable",
  inputs: [
    { name: "name", type: "string" },
    { name: "symbol", type: "string" },
    { name: "metadataURI", type: "string" },
  ],
  outputs: [
    { name: "launchId", type: "uint256" },
    { name: "market", type: "address" },
  ],
}];

await client.writeContract({
  address: cfg.addresses.launchFactory,
  abi: factoryAbi,
  functionName: "create",
  args: ["Agent Coin", "AGT", "ipfs://…"], // or https metadata / logo URL
  value: parseEther(String(cfg.fees.discoveryCreationUsdc)), // 1e18 native USDC
});

LIVO: createLivo with cfg.fees.livoCreationUsdc. Fuse: createFuse.

2 — Buy on bootstrap (Discovery / LIVO)

// market from GET /markets/:id → .market
const marketAbi = [{
  type: "function",
  name: "buy", // LIVO Phase-1 also has buyPrimary
  stateMutability: "payable",
  inputs: [{ name: "minTokensOut", type: "uint256" }],
  outputs: [],
}];

await client.writeContract({
  address: market,
  abi: marketAbi,
  functionName: "buy",
  args: [0n], // set a real minTokensOut in production
  value: parseEther("10"), // 10 native USDC
});

3 — Pool swap via SwapHelper

// Approve ERC-20 USDC (6 dec) to cfg.addresses.swapHelper, then:
await client.writeContract({
  address: cfg.addresses.swapHelper,
  abi: [{
    type: "function",
    name: "exactInputSingle",
    stateMutability: "nonpayable",
    inputs: [
      { name: "pool", type: "address" },
      { name: "tokenIn", type: "address" },
      { name: "amountIn", type: "uint256" },
      { name: "amountOutMin", type: "uint256" },
      { name: "recipient", type: "address" },
      { name: "deadline", type: "uint256" },
    ],
    outputs: [{ name: "amountOut", type: "uint256" }],
  }],
  functionName: "exactInputSingle",
  args: [
    pool,
    cfg.quote.erc20.address,
    10_000_000n, // 10 USDC (6 dec)
    minOut,      // required — 0 reverts
    account.address,
    BigInt(Math.floor(Date.now() / 1000) + 300),
  ],
});

Rate limits & cost

  • 60 requests/minute per IP across all /api/v1
  • 30/minute additional cap on trades, search, profile
  • Upload: 8/minute (shared with logo route)
  • Responses include Cache-Control — clients and edges should honor it
  • 429 responses set Retry-After: 30

Prefer /config + list endpoints over polling trades every second. Index lag is normal — confirm critical state on-chain when needed.

Related

Developers