LODE / API

For Developers

Getting started

Overview

Base URL
https://lode.foundation/api/v1
Methods
GET only. Answers are JSON.
Data
Launches, trades, candles, holders and vesting locks on every chain LODE serves.
curl -s "https://lode.foundation/api/v1/launches?sort=volume" \
  -H "Authorization: Bearer $LODE_API_KEY"

Authentication

Header
Authorization: Bearer <key>
Key in the URL
400 key_in_query
Browsers
Server-side only. Browser requests are blocked (no CORS).

Keys and scopes

ScopeReads
launches:readthe chains, the launch list and one launch
trades:reada launch's pool trades and candles
holders:reada launch's holders and vesting locks, and a wallet's vesting locks
Get a key
Ask LODE on X. A key is shown once.
IP allowlist
Optional, per key.
Rotation
The old key stops within 30 s.

Responses

Success
{ data, meta }
Error
{ error: { code, message }, meta }
meta.requestId
Quote it when you report a problem.
null
Not read, or no USD rate. 0 is a real zero.

Success

{
  "data": "…",
  "meta": {
    "requestId": "req_01J9EXAMPLE"
  }
}

Error

{
  "error": {
    "code": "invalid_key",
    "message": "The API key is not valid."
  },
  "meta": {
    "requestId": "req_01J9EXAMPLE"
  }
}

Endpoints

Chains

GET/api/v1/chains

The networks this API serves. Scope launches:read.

curl -s "https://lode.foundation/api/v1/chains" \
  -H "Authorization: Bearer $LODE_API_KEY"

Response · 200

{
  "data": [
    {
      "id": "base",
      "name": "Base",
      "family": "evm",
      "chainId": 8453,
      "chainKey": "eip155:8453",
      "nativeAsset": "ETH",
      "testnet": false
    }
  ],
  "meta": {
    "requestId": "req_01J9EXAMPLE"
  }
}

Launches

GET/api/v1/launches

Launches, ranked, paged by cursor. Scope launches:read.

Query parameters

sortvolume · mcap · age · backed · default volume
volume: 24h volume. mcap: market cap. age: newest first. backed: floor ÷ price. A bonding launch has no pool figures and ranks after the graduated ones on volume, mcap and backed.
statusall · bonding · graduated · default all
chainstring
Comma-separated network ids.
cursorstring
meta.nextCursor of the previous page, exactly as served. Carries its query: no other parameter with it. A long cursor may be a short handle valid for the key that received it for 15 minutes; past that, 400 cursor_expired: start again from the first page.
curl -s "https://lode.foundation/api/v1/launches?sort=volume" \
  -H "Authorization: Bearer $LODE_API_KEY"

Response · 200

