# API reference

V1: coins launched before factory v2. This tab applies to coins launched before factory v2, from the v1 factory, and only to them. Nothing new launches there: every new launch is v2, in the V2 tab.

All endpoints are under `https://www.pangea.trade/api`, take and return JSON, and need no key or account. The general rules are in [For integrators](https://www.pangea.trade/app/docs?v=1#v1-integrators), which also describes five of them in full: pools, history, bridge activity, token metadata and the bridge quote. The relayers’ price board is in [Relayers](https://www.pangea.trade/app/docs?v=1#v1-relayers). This section lists all of them and describes the rest.

- An error is `{ "error": "..." }` with a 4xx status (a 5xx is a fault, and its body may be a proxy's own). A value the chains could not give is `null`, not a guess.
- Limits are per caller, by IP address, counted on each server. Over a limit the answer is `429` and the message says how many seconds to wait; some also send `Retry-After`.
- A JSON body that is too large is `413`, one that is compressed is `415`, one that does not arrive within 10 seconds is `408`, and one that is not a JSON object of the expected fields is `400`.
- Amounts are base units as decimal strings. Chains are named `ethereum`, `base`, `robinhood`, `bsc` and `solana`. A launch is named by its slug.
- Three endpoints answer as a stream of server-sent events: `data: <json>` lines, with `content-type: text/event-stream`. Read them with a streaming fetch; they are POST, so an `EventSource` cannot open them. The Launch API’s event stream and the launches stream are GETs, in the same format with named events.
- A coin is named by its slug, its launch id or any chain’s token address wherever the path says `[id]`. The coin, its supply, the pools, the holders and the launches feed carry `degen` and the coin’s supply: circulating, the bridge reserve and where it is held, the total, and what each chain mints and each token reports.

## Every public endpoint

| Endpoint | What it is for | Limit per caller |
| --- | --- | --- |
| `GET /pools` | Every launch and its pool on each chain. | None; one shared reading. |
| `GET /history` | Trades, volume and price candles. | 30 in ten minutes, uncached reads only. |
| `GET /holders` | Who holds a token, per chain. | 60 in ten minutes, uncached reads only. |
| `GET /token/meta` | A token’s metadata document. | None. |
| `GET, POST /token/socials` | Who may edit a coin’s socials (its creator, EVM and Solana); with history=1 every version so far, each with the creator’s signature, and with onchain=1 each EVM chain’s metadata authority and URI; POST stores a new version the creator signed (EIP-712, or a signed message on Solana) with a new website, X, Telegram, Discord, description or logo. No transaction and no gas: /token/meta shows the newest version, marked as edited by the creator. | GET 120 a minute, 10 with onchain=1. POST 30 attempts in ten minutes; 10 stored edits an hour, and 6 an hour and 24 a day per coin. |
| `GET /logo/[cid]/[file]` | A token’s logo from this site, as square WebP: the file is 64.webp, 128.webp or 256.webp, and the CID is the image’s own, as /token/meta names it. Cached for a year: a CID’s picture cannot change. | None. |
| `GET /platform-funds` | The platform’s fee balance on each chain, in native units and US dollars, with the total. | None; one shared reading a minute. |
| `GET /creator-rewards` | Everything launches’ trading fees have paid to their creators, all time: per chain in native units and US dollars at today’s prices, with the total and which chains are not counted in full. | None; one shared reading a minute. |
| `GET /bridge/activity` | Recent transfers between chains. | None. |
| `GET /bridge/balance` | One address’s balance of a token or the native asset. | 120 in ten minutes |
| `POST /bridge/quote` | A transfer priced, both lanes, with the transaction to sign. | 120 in ten minutes, 15 a minute. |
| `POST /bridge/solana-tx` | The unsigned transaction for a transfer out of Solana. | 60 in ten minutes, 10 a minute. |
| `POST /bridge/solana-fast-tx` | The same, as a fast order. | 60 in ten minutes, 10 a minute. |
| `POST /bridge/route-open` | Opens a Solana route once its setup payment has landed. | 120 in ten minutes |
| `POST /bridge/arrival` | A stream that says when a transfer has arrived. | 60 in ten minutes |
| `POST /bridge/refund` | Whether a fast order is held, and the transaction that sends it back. | 60 in ten minutes |
| `POST /bridge/orders` | Tells the board a fast order was posted at a relayer’s price. | 60 in ten minutes |
| `GET, POST /bridge/relayer-quotes` | The relayers’ price board. | 300 in ten minutes reads, 120 publishes. |
| `POST /chain/tx` | A stream that says when a transaction is in a block. | 60 in ten minutes |
| `POST /trade/quote` | A buy or sell priced through Relay, or Jupiter on Solana. | 60 a minute. |
| `POST /trade/solana-tx` | Compiles a swap’s Solana instructions into an unsigned transaction. | 60 in ten minutes |
| `GET /token/launch-buys` | Who bought in a launch’s own block, per chain, and whether that block has been read. | 60 in ten minutes, uncached reads only. |
| `GET /coin/[id]` | One coin: its addresses, degen mode, its supply, and its tokenomics config as its launch signed it. No chain is read. | 120 a minute. |
| `GET /coin/[id]/supply` | A coin’s supply: what its launch made, and for a degen mode coin the same read from the chains. | 60 a minute. |
| `GET /coin/[id]/tokenomics` | A coin’s tokenomics config, and each chain’s vault read from the chain: what waits in each bucket, and what was burned, bought and added to liquidity. | 20 a minute. |
| `POST /v1/launch/prepare` | A launch quoted, with the ticket every later step takes. | 12 in ten minutes, shared with the launch page. |
| `POST /v1/launch/authorization` | The permission a creator wallet signs for another launching wallet. | 30 in ten minutes |
| `POST /v1/launch/pay` | The transaction that pays the launch fee. | 30 in ten minutes |
| `POST /v1/launch/submit` | Hands a paid launch to Pangea’s launcher. | 30 in ten minutes |
| `GET /v1/launch/status` | Where a launch stands, chain by chain. | 300 in ten minutes |
| `GET /v1/launch/events` | The same, as a stream of events. | 30 opened in ten minutes, 3 open at once. |
| `GET /v1/launches` | Every coin launched here, newest first, a page at a time. | 60 a minute. |
| `GET /v1/launches/stream` | Every new launch the moment it is live, as server-sent events. | 30 opened in ten minutes, 3 open at once. |
| `POST /v1/launch/kit` | What you need to make your own launch-time buys. | 30 in ten minutes |
| `POST /v1/launch/solana-cosigned` | Not available yet: answers 409. | None. |

> **Note:** The launch endpoints under `/v1/launch` are described in [Launch API →](https://www.pangea.trade/app/docs#launch-api)

## GET /coin/{id}

- Coin, GET: `https://www.pangea.trade/api/coin/{slug, launch id or token address}`

One coin as the site knows it, with no chain read: `{ slug, name, symbol, launchId, listedAt, launchChains, chains, degen, factoryGen, supplyMode, supply, tokenomics, tokenomicsKnown }`. `chains` is each chain’s `{ token, pool }`. `factoryGen` is 1 or 2; `supplyMode` is factory v2’s, 0 (1B on each chain) or 1 (degen mode), and null on a factory v1 coin. `tokenomics` is the config the launch’s quote signed, or null for none; `tokenomicsKnown: false` means it could not be read, so null is then not “none”. Errors: `400` for an id that cannot be a coin’s, `404` for one not launched here.

| Field | What it is |
| --- | --- |
| `degen` | `true` for a coin launched in degen mode: 1B in all, an equal share minted and paired on each chain, every chain’s token reporting the 1B. [Degen mode →](https://www.pangea.trade/app/docs#degen-mode) |
| `supply.total` | The launch’s whole supply, in whole tokens, as a string: 1B for degen mode (999,999,999 on three chains, whose equal shares are whole tokens), 1B a chain otherwise. |
| `supply.circulating` | What the chains minted and paired, in all: 1B in degen mode. The bridge reserve backs the other chains and is not extra supply, so it is never taken off circulating; `/coin/{id}/supply`’s `live` takes off what was burned and reads the bridge reserve as it is now. |
| `supply.reserve`, `supply.reserveChain` | The rest of a degen mode coin’s supply, held in Solana’s bridge reserve, and `solana`. `0` and null without one. |
| `supply.perChain` | What each chain minted and paired, by chain. |
| `supply.reportedPerChain` | What every chain’s `totalSupply()` reports in degen mode, the 1B; null otherwise, where each chain reports its own. |
| `supply.circulatingShareBps` | In degen mode, what one chain mints as a share of the total, in basis points: 2,000 on five chains. 10,000 where each chain holds a whole supply of its own; null where the supply figures are. |
| `supply.supplyModel` | `perChain` for 1B on each chain, `global` for one supply (degen mode, and launches before 2026-10-15, whose figures are null here: `/pools` reads them off the token). |
| `tokenomics.perChain` | Each chain’s split by bucket, in basis points: `{ burn, buyback, liquidity, creator, community }`, adding up to 10,000. |
| `tokenomics.vault`, `tokenomics.owner` | The coin’s vault on the EVM chains, the fee receiver its trading fees are paid to, and its owner, the creator, who receives the creator share. |
| `tokenomics.treasury`, `tokenomics.community` | The wallets the bought-and-held coins and the community share go to on the EVM chains; null when no chain uses that bucket. |
| `tokenomics.solana` | `{ account, owner, treasury, community }`: the coin’s tokenomics account on Solana and its wallets there; null without Solana. |
| `tokenomics.version` | `1` for the config above. Another value is a kind this API does not describe yet, and carries only `version` and `vault`. |

## GET /coin/{id}/supply

- Supply, GET: `https://www.pangea.trade/api/coin/{id}/supply`

The answer is `{ slug, name, symbol, launchId, launchChains, degen, supply, live, liveError? }`. `supply` is the same as on the coin. For a degen mode coin, `live` is read from the chains and kept a minute: `{ mode, total, reserve, circulating, burned, burnedUnread, perChain, burnedPerChain, reserveAddress, decimals, onSolana, chains }`, in base units as strings, where `total` is what the tokens report, `reserve` what Solana’s bridge reserve at `reserveAddress` holds now, and `circulating` the total less what was burned (never less the bridge reserve, which backs the other chains and is not extra supply); `perChain` is what is on each chain, Solana’s its own float with the bridge reserve apart. A figure the chains did not give is null. `live` is null for any other coin and with `?live=0`; `liveError: "busy"` means the shared budget of chain reads is spent for the minute.

## GET /coin/{id}/tokenomics

- Tokenomics, GET: `https://www.pangea.trade/api/coin/{id}/tokenomics`

The answer is `{ slug, name, symbol, launchId, launchChains, tokenomics, tokenomicsKnown, chains }`. `tokenomics` is the coin’s config, as on the coin. `chains` is each chain’s vault read from the chain, `{ tokenomics }`, or null with an `error` when that chain could not be read. A vault has its `split`, `buckets` (what waits in each, in the chain’s native unit), `spent`, and `totals`: `receivedWei`, `coinBurned`, `coinToTreasury` (bought and held), `liquidityAdded`, `gasRepaidWei`. A coin its launch’s config says has no tokenomics is read on no chain. `?live=0` answers the config alone. Each chain’s reading is shared with the coin page and kept a while: a vault five minutes, no vault 24 hours, a chain that could not be read half a minute. `404` while tokenomics is switched off on this deployment.

## GET /v1/launches

- Launches, GET: `https://www.pangea.trade/api/v1/launches?limit=25`

Every coin launched here, newest first: `{ launches, next, latest, readAt }`. Each launch is `{ id, slug, name, symbol, launchId, listedAt, launchedAt, launchChains, chains, degen, factoryGen, supplyMode, supply, tokenomics, image, platform }`: `chains` each chain’s `{ token, pool }`, `supply` is `{ total, circulating, reserve, reserveChain }`, `tokenomics` is `{ on: false }`, or `{ on: true, version, vault, buckets, chains }` naming the buckets any chain uses, or null while it is not known; `image` the coin’s logo on this site, or null until it is stored. A coin is listed once it has landed and its pools are open. `id` is its cursor, `<listedAt>:<slug>`.

- `limit`: 1 to 100, 25 by default.
- `before`: the previous page’s `next`, for the page after it. `next` is null on the last page. To catch up, send the same `since` with each page.
- `since`: a cursor, for the coins listed after it, or unix seconds, for the coins listed in that second or later. A coin can be listed a little after one with a later time, so to catch up, ask from a minute or two before the newest you have and drop the ids you already hold.
- `latest`: the newest coin’s cursor. Open the stream with it as `since` and nothing is missed between the two.

The newest launches, then the page after:

```bash
curl -s "https://www.pangea.trade/api/v1/launches?limit=10"
curl -s "https://www.pangea.trade/api/v1/launches?limit=10&before=<next>"
```

## GET /v1/launches/stream

- Launches stream, GET: `https://www.pangea.trade/api/v1/launches/stream`

Every new launch as server-sent events, the moment it is live. Each is an `event: launch` with the launch, as `/v1/launches` lists it, as its data, and, for a launch newer than any sent before, its cursor as the event `id`. After the first catch-up comes one `event: ready` with `{ latest }`. To miss nothing across a reconnect, send the last id you saw as `Last-Event-ID` (an `EventSource` does this by itself) or as `?since=`: the launches listed after it come first, oldest first, up to 100 at a time. Without either, only launches from now on. The `ready` event carries the stream’s place as its id too, so a reconnect before any launch still resumes. A coin can become visible a little after one listed later, so the stream also looks two minutes back and sends such a coin with no event id, keeping your place. A resume sends those two minutes again, so a launch can come twice: drop the ones whose data’s id you have. A comment line comes every 15 seconds; the stream closes after 30 minutes, so reconnect with the last id. Send `Accept: text/event-stream`. At most 3 open per caller; it takes requests from programs and from the Pangea site, like the Launch API.

> **Note:** Server-sent events are the realtime API: one long GET that any HTTP client can read, that resumes by itself, and that passes every proxy. There is no public WebSocket; the site’s own live socket serves its pages only.

Follow new launches with curl:

```bash
curl -N -H "Accept: text/event-stream" "https://www.pangea.trade/api/v1/launches/stream"
```

Follow new launches with EventSource (Node: npm install eventsource):

```js
import { EventSource } from "eventsource";

const stream = new EventSource("https://www.pangea.trade/api/v1/launches/stream");
stream.addEventListener("launch", (e) => {
  const coin = JSON.parse(e.data);
  console.log(coin.symbol, coin.degen ? "degen" : "", coin.chains);
});
// It reconnects by itself and sends the last id as Last-Event-ID, so nothing is missed.
```

## GET /holders

- Holders, GET: `https://www.pangea.trade/api/holders`

Query: `token`, a slug, required; `chain`, optional, to answer for one chain. The answer is `{ slug, readAt, launchTotal, degen, supply, chains, all }`, where `degen` and `supply` are as on `/coin/[id]`, and each of `chains` is `{ chain, count, top10Pct, rows, complete, note?, error? }` and each row `{ chain, address, balance, pct, label }`, balances in whole tokens, at most 100 rows a chain. `all` combines the chains, `{ rows, count, partial, top10Pct }`, and is left out when `chain` is given. `label` names a known holder such as the pool or the bridge escrow. An answer is reused for a minute. Errors: `400` without a token, `404` for an unknown launch or a chain it is not on.

## GET /bridge/balance

- Balance, GET: `https://www.pangea.trade/api/bridge/balance`

Query: `token` (slug), `chain` and `address`, all required, and `asset=native` to read the chain’s native asset instead of the token. The answer is `{ slug, chain, address, balance, decimals, reason?, reserve? }`: `balance` in base units as a string, or `null` with a `reason` when the chain could not be read, never a false zero. On Solana the token balance is the sum of the owner’s token accounts for the mint. For the native asset, `reserve` is the gas the app keeps back for a trade. Errors: `400` for a missing field or an address of the wrong kind, `404` for an unknown launch or chain.

## POST /bridge/quote, in full

Beyond the fields in [For integrators](https://www.pangea.trade/app/docs?v=1#v1-integrators), the body may carry `slippageBps` for the fast lane, 50 unless given and 1000 at most, and `smartWallet`, true when the sender is a contract wallet. The answer’s `routes` holds two routes, `canonical` and `fast`, and a route that cannot be used says why in `unavailable`. Besides the fields listed there, a route may carry:

| Field | What it is |
| --- | --- |
| `label` | `Standard` or `Fast`. |
| `fastFee`, `relayerFee`, `relayer` | On the fast route: the fast lane’s fee, the relayer’s price and who it is, in base units. |
| `minReceived` | On the fast route: the least the order lets the recipient be paid. |
| `approval` | On the fast route from an EVM chain: the approval to send first, `{ to, data, value, chainId }`, or null when none is needed. |
| `solanaFast` | On the fast route out of Solana: `{ relayerFee, minReceived }`, for `/bridge/solana-fast-tx`. |
| `routePayment` | From an EVM chain into a Solana route that is not open: the one-time setup payment, `{ to, data, value, chainId }`, to send before the transfer. |
| `setupNote`, `messageFeeLater` | Out of Solana with a route to open: the setup is paid first and LayerZero’s fee is priced after it. |
| `feeIsMaximum` | `nativeFee` is the most the Solana transaction will sign; LayerZero charges what its workers quote. |
| `note` | A sentence about the route, for showing to a person. |

Further errors: `409` when the token has not launched on the destination, `424` when a Solana recipient could not be checked, and `424` with `retry: true` when pricing took longer than 45 seconds.

## POST /bridge/solana-tx

- Out of Solana, POST: `https://www.pangea.trade/api/bridge/solana-tx`

The body you POST:

```json
{
  "slug": "<launch slug>",
  "to": "base",
  "amount": "1000000000000",
  "sender": "<Solana wallet>",
  "recipient": "0x<EVM address>"
}
```

Builds the unsigned transaction that sends the token from Solana to an EVM chain, for the sender to sign. `after` and `afterValidUntil` are given only on a second call after a setup step. The answer carries the request’s `from`, `to`, `amount` and `symbol` and one of three stages:

| Stage | What to do |
| --- | --- |
| `send` | Sign `transaction`, a base64 versioned transaction, and send it. `received` is what arrives, `nativeFee` LayerZero’s fee and `nativeFeeCap` the most it will sign. |
| `together` | The same, with the route’s opening in the same transaction. `setupFee` is the opening’s part of `totalFee`. |
| `setup` | The opening alone. Sign and send it, then call again with `after` set to its signature for the send. |

Every stage carries `blockhash` and `lastValidBlockHeight`: sign within about a minute. While a setup step is still settling the answer is `202` with `{ pending: true, stage: "waiting" }`; ask again. Errors: `400` for a bad field or a signature that is not this transfer’s setup, `404` for an unknown launch, `409` when the setup ran out or failed, the route is unusable or the wallet is short of SOL, `424` when the build takes longer than usual, with `retry: true`, and `424` after 50 seconds.

## POST /bridge/solana-fast-tx

- Fast out of Solana, POST: `https://www.pangea.trade/api/bridge/solana-fast-tx`

The fast lane out of Solana: one unsigned transaction holding Pangea’s fast-bridge order and the OFT send that carries it. Body: `{ slug, to, recipient, amount, relayerFee, minReceived, sender }`, with `relayerFee` and `minReceived` from the quote’s `solanaFast`. The answer is `{ stage: "send", transaction, orderId, amount, arriving, fastFee, relayerFee, nativeFee, nativeFeeCap, blockhash, lastValidBlockHeight }`. Errors: `409` when the fast lane is off for this launch or route, `422` when the order could not be built, nothing having been sent.

## POST /bridge/route-open

- Open a Solana route, POST: `https://www.pangea.trade/api/bridge/route-open`

The second step of the first transfer from an EVM chain into a Solana route: once the quote’s `routePayment` has been sent, this hands its transaction to Pangea’s delivery service, which checks the payment on chain and opens the route, or refunds it. Body: `{ slug, from, txHash, sender }`, `from` being the EVM chain the payment was made on. With `Accept: text/event-stream` it streams `{ state, reason?, refundTx? }` as the route is opened; otherwise it answers once. `state` is one of `verifying`, `paid`, `opening`, `open`, `refunded`, `refund-owed`, `review` and `refused`. Send the transfer once it is `open`. Errors: `404` for a launch not on Solana, `424` when routes cannot be opened from this deployment.

## POST /bridge/arrival

- Arrival stream, POST: `https://www.pangea.trade/api/bridge/arrival`

Body: `{ txHash }`, the send’s transaction hash or Solana signature. A stream of `{ state, route, guid, dstTx?, by? }`, `state` being `in-flight` and then `delivered`, with the delivery’s transaction in `dstTx`. It is fed by Pangea’s delivery service, which remembers a transfer for 30 minutes. Errors: `400` for a malformed hash, `424` when the deployment does not serve arrivals; LayerZero Scan answers the same question.

## POST /bridge/refund

- Held fast orders, POST: `https://www.pangea.trade/api/bridge/refund`

Body: `{ chain, orderId }`, the destination chain and the fast order’s id. The answer is `{ held: false }` or `{ held: true, guid, amount, srcEid, call }`, where `call` is the `refund(guid)` transaction, `{ to, data, value, chainId }`, with LayerZero’s fee for the trip back as its value. It looks back 5,000 blocks. Errors: `400` for a malformed id or a chain without a fast bridge.

## POST /bridge/orders

- Report a fast order, POST: `https://www.pangea.trade/api/bridge/orders`

Body: `{ from, hash }`, the chain a fast order was posted on and its transaction. The board reads the order from the receipt and remembers whose price it was sent at, which is how a relayer that does not fill is benched. The answer is `202` with `{ recorded: false, pending: true }` before the receipt exists, then `{ recorded, relayer, why?, orderId, to, srcBridge }`. Only orders priced from this deployment’s board are recorded; `why` says why not.

## POST /chain/tx

- Transaction stream, POST: `https://www.pangea.trade/api/chain/tx`

Body: `{ chain, hash }`. One event when the transaction is in a block: `{ state: "mined", success, block }` on an EVM chain, `{ state: "mined", success }` on Solana, or `{ state: "unseen" }` if it never appears, after up to 10 minutes on an EVM chain and 5 on Solana.

## Trading: POST /trade/quote and POST /trade/solana-tx

These are the trade card’s, as they are in release r41, and are due to change. `/trade/quote` takes `{ slug, side, chain, amount, fromChain?, user?, solanaUser?, recipient?, slippageBps? }`: `side` is `buy` or `sell`, `chain` a chain name or `auto` for the cheapest chain to buy on or the dearest to sell on, and `amount` the native asset’s base units for a buy, the token’s for a sell. `slippageBps` is the slippage, how far below the quote the trade may fill: a whole number of basis points from 1 to 9900 (0.01% to 99%), 100 unless given. The trade card sets it with its Slippage presets or a custom value. It prices the trade through Relay, or Jupiter for a trade within Solana, and answers `{ chain, fromChain, crossChain, cheapestNote, unroutable, details, steps }`, passing the router’s own `details` and `steps` through. Errors: `400`, `404`, `422` with the reason when no route was found, and `424` when a chain or the router could not be reached or took too long (with `retry: true` where trying again can help). Never a 5xx: a proxy in front may replace a 5xx body.

`/trade/solana-tx` takes `{ instructions, addressLookupTableAddresses?, payer }`, a swap step’s Solana instructions as the quote gives them, at most 24 instructions and 8 lookup tables, and answers `{ transaction, blockhash, lastValidBlockHeight }`: an unsigned versioned transaction. It does not inspect what the instructions do, so read them, or let your wallet simulate them, before you sign.

Part of the Pangea documentation, V1 (earlier launches) tab: https://www.pangea.trade/app/docs.md