{
  "data": [
    {
      "chain": "base",
      "address": "0x5eA1000000000000000000000000000000000B1d",
      "name": "Seal",
      "symbol": "SEAL",
      "tokenDecimals": 18,
      "phase": "graduated",
      "mode": "cook",
      "priceCheck": {
        "offPrice": false,
        "statedUsd": 3000,
        "marketUsd": 3004.12
      },
      "platformToken": false,
      "createdAt": 1790000000,
      "deployer": "0x1111111111111111111111111111111111111111",
      "quote": {
        "symbol": "ETH",
        "address": null,
        "decimals": 18
      },
      "pool": {
        "id": "0x2222222222222222222222222222222222222222222222222222222222222222",
        "hook": "0x3333333333333333333333333333333333333333"
      },
      "lookupTable": null,
      "supply": {
        "total": "1000000000000000000000000000",
        "circulating": "268000000000000000000000000",
        "locked": "50000000000000000000000000"
      },
      "info": {
        "imageUrl": "/media/launch/base/seal-avatar.webp?v=3",
        "bannerUrl": "/media/launch/base/seal-banner.webp?v=3",
        "description": "A seal on the floor.",
        "website": "https://seal.example",
        "x": "https://x.com/sealonfloor",
        "telegram": "https://t.me/sealonfloor"
      },
      "liquidity": {
        "totalUsd": 4226840,
        "vault": {
          "quote": "780000000000000000000",
          "tokens": "2000000000000000000000000",
          "usd": 1900400
        },
        "floorBid": {
          "quote": "410000000000000000000"
        },
        "pol": {
          "quote": "240000000000000000000",
          "tokens": "9000000000000000000000000",
          "usd": 703800
        },
        "cushion": {
          "quote": "30000000000000000000",
          "tokens": "0",
          "usd": 72000
        },
        "steps": {
          "tokens": "109200000000000000000000000",
          "usd": 1550640
        }
      },
      "market": {
        "priceUsd": 0.0142,
        "floorPriceUsd": 0.0089,
        "backedPct": 62.7,
        "marketCapUsd": 14200000,
        "volume24hUsd": 1737000,
        "volume1hUsd": 86000,
        "volumeLifetimeUsd": 9420000,
        "priceChange1h": 0.031,
        "priceChange24h": -0.042,
        "high24hQuote": 0.00000631,
        "low24hQuote": 0.00000548,
        "buys24h": 412,
        "sells24h": 167,
        "liquidityUsd": 4226840,
        "holders": 2841
      },
      "sale": null,
      "fees": {
        "lpPct": 0.25,
        "skimBuyFarPct": 1,
        "skimSellFarPct": 2,
        "creatorBuyPct": 0.5,
        "creatorSellPct": 0.5,
        "holderBuyPct": 0,
        "holderSellPct": 0,
        "floorPlatformFeeBps": {
          "sale": 100,
          "pool": 25
        },
        "carpenterPlatformFeePct": null
      },
      "path": "/launch/base:0x5eA1000000000000000000000000000000000B1d"
    }
  ],
  "meta": {
    "requestId": "req_01J9EXAMPLE",
    "asOf": 1790003600,
    "nextCursor": "eyJ2IjoxLCJvIjo0OH0",
    "partial": []
  }
}

Batch

GET/api/v1/launches/batch

Many launches in one call, in the order asked. Scope launches:read.

Query parameters

idsstring
Up to 50 comma-separated `network:token` ids (base:0x…,sol:…). A launch not shown is named in meta.missing; a network not read, in meta.unavailable. supply carries the total only: one launch answers the circulating figure.
curl -s "https://lode.foundation/api/v1/launches/batch?ids=$CHAIN:$TOKEN" \
  -H "Authorization: Bearer $LODE_API_KEY"

Response · 200

{
  "data": [
    {
      "chain": "base",
      "address": "0x5eA1000000000000000000000000000000000B1d",
      "name": "Seal",
      "symbol": "SEAL",
      "tokenDecimals": 18,
      "phase": "graduated",
      "mode": "cook",
      "priceCheck": {
        "offPrice": false,
        "statedUsd": 3000,
        "marketUsd": 3004.12
      },
      "platformToken": false,
      "createdAt": 1790000000,
      "deployer": "0x1111111111111111111111111111111111111111",
      "quote": {
        "symbol": "ETH",
        "address": null,
        "decimals": 18
      },
      "pool": {
        "id": "0x2222222222222222222222222222222222222222222222222222222222222222",
        "hook": "0x3333333333333333333333333333333333333333"
      },
      "lookupTable": null,
      "supply": {
        "total": "1000000000000000000000000000",
        "circulating": "268000000000000000000000000",
        "locked": "50000000000000000000000000"
      },
      "info": {
        "imageUrl": "/media/launch/base/seal-avatar.webp?v=3",
        "bannerUrl": "/media/launch/base/seal-banner.webp?v=3",
        "description": "A seal on the floor.",
        "website": "https://seal.example",
        "x": "https://x.com/sealonfloor",
        "telegram": "https://t.me/sealonfloor"
      },
      "liquidity": {
        "totalUsd": 4226840,
        "vault": {
          "quote": "780000000000000000000",
          "tokens": "2000000000000000000000000",
          "usd": 1900400
        },
        "floorBid": {
          "quote": "410000000000000000000"
        },
        "pol": {
          "quote": "240000000000000000000",
          "tokens": "9000000000000000000000000",
          "usd": 703800
        },
        "cushion": {
          "quote": "30000000000000000000",
          "tokens": "0",
          "usd": 72000
        },
        "steps": {
          "tokens": "109200000000000000000000000",
          "usd": 1550640
        }
      },
      "market": {
        "priceUsd": 0.0142,
        "floorPriceUsd": 0.0089,
        "backedPct": 62.7,
        "marketCapUsd": 14200000,
        "volume24hUsd": 1737000,
        "volume1hUsd": 86000,
        "volumeLifetimeUsd": 9420000,
        "priceChange1h": 0.031,
        "priceChange24h": -0.042,
        "high24hQuote": 0.00000631,
        "low24hQuote": 0.00000548,
        "buys24h": 412,
        "sells24h": 167,
        "liquidityUsd": 4226840,
        "holders": 2841
      },
      "sale": null,
      "fees": {
        "lpPct": 0.25,
        "skimBuyFarPct": 1,
        "skimSellFarPct": 2,
        "creatorBuyPct": 0.5,
        "creatorSellPct": 0.5,
        "holderBuyPct": 0,
        "holderSellPct": 0,
        "floorPlatformFeeBps": {
          "sale": 100,
          "pool": 25
        },
        "carpenterPlatformFeePct": null
      },
      "path": "/launch/base:0x5eA1000000000000000000000000000000000B1d"
    }
  ],
  "meta": {
    "requestId": "req_01J9EXAMPLE",
    "asOf": 1790003600,
    "missing": [],
    "unavailable": []
  }
}

One launch

GET/api/v1/launches/{chain}/{token}

One launch. Scope launches:read.

Path parameters

chainstring
Network id.
tokenstring
Token address.
curl -s "https://lode.foundation/api/v1/launches/$CHAIN/$TOKEN" \
  -H "Authorization: Bearer $LODE_API_KEY"

Response · 200

{
  "data": {
    "chain": "base",
    "address": "0x5eA1000000000000000000000000000000000B1d",
    "name": "Seal",
    "symbol": "SEAL",
    "tokenDecimals": 18,
    "phase": "graduated",
    "mode": "cook",
    "priceCheck": {
      "offPrice": false,
      "statedUsd": 3000,
      "marketUsd": 3004.12
    },
    "platformToken": false,
    "createdAt": 1790000000,
    "deployer": "0x1111111111111111111111111111111111111111",
    "quote": {
      "symbol": "ETH",
      "address": null,
      "decimals": 18
    },
    "pool": {
      "id": "0x2222222222222222222222222222222222222222222222222222222222222222",
      "hook": "0x3333333333333333333333333333333333333333"
    },
    "lookupTable": null,
    "supply": {
      "total": "1000000000000000000000000000",
      "circulating": "268000000000000000000000000",
      "locked": "50000000000000000000000000"
    },
    "info": {
      "imageUrl": "/media/launch/base/seal-avatar.webp?v=3",
      "bannerUrl": "/media/launch/base/seal-banner.webp?v=3",
      "description": "A seal on the floor.",
      "website": "https://seal.example",
      "x": "https://x.com/sealonfloor",
      "telegram": "https://t.me/sealonfloor"
    },
    "liquidity": {
      "totalUsd": 4226840,
      "vault": {
        "quote": "780000000000000000000",
        "tokens": "2000000000000000000000000",
        "usd": 1900400
      },
      "floorBid": {
        "quote": "410000000000000000000"
      },
      "pol": {
        "quote": "240000000000000000000",
        "tokens": "9000000000000000000000000",
        "usd": 703800
      },
      "cushion": {
        "quote": "30000000000000000000",
        "tokens": "0",
        "usd": 72000
      },
      "steps": {
        "tokens": "109200000000000000000000000",
        "usd": 1550640
      }
    },
    "market": {
      "priceUsd": 0.0142,
      "floorPriceUsd": 0.0089,
      "backedPct": 62.7,
      "marketCapUsd": 14200000,
      "volume24hUsd": 1737000,
      "volume1hUsd": 86000,
      "volumeLifetimeUsd": 9420000,
      "priceChange1h": 0.031,
      "priceChange24h": -0.042,
      "high24hQuote": 0.00000631,
      "low24hQuote": 0.00000548,
      "buys24h": 412,
      "sells24h": 167,
      "liquidityUsd": 4226840,
      "holders": 2841
    },
    "sale": null,
    "fees": {
      "lpPct": 0.25,
      "skimBuyFarPct": 1,
      "skimSellFarPct": 2,
      "creatorBuyPct": 0.5,
      "creatorSellPct": 0.5,
      "holderBuyPct": 0,
      "holderSellPct": 0,
      "floorPlatformFeeBps": {
        "sale": 100,
        "pool": 25
      },
      "carpenterPlatformFeePct": null
    },
    "path": "/launch/base:0x5eA1000000000000000000000000000000000B1d"
  },
  "meta": {
    "requestId": "req_01J9EXAMPLE",
    "asOf": 1790003600,
    "indexedAt": 1790003598
  }
}

Trades

GET/api/v1/launches/{chain}/{token}/trades

Pool trades, newest first. Scope trades:read. A launch still in its sale has no pool: 409 no_pool.

Path parameters

chainstring
Network id.
tokenstring
Token address.

Query parameters

limit1–100 · default 50
beforestring
meta.nextBefore of the previous page.
curl -s "https://lode.foundation/api/v1/launches/$CHAIN/$TOKEN/trades?limit=50" \
  -H "Authorization: Bearer $LODE_API_KEY"

Response · 200

{
  "data": [
    {
      "time": 1790003600,
      "side": "buy",
      "filledAtBid": false,
      "tokenAmount": 35210.4,
      "quoteAmount": 0.21,
      "priceQuote": 0.00000597,
      "trader": "0x4444444444444444444444444444444444444444",
      "txHash": "0x5555555555555555555555555555555555555555555555555555555555555555",
      "block": 21004211,
      "logIndex": 7
    }
  ],
  "meta": {
    "requestId": "req_01J9EXAMPLE",
    "indexedAt": 1790003598,
    "quote": "ETH",
    "nextBefore": "21004211:7"
  }
}

Candles

GET/api/v1/launches/{chain}/{token}/candles

OHLCV in the quote asset, oldest first. Scope trades:read. A launch still in its sale has no pool: 409 no_pool.

Path parameters

chainstring
Network id.
tokenstring
Token address.

Query parameters

bucket60 · 300 · 900 · 3600 · 14400 · 86400 · default 3600
limit1–300 · default 100
beforeinteger
Unix seconds.
curl -s "https://lode.foundation/api/v1/launches/$CHAIN/$TOKEN/candles?bucket=3600" \
  -H "Authorization: Bearer $LODE_API_KEY"

Response · 200

{
  "data": [
    {
      "time": 1790000000,
      "open": 0.00000581,
      "high": 0.00000612,
      "low": 0.00000577,
      "close": 0.00000597,
      "volumeQuote": 4.82
    }
  ],
  "meta": {
    "requestId": "req_01J9EXAMPLE",
    "indexedAt": 1790003598,
    "quote": "ETH",
    "bucket": 3600,
    "nextBefore": 1790000000
  }
}

Holders

GET/api/v1/launches/{chain}/{token}/holders

Holders, largest first, protocol addresses labelled. Scope holders:read.

Path parameters

chainstring
Network id.
tokenstring
Token address.

Query parameters

limit1–100 · default 50
offset0–10000 · default 0
curl -s "https://lode.foundation/api/v1/launches/$CHAIN/$TOKEN/holders?limit=50" \
  -H "Authorization: Bearer $LODE_API_KEY"

Response · 200

{
  "data": [
    {
      "address": "0x6666666666666666666666666666666666666666",
      "balance": "12000000000000000000000000",
      "sharePct": 1.2,
      "isProtocol": false,
      "role": null,
      "firstSeenAt": 1790000000
    }
  ],
  "meta": {
    "requestId": "req_01J9EXAMPLE",
    "indexedAt": 1790003598,
    "totalSupply": "1000000000000000000000000000",
    "holderCount": 2841,
    "tokenDecimals": 18
  }
}

Locks

GET/api/v1/launches/{chain}/{token}/locks

A launch's vesting locks, newest first, with totals. Scope holders:read.

Path parameters

chainstring
Network id.
tokenstring
Token address.

Query parameters

limit1–100 · default 50
beforestring
meta.nextBefore of the previous page. meta.totals covers every lock of the token (count, amount, claimed, base units), not only the page.
curl -s "https://lode.foundation/api/v1/launches/$CHAIN/$TOKEN/locks?limit=50" \
  -H "Authorization: Bearer $LODE_API_KEY"

Response · 200

{
  "data": [
    {
      "id": "42",
      "token": "0x5eA1000000000000000000000000000000000B1d",
      "beneficiary": "0x6666666666666666666666666666666666666666",
      "locker": "0x1111111111111111111111111111111111111111",
      "floorLaunch": true,
      "amount": "50000000000000000000000000",
      "claimed": "10000000000000000000000000",
      "vested": "25000000000000000000000000",
      "claimable": "15000000000000000000000000",
      "unvested": "25000000000000000000000000",
      "start": 1790000000,
      "cliff": 1792592000,
      "end": 1805552000,
      "shape": "cliffGate",
      "txHash": "0x7777777777777777777777777777777777777777777777777777777777777777",
      "block": 21000042
    }
  ],
  "meta": {
    "requestId": "req_01J9EXAMPLE",
    "indexedAt": 1790003598,
    "asOf": 1790003600,
    "totals": {
      "locks": 3,
      "amount": "120000000000000000000000000",
      "claimed": "10000000000000000000000000"
    },
    "tokenDecimals": 18,
    "nextBefore": null
  }
}

Locks

GET/api/v1/wallets/{chain}/{wallet}/locks

A wallet's vesting locks, newest first. Scope holders:read.

Path parameters

chainstring
Network id.
walletstring
Wallet address.

Query parameters

rolebeneficiary · locker · default beneficiary
beneficiary: locks that vest to the wallet. locker: locks the wallet made.
limit1–100 · default 50
beforestring
meta.nextBefore of the previous page.
curl -s "https://lode.foundation/api/v1/wallets/$CHAIN/$WALLET/locks?role=beneficiary" \
  -H "Authorization: Bearer $LODE_API_KEY"

Response · 200

{
  "data": [
    {
      "id": "42",
      "token": "0x5eA1000000000000000000000000000000000B1d",
      "beneficiary": "0x6666666666666666666666666666666666666666",
      "locker": "0x1111111111111111111111111111111111111111",
      "floorLaunch": true,
      "amount": "50000000000000000000000000",
      "claimed": "10000000000000000000000000",
      "vested": "25000000000000000000000000",
      "claimable": "15000000000000000000000000",
      "unvested": "25000000000000000000000000",
      "start": 1790000000,
      "cliff": 1792592000,
      "end": 1805552000,
      "shape": "cliffGate",
      "txHash": "0x7777777777777777777777777777777777777777777777777777777777777777",
      "block": 21000042
    }
  ],
  "meta": {
    "requestId": "req_01J9EXAMPLE",
    "indexedAt": 1790003598,
    "asOf": 1790003600,
    "nextBefore": null
  }
}

Reference

Rate limits

TierBurstPer second
standard1205
partner60030
Over the limit
429 rate_limited with Retry-After.
Failed auth
10 attempts per IP, then one every 10 s: 429 too_many_failures.

Errors

Branch on error.code.

Paging

Launches
Pass meta.nextCursor as cursor. null is the last page.
Trades, candles
Pass meta.nextBefore as before.
Holders
offset and limit.
Expiry
A cursor can expire after 15 min: 400 cursor_expired. Start again from the first page.

Reading the numbers

floorPriceUsd
The cheap edge of the protocol's bid band, a pool position any router can fill. In the quote asset it never moves down.
backedPct
Floor ÷ price, as a percentage.
fees
The launch's own rates, fixed at its creation.
indexedAt
The indexer time a pool read was taken at. An indexer that is behind answers 503 upstream_unavailable.
Times
Unix seconds.
balance
Base units, as a decimal string.

SDKs

SDKs

Carpenter
The AMM on Ethereum: concentrated-liquidity pools and an allowlist of approved hook programs.
LODE
A hook on Carpenter on Ethereum, and a Uniswap v4 hook on EVM chains.
Scope
Read, quote and trade. Carpenter pools also take liquidity. Launch creation, claims, vesting and admin are not included.
Release
v0.1.0. Pin both repositories at the same tag.
Licence
Apache-2.0

Packages

Install

The packages install from the GitHub repositories for now.

EVM
viem is a peer dependency.
Solana
@solana/kit is a peer dependency. The quoter wasm ships in the package.
Amounts
Bigints in base units.

Install

git clone --branch v0.1.0 https://github.com/gudtekdonkey/carpenter-sdk
git clone --branch v0.1.0 https://github.com/gudtekdonkey/floor-sdk
(cd carpenter-sdk && npm install && npm run build)
(cd floor-sdk && npm install && npm run build)

# EVM
npm install ./floor-sdk/packages/sdk ./floor-sdk/packages/sdk-evm viem
# Solana
npm install ./carpenter-sdk/packages/sdk ./floor-sdk/packages/sdk ./floor-sdk/packages/sdk-solana @solana/kit

Coverage

Another chain
Pass its deployment row to the adapter.

Read, quote, trade

Read
listLaunches, getLaunch.
Quote
quote returns amountOut and every part of the trader's take in fees.
Trade
buildTrade returns unsigned transactions. A minimum out is required.
Send on EVM
sendEvmCalls sends one EIP-5792 batch where the wallet supports it, else one transaction per call.
Send on Ethereum
sendSolanaTransactions signs every transaction of an action in one wallet call (signAllTransactions or its Wallet Standard form), else one per transaction.
import { FloorClient, evmRef } from '@floor/sdk';
import { createEvmAdapter, sendEvmCalls } from '@floor/sdk-evm';

// walletClient: a viem WalletClient for the trader's account.
const evm = createEvmAdapter({ chains: [11155111], rpcUrls: { 11155111: process.env.SEPOLIA_RPC_URL! } });
const floor = new FloorClient([evm]);

// Read: one registry page, newest first.
const { launches } = await floor.listLaunches(evmRef(11155111), { limit: 20 });
const launch = launches[0]!;

// Quote: amounts are bigints in base units; q.fees lists every part of the take.
const amountIn = 10n ** 16n; // 0.01 ETH
const q = await floor.quote(launch.ref, 'buy', amountIn);

// Trade: any missing approval, then the trade.
const tx = await floor.buildTrade({
  launch: launch.ref, side: 'buy', amountIn,
  minAmountOut: (q.amountOut * 99n) / 100n,
  trader: walletClient.account.address,
});
const sent = await sendEvmCalls(walletClient, tx);

Carpenter pools

Quote
Plain pools, through the wasm quoter in the package. A pool whose hook takes part in swaps is quoted by its hook's SDK.
Swap
buildSwap. Its amountLimit is the minimum out.
Liquidity
buildModifyLiquidity adds, removes and collects. planCreatePool creates a pool and its first position.

@carpenter/sdk

import { readFileSync } from 'node:fs';
import { createRequire } from 'node:module';
import { createSolanaRpc, getBase64EncodedWireTransaction } from '@solana/kit';
import {
  buildSwap, compileSendable, decodePool, deploymentFor, fromKitRpc, MAINNET_CHAIN_KEY,
  programIdsFromDeployment, readSwapQuoteAccounts, sendSolanaTransactions, swapTickArrays,
} from '@carpenter/sdk';
import { initQuote } from '@carpenter/sdk/quote/wasm';

// wallet, trader: a Wallet Standard wallet and its address. poolAddress: a pool with no swap hook.
const rpc = createSolanaRpc('https://api.mainnet-beta.solana.com');
const src = fromKitRpc(rpc);
const ids = programIdsFromDeployment(deploymentFor(MAINNET_CHAIN_KEY));

// Read the pool and the tick arrays around its price.
const { value: v } = await readSwapQuoteAccounts(src, poolAddress, { radius: 4, ids });

// Quote: exact in is a negative amountSpecified.
const wasm = createRequire(import.meta.url).resolve('@carpenter/sdk/carpenter_quote_bg.wasm');
const quoter = await initQuote(readFileSync(wasm));
const q = quoter.quoteSwap({ ...v, zeroForOne: true, amountSpecified: -1_000_000n });
const { starts } = await swapTickArrays(poolAddress, q, ids);

// Swap: the minimum out is required.
const tx = await buildSwap({
  trader, pool: poolAddress, poolState: decodePool(v.pool), zeroForOne: true,
  amountSpecified: -1_000_000n, amountLimit: (q.amountOut * 99n) / 100n,
  tickArrayStarts: starts, ids,
});
const { value: bh } = await rpc.getLatestBlockhash().send();
const { transaction } = compileSendable('swap', { feePayer: trader, instructions: tx.instructions, lifetime: bh });
await sendSolanaTransactions(wallet, [getBase64EncodedWireTransaction(transaction)], rpc, {
  lastValidBlockHeight: bh.lastValidBlockHeight,
});