# PumpApi Documentation > The fastest & simplest API for Pump.fun, Raydium and Meteora & Solana and token transfers ## Actions ### Actions **Actions** let you combine multiple operations — like `buy`, `sell`, `create`, `transfer`, `claimCashback`, `burn`, and more — into a **single transaction**. Great for increasing token volume, making multiple sales to clean up an account, and other strategies. #### Endpoint[​](#endpoint "Direct link to Endpoint") `POST https://api.pumpapi.io` #### Basic Structure[​](#basic-structure "Direct link to Basic Structure") ```json { "actions": [ { "privateKey": "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "buy", "mint": "token_address", "amount": 0.1, "denominatedInQuote": True, "slippage": 99, "priorityFee": 0.00002 }, { "privateKey": "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "sell", "mint": "token_address", "amount": "100%", "denominatedInQuote": True, "slippage": 99, "priorityFee": 0.00002 } ] } ``` Each object in `actions` follows the same fields as the [Trade API](/trade-api.md). *** #### Priority Fee[​](#priority-fee "Direct link to Priority Fee") `priorityFee` **accumulates across actions** — because each action adds complexity to the transaction. A transaction with two swaps is more complex than with one, so it requires a higher fee to land reliably. ##### Global Priority Fee[​](#global-priority-fee "Direct link to Global Priority Fee") If you want a single `priorityFee` for the whole transaction, set it **above** the `actions` block. Per-action `priorityFee` values will be ignored. ```json { "priorityFee": 0.00002, "actions": [ { "action": "buy", ... }, { "action": "sell", ... } ] } ``` *** #### Multiple Wallets[​](#multiple-wallets "Direct link to Multiple Wallets") You can use **different wallets** for different actions. Just set `privateKey` or `apiKey` inside each action. You can also change the **transaction signer** (the wallet that pays the fee) by setting `privateKey` or `apiKey` at the top level: ```json { "privateKey": "base58_fee_payer_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "actions": [ { "privateKey": "wallet_a_key", "action": "buy", ... }, // or use "apiKey": "your_api_key" instead of privateKey { "privateKey": "wallet_b_key", "action": "sell", ... } // or use "apiKey": "your_api_key" instead of privateKey ] } ``` *** #### Solana Transaction Limits[​](#solana-transaction-limits "Direct link to Solana Transaction Limits") warning Solana has a **1232-byte limit** per transaction. Transaction size grows when actions involve **different AMMs**, because each AMM requires loading additional accounts. | Scenario | How many swaps fit | | ---------------------------- | ------------------ | | Same AMM (e.g. all Pump.fun) | ~4–5 swaps | | Mixed AMMs | ~2 | There's also a **CPI limit of 64**. A typical swap uses ~10 CPIs, so you'll hit this limit around 4–5 swaps even on a single AMM like Pump.fun. *** #### Actions vs. Jito Bundles[​](#actions-vs-jito-bundles "Direct link to Actions vs. Jito Bundles") | | Actions | Jito Bundles | | ------------ | --------------------------------------------------- | ------------------------------------------------ | | What it does | Combines multiple operations into **1 transaction** | Combines multiple transactions into **1 bundle** | | Use case | Multi-step logic in one atomic tx | Atomic ordering of separate txs | *** #### Local Transactions[​](#local-transactions "Direct link to Local Transactions") Actions also support **local (unsigned) transactions** — just use `publicKey` instead of `privateKey` or `apiKey`, and sign + send the transaction yourself. See the [Trade API](/trade-api.md) page for the local logic. *** #### Code Examples[​](#code-examples "Direct link to Code Examples") * Python * JavaScript * Rust * Go ```python import requests url = "https://api.pumpapi.io" data = { "actions": [ { "privateKey": "base58_private_key", # or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "buy", "mint": "token_address", "amount": 0.1, "denominatedInQuote": True, "slippage": 99, "priorityFee": 0.00002, }, { "privateKey": "base58_private_key", # or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "sell", "mint": "token_address", "amount": "100%", "denominatedInQuote": True, "slippage": 99, "priorityFee": 0.00002, } ] } response = requests.post(url, json=data) print(response.json()) ``` ```javascript import axios from 'axios'; const data = { actions: [ { privateKey: "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) action: "buy", mint: "token_address", amount: 0.1, denominatedInQuote: true, slippage: 99, priorityFee: 0.00002, }, { privateKey: "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) action: "sell", mint: "token_address", amount: "100%", denominatedInQuote: true, slippage: 99, priorityFee: 0.00002, } ] }; axios.post("https://api.pumpapi.io", data) .then(response => console.log(response.data)) .catch(error => console.error(error)); ``` ```rust use reqwest::Client; use serde_json::json; #[tokio::main] async fn main() -> Result<(), Box> { let client = Client::new(); let res = client .post("https://api.pumpapi.io") .json(&json!({ "actions": [ { "privateKey": "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "buy", "mint": "token_address", "amount": 0.1, "denominatedInQuote": true, "slippage": 99, "priorityFee": 0.00002 }, { "privateKey": "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "sell", "mint": "token_address", "amount": "100%", "denominatedInQuote": true, "slippage": 99, "priorityFee": 0.00002 } ] })) .send() .await? .text() .await?; println!("{}", res); Ok(()) } ``` ```go package main import ( "bytes" "encoding/json" "fmt" "net/http" ) func main() { data := map[string]interface{}{ "actions": []map[string]interface{}{ { "privateKey": "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "buy", "mint": "token_address", "amount": 0.1, "denominatedInQuote": true, "slippage": 99, "priorityFee": 0.00002, }, { "privateKey": "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "sell", "mint": "token_address", "amount": "100%", "denominatedInQuote": true, "slippage": 99, "priorityFee": 0.00002, }, }, } jsonData, _ := json.Marshal(data) resp, err := http.Post("https://api.pumpapi.io", "application/json", bytes.NewBuffer(jsonData)) if err != nil { panic(err) } defer resp.Body.Close() var result map[string]interface{} json.NewDecoder(resp.Body).Decode(&result) fmt.Println(result) } ``` *** Need help? Join our [Telegram group](https://t.me/pumpapi_devs). --- ## Burn ### 🔥 Burn Tokens – API Use this endpoint to **permanently remove tokens from circulation**.
Burning is **irreversible** — double‑check your parameters before sending the call. #### Endpoint[​](#endpoint "Direct link to Endpoint") `POST https://api.pumpapi.io` #### Request Body[​](#request-body "Direct link to Request Body") | Field | Description | | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `privateKey` | Wallet that owns the tokens. **Not required if you pass `apiKey` instead.** | | `apiKey` | **Optional. Not required.** Pass it instead of `privateKey` if you prefer not to send your private key. Generate one on the **[Trade API](/trade-api.md)** page (🔑 spoiler). | | `action` | Must be **"burn"** | | `mint` | Mint address of the token | | `mintRef` | Temporary token reference for [token creations](/create-token-pump-fun.md) | | `amount` | Amount to burn. `'100%'` burns all available balance of the token | | `priorityFee` | Optional extra fee in SOL to speed up the transaction | The response returns the burn transaction signature once confirmed. #### 📦 Code Examples[​](#-code-examples "Direct link to 📦 Code Examples") * Python * JavaScript * Rust * Go ```python import requests url = "http://api.pumpapi.io" data = { "privateKey": "base58_private_key", # or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "burn", "mint": "mint_address", "amount": "100%", # burn all tokens "priorityFee": 0.000001 } response = requests.post(url, json=data) print(response.json()) # {'signature': '...'} ``` ```javascript import axios from 'axios'; const data = { privateKey: "private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) action: "burn", mint: "mint_address", amount: "100%", // burn all tokens priorityFee: 0.000001 }; axios.post('http://api.pumpapi.io', data) .then(res => console.log(res.data)) // { signature: '...' } .catch(err => console.error(err)); ``` ```rust use reqwest::Client; use serde_json::json; #[tokio::main] async fn main() -> Result<(), Box> { let client = Client::new(); let res = client .post("http://api.pumpapi.io") .json(&json!({ "privateKey": "private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "burn", "mint": "mint_address", "amount": "100%", "priorityFee": 0.000001, })) .send() .await? .text() .await?; println!("{}", res); // {"signature":"..."} Ok(()) } ``` ```go package main import ( "bytes" "encoding/json" "fmt" "net/http" ) func main() { data := map[string]interface{}{ "privateKey": "private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "burn", "mint": "mint_address", "amount": "100%", // burn all tokens "priorityFee": 0.000001, } jsonData, _ := json.Marshal(data) resp, err := http.Post("http://api.pumpapi.io", "application/json", bytes.NewBuffer(jsonData)) if err != nil { panic(err) } defer resp.Body.Close() var result map[string]interface{} json.NewDecoder(resp.Body).Decode(&result) fmt.Println(result) // map[signature:...] } ``` --- ## Claim Cashback ### Claim Cashback – pump.fun API Use this endpoint to **claim accumulated cashback from trades and creator fees** from **pump.fun** and **PumpSwap**. We claim cashback from trading in pools where `cashbackEnabled = True`, as well as **creator fees** from trades on tokens you created with `cashbackToTradersEnabled = False` (the default, no need to pass it when creating a token). ✅ If you are planning to discard your account and switch to a new one — do not forget to call this function first.
It will return several rent fees (~0.004 SOL) to your wallet, even if you have not traded in pools with cashback enabled or created any tokens. You can verify the refund on Solscan in the "Balance Changes" tab to confirm that the return was successfully processed. ✅ You **do not** need to provide a specific pool name — we do everything for you. > **Local transactions are supported**
For a local-transaction example, visit the **Trade API page** and reuse the same local-transaction code snippets — the flow works the same way here. #### Endpoint[​](#endpoint "Direct link to Endpoint") `POST https://api.pumpapi.io` #### Request Body[​](#request-body "Direct link to Request Body") | Field | Description | | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `privateKey` | Base58 private key of the wallet that will sign the claim transaction. **Not required if you pass `apiKey` instead.** | | `apiKey` | **Optional. Not required.** Pass it instead of `privateKey` if you prefer not to send the private key. Generate one on the **[Trade API](/trade-api.md)** page (🔑 spoiler). | | `action` | Must be **"claimCashback"** | | `priorityFee` | Priority fee in SOL. | #### 📦 Code Examples[​](#-code-examples "Direct link to 📦 Code Examples") * Python * JavaScript * Rust * Go ```python import requests url = "https://api.pumpapi.io" data = { "privateKey": "private_key", # or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "claimCashback", "priorityFee": "0.0000012", } response = requests.post(url, json=data) print(response.json()) ``` ```javascript import axios from "axios"; const url = "https://api.pumpapi.io"; const data = { privateKey: "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) action: "claimCashback", priorityFee: "0.0000012", }; axios .post(url, data) .then((res) => console.log(res.data)) .catch((err) => console.error(err)); ``` ```rust use reqwest::Client; use serde_json::json; #[tokio::main] async fn main() -> Result<(), Box> { let client = Client::new(); let res = client .post("https://api.pumpapi.io") .json(&json!({ "privateKey": "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "claimCashback", "priorityFee": "0.0000012" })) .send() .await? .text() .await?; println!("{}", res); Ok(()) } ``` ```go package main import ( "bytes" "encoding/json" "fmt" "net/http" ) func main() { url := "https://api.pumpapi.io" data := map[string]any{ "privateKey": "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "claimCashback", "priorityFee": "0.0000012", } jsonData, _ := json.Marshal(data) resp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonData)) if err != nil { panic(err) } defer resp.Body.Close() var result any _ = json.NewDecoder(resp.Body).Decode(&result) fmt.Printf("%v\n", result) } ``` *** Need help? Join our [Telegram group](https://t.me/pumpapi_devs). --- ## Create Token Pump Fun ### Create Token **Create tokens on Pump.fun** directly through our API — in a single request. This is an extension of the [Trade API](/trade-api.md): everything that works there works here too. #### Endpoint[​](#endpoint "Direct link to Endpoint") `POST https://api.pumpapi.io` #### Parameters[​](#parameters "Direct link to Parameters") | Parameter | Required | Description | | -------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `name` | Yes | Token name | | `symbol` | Yes | Token ticker symbol | | `imageURL` | No | Token image URL. Without it, Pump.fun won't display your token — only bots will be able to trade it. You can host images on [prnt.sc](https://prnt.sc), [imgur.com](https://imgur.com), or [imgbb.com](https://imgbb.com), or simply copy an image URL from Google Images. | | `description` | No | Token description | | `website` | No | Project website URL | | `telegram` | No | Telegram channel/group link | | `x` | No | X (Twitter) profile link | | `uri` | No | Custom metadata URI. If provided, `imageURL`, `description`, `website`, `telegram`, and `x` are ignored | | `mayhemMode` | No | Default: `false` | | `creatorFeeAddress` | No | Address that receives creator fees. Defaults to your own address - provide it only if you want the fees to be sent elsewhere. | | `cashbackToTradersEnabled` | No | Default: `false`. If `true`, trading fees are earned by traders, not you | | `mintRef` | No | When using Jito Bundles or Actions, you don’t yet know the token address assigned to you (unless you provide mintPrivateKey). To handle this, within a single request you can set "mintRef": "any value" (the default is "0") and reuse it across related transactions inside the same Jito Bundle or Actions. When buying the token, specify "mintRef": "the\_value\_you\_set\_earlier", and the backend will understand which token you’re referring to. Works within a single request; a second request requires providing the mint address. | | `quoteMint` | No | Quote token mint address. Defaults to WSOL (`So11111111111111111111111111111111111111112`). To use USDC, specify `EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v`. | | `mintPrivateKey` | No | Custom mint address key. By default we generate tokens with the `pump` ending — you don't need to set this | | `amount` | No | Amount of SOL to buy as dev on launch | *** #### Basic Example[​](#basic-example "Direct link to Basic Example") * Python * JavaScript * Rust * Go ```python import requests url = "https://api.pumpapi.io" data = { "privateKey": "base58_private_key", # or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "create", "name": "PumpApi", "symbol": "PAPI", "description": "Fast API for Pump.fun, Raydium, Meteora", "imageURL": "https://pumpapi.io/img/pumpapi_logo.webp", "website": "https://pumpapi.io", "telegram": "https://t.me/YOUR_TG", "x": "https://x.com/realpumpapi", "amount": "0.0001", "denominatedInQuote": "true", "priorityFee": "0.00002001", } response = requests.post(url, json=data) print(response.json()) ``` ```javascript import axios from 'axios'; const data = { privateKey: "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) action: "create", name: "PumpApi", symbol: "PAPI", description: "Fast API for Pump.fun, Raydium, Meteora", imageURL: "https://pumpapi.io/img/pumpapi_logo.webp", website: "https://pumpapi.io", telegram: "https://t.me/YOUR_TG", x: "https://x.com/realpumpapi", amount: "0.0001", denominatedInQuote: "true", priorityFee: "0.00002001", }; axios.post("https://api.pumpapi.io", data) .then(response => console.log(response.data)) .catch(error => console.error(error)); ``` ```rust use reqwest::Client; use serde_json::json; #[tokio::main] async fn main() -> Result<(), Box> { let client = Client::new(); let res = client .post("https://api.pumpapi.io") .json(&json!({ "privateKey": "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "create", "name": "PumpApi", "symbol": "PAPI", "description": "Fast API for Pump.fun, Raydium, Meteora", "imageURL": "https://pumpapi.io/img/pumpapi_logo.webp", "website": "https://pumpapi.io", "telegram": "https://t.me/YOUR_TG", "x": "https://x.com/realpumpapi", "amount": "0.0001", "denominatedInQuote": "true", "priorityFee": "0.00002001" })) .send() .await? .text() .await?; println!("{}", res); Ok(()) } ``` ```go package main import ( "bytes" "encoding/json" "fmt" "net/http" ) func main() { data := map[string]interface{}{ "privateKey": "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "create", "name": "PumpApi", "symbol": "PAPI", "description": "Fast API for Pump.fun, Raydium, Meteora", "imageURL": "https://pumpapi.io/img/pumpapi_logo.webp", "website": "https://pumpapi.io", "telegram": "https://t.me/YOUR_TG", "x": "https://x.com/realpumpapi", "amount": "0.0001", "denominatedInQuote": "true", "priorityFee": "0.00002001", } jsonData, _ := json.Marshal(data) resp, err := http.Post("https://api.pumpapi.io", "application/json", bytes.NewBuffer(jsonData)) if err != nil { panic(err) } defer resp.Body.Close() var result map[string]interface{} json.NewDecoder(resp.Body).Decode(&result) fmt.Println(result) } ``` *** #### Multi-Wallet Launch[​](#multi-wallet-launch "Direct link to Multi-Wallet Launch") You can launch your token and buy from multiple wallets in a **single request**, using either [Jito Bundles](/jito-bundles.md) or [Actions](/actions.md). Both are supported — pick whichever fits your strategy: * **Jito Bundles** — each buy is a **separate transaction** inside an atomic bundle. To outside observers the buys look unrelated, but no one can sandwich between them. Supports up to **5 transactions** per bundle. * **Actions** — all buys are packed into **one transaction**. Slightly cheaper, but on-chain everyone can see all the buys are connected. Limited to ~4–5 swaps per tx on Pump.fun due to Solana's tx size limit. In both cases, use `"mintRef": "0"` on the `create` action to set a temporary token reference, then reuse the same `mintRef` on every `buy` so the backend knows which mint you're referring to. * Jito Bundles (recommended) * Actions ```json { "jitoTip": 0.00001, "transactions": [ { "privateKey": "dev_wallet_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "create", "name": "PumpApi", "symbol": "PAPI", "imageURL": "https://pumpapi.io/img/pumpapi_logo.webp", "mintRef": "0", "initialTradeAction": "buy", "amount": 0.5, # dev buy "denominatedInQuote": true, "slippage": 99 }, { "privateKey": "wallet_b_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "buy", "mintRef": "0", "amount": 0.3, "denominatedInQuote": true, "slippage": 99 }, { "privateKey": "wallet_c_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "buy", "mintRef": "0", "amount": 0.3, "denominatedInQuote": true, "slippage": 99 }, { "privateKey": "wallet_d_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "buy", "mintRef": "0", "amount": 0.3, "denominatedInQuote": true, "slippage": 99 }, { "privateKey": "wallet_e_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "buy", "mintRef": "0", "amount": 0.3, "denominatedInQuote": true, "slippage": 99 } ] } ``` See the [Jito Bundles](/jito-bundles.md) page for full details. ```json { "privateKey": "base58_fee_payer_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "actions": [ { "privateKey": "dev_wallet_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "create", "name": "PumpApi", "symbol": "PAPI", "imageURL": "https://pumpapi.io/img/pumpapi_logo.webp", "mintRef": "0", "amount": 0.1, "denominatedInQuote": true, "priorityFee": 0.00002 }, { "privateKey": "wallet_b_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "buy", "mintRef": "0", "amount": 0.9, "denominatedInQuote": true, "slippage": 99, "priorityFee": 0.00002 }, { "privateKey": "wallet_c_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "buy", "mintRef": "0", "amount": 0.9, "denominatedInQuote": true, "slippage": 99, "priorityFee": 0.00002 } ] } ``` You can also change the `txSigner` (the wallet that pays the fee) by setting `privateKey` at the top level — useful to avoid copy-traders. See the [Actions](/actions.md) page for full details. *** #### Local Transactions[​](#local-transactions "Direct link to Local Transactions") Local (unsigned) transactions are supported too — just send `publicKey` instead of `privateKey` or `apiKey` to receive an unsigned transaction, sign it on your side, and broadcast it yourself. See the [Trade API](/trade-api.md) page for local transaction code examples. *** #### Cashback[​](#cashback "Direct link to Cashback") If you launched with `cashbackToTradersEnabled: false` (the default one, no need to pass it), creator trading fees can be withdrawn using the [claimCashback](/claim-cashback.md) method. *** #### Custom Metadata URI[​](#custom-metadata-uri "Direct link to Custom Metadata URI") For experts This step is **entirely optional**. By default, we host your token metadata on our server so you can create a token with a single request. If you want to use the standard Pump.fun method, you can upload your icon and metadata to IPFS yourself, then pass the resulting URI as `"uri"` when creating the token. When `uri` is set, the `imageURL`, `description`, `telegram`, and `x` fields are ignored. Show IPFS upload example * Python * JavaScript * Rust * Go ```python import requests # Define token metadata uri_data = { "name": "PumpApi", "symbol": "PAPI", "description": "Fast API for Pump.fun, Raydium, Meteora", "twitter": "https://x.com/realpumpapi", "telegram": "https://t.me/YOUR_TG", "website": "https://pumpapi.io", "showName": "true" } # Load your image # Windows: # with open("C:\\Users\\Admin\\Pictures\\coin_logo.webp", "rb") as f: # file_content = f.read() # Linux / macOS: with open("/path/to/coin_logo.webp", "rb") as f: file_content = f.read() coin_logo = {"file": ("coin_logo.webp", file_content, "image/webp")} # Upload to IPFS via Pump.fun response = requests.post("https://pump.fun/api/ipfs", data=uri_data, files=coin_logo) uri = response.json()["metadataUri"] # Use the URI when creating your token data = { "privateKey": "base58_private_key", # or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "create", "name": "PumpApi", "symbol": "PAPI", "uri": uri, "amount": "0.0001", "priorityFee": "0.00002001", } response = requests.post("https://api.pumpapi.io", json=data) print(response.json()) ``` ```javascript import axios from 'axios'; import fs from 'fs'; import FormData from 'form-data'; const uriData = { name: "PumpApi", symbol: "PAPI", description: "Fast API for Pump.fun, Raydium, Meteora", twitter: "https://x.com/realpumpapi", telegram: "https://t.me/YOUR_TG", website: "https://pumpapi.io", showName: "true", }; const form = new FormData(); Object.entries(uriData).forEach(([k, v]) => form.append(k, v)); form.append("file", fs.createReadStream("/path/to/coin_logo.webp"), "coin_logo.webp"); const ipfsRes = await axios.post("https://pump.fun/api/ipfs", form, { headers: form.getHeaders(), }); const uri = ipfsRes.data.metadataUri; const data = { privateKey: "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) action: "create", name: "PumpApi", symbol: "PAPI", uri, amount: "0.0001", priorityFee: "0.00002001", }; const response = await axios.post("https://api.pumpapi.io", data); console.log(response.data); ``` ```rust use reqwest::{Client, multipart}; use serde_json::json; use std::fs; #[tokio::main] async fn main() -> Result<(), Box> { let client = Client::new(); let file_bytes = fs::read("/path/to/coin_logo.webp")?; let part = multipart::Part::bytes(file_bytes).file_name("coin_logo.webp"); let form = multipart::Form::new() .text("name", "PumpApi") .text("symbol", "PAPI") .text("description", "Fast API for Pump.fun, Raydium, Meteora") .text("twitter", "https://x.com/realpumpapi") .text("telegram", "https://t.me/YOUR_TG") .text("website", "https://pumpapi.io") .text("showName", "true") .part("file", part); let ipfs_res: serde_json::Value = client .post("https://pump.fun/api/ipfs") .multipart(form) .send() .await? .json() .await?; let uri = ipfs_res["metadataUri"].as_str().unwrap(); let res = client .post("https://api.pumpapi.io") .json(&json!({ "privateKey": "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "create", "name": "PumpApi", "symbol": "PAPI", "uri": uri, "amount": "0.0001", "priorityFee": "0.00002001" })) .send() .await? .text() .await?; println!("{}", res); Ok(()) } ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io" "mime/multipart" "net/http" "os" ) func main() { // Upload to IPFS var b bytes.Buffer w := multipart.NewWriter(&b) for k, v := range map[string]string{ "name": "PumpApi", "symbol": "PAPI", "description": "Fast API for Pump.fun, Raydium, Meteora", "twitter": "https://x.com/realpumpapi", "telegram": "https://t.me/YOUR_TG", "website": "https://pumpapi.io", "showName": "true", } { w.WriteField(k, v) } f, _ := os.Open("/path/to/coin_logo.webp") defer f.Close() fw, _ := w.CreateFormFile("file", "coin_logo.webp") io.Copy(fw, f) w.Close() ipfsResp, _ := http.Post("https://pump.fun/api/ipfs", w.FormDataContentType(), &b) var ipfsResult map[string]interface{} json.NewDecoder(ipfsResp.Body).Decode(&ipfsResult) uri := ipfsResult["metadataUri"].(string) // Create token data := map[string]interface{}{ "privateKey": "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "create", "name": "PumpApi", "symbol": "PAPI", "uri": uri, "amount": "0.0001", "priorityFee": "0.00002001", } jsonData, _ := json.Marshal(data) resp, err := http.Post("https://api.pumpapi.io", "application/json", bytes.NewBuffer(jsonData)) if err != nil { panic(err) } defer resp.Body.Close() var result map[string]interface{} json.NewDecoder(resp.Body).Decode(&result) fmt.Println(result) } ``` *** #### Response Format[​](#response-format "Direct link to Response Format") | Request type | Response | | ------------------------------------------------- | ------------------------------------------------------------------------------- | | **Single transaction** | `{"signature": "...", "createdMints": ["mint_address_1"], "err": ""}` | | **[Jito Bundle](/jito-bundles.md)** (up to 5 txs) | `{"signatures": ["...", "..."], "createdMints": ["mint_address_1"], "err": ""}` | * `createdMints` — array of mint addresses for every token created in the request. If you create multiple tokens in one Jito Bundle, you'll get multiple entries here. * `err` is an **empty string `""` on success**, or the error message on failure. *** Need help? Join our [Telegram group](https://t.me/pumpapi_devs). --- ## FAQ ### ❓ Frequently Asked Questions Here’s some helpful information to get you started. **What is PumpApi?** PumpApi is a fast **[Pump.fun API](/index.md)** for building trading bots, token launchers, market monitors, analytics tools, and backtesting systems. It also supports [trading](/trade-api.md) and [real-time data](/stream.md) across PumpSwap, Raydium, and Meteora through the same API. **How is PumpApi better than other Pump.fun APIs?** PumpApi is designed to make Solana trading **faster, simpler, and more affordable**: * **Faster transactions and data delivery:** PumpApi is optimized for both low-latency transaction submission and real-time [Data Stream](/stream.md) delivery. * **Only 0.25% trading fees:** PumpApi charges **0.25% of trade volume**, while competing APIs may charge up to **1%**. * **100% landing rate:** PumpApi Lightning transactions provide a **100% landing rate**, compared with rates of around **80%** on some competing APIs. * **More than Pump.fun:** One API supports Pump.fun, PumpSwap, Raydium, and Meteora, plus real-time streaming of native Solana and token transfers. * **FREE Historical Replay:** Use our completely free [Historical Replay](/historical-replay.md) to backtest strategies and replay previous market conditions. * **FREE real-time data:** The [Data Stream](/stream.md) is completely free. * **No sign-up required:** PumpApi works without an account or API key. * **Cleaner bot code:** Lightning mode handles transaction building, signing, and sending, keeping your integration as short and simple as possible. * **Solana and token transfer streaming:** The [Data Stream](/stream.md) includes real-time native SOL and token transfers. **We want PumpApi to be the Apple of the Solana world.** Every detail is designed to be as simple, polished, and convenient as possible for our users. With PumpApi, your code stays clean and minimal while your bot competes at maximum speed. **I am not a programmer. How can I create a Pump.fun trading bot?** We offer two options: 1. **The easiest option: [PumpApi Agent](https://pumpapi.ai/).** You pay for your AI agent's server and AI usage, then simply describe the bot you want. PumpApi Agent has preinstalled PumpApi skills that help it build the bot, run it on the remote server, and assist you with future changes. It is a modified version of Hermes Agent designed to make PumpApi automation accessible to non-programmers. 2. **Run a coding agent yourself.** Install Claude Code, Codex, or Hermes Agent on your computer or server. Give it the [complete PumpApi documentation](https://pumpapi.io/llms-full.txt), then describe the bot you want it to build. For the simplest AI-generated implementation, ask it to use [Lightning mode](/trade-api.md): the transaction workflow and resulting code are shorter, so the coding agent has less complexity to handle. **Is PumpApi fast?** **Yes. PumpApi is built for low-latency Solana trading and real-time data delivery.** Our servers are located in **Frankfurt am Main, Germany**, close to major Solana validator and RPC infrastructure. We also use multiple optimizations to build, deliver, and send your transactions as quickly as possible. For the lowest possible latency, we recommend hosting your trading bot or server in or near Frankfurt. **Do I need an API key or an account to use PumpApi?** **No. You do not need an API key, account, or sign-up to use PumpApi.** You can connect to the [Data Stream](/stream.md) and start using the [Trade API](/trade-api.md) without creating an account. **Can I build a pump.fun trading bot with PumpApi?** **Yes.** PumpApi provides the [real-time events](/stream.md) and [transaction API](/trade-api.md) needed to build automated pump.fun trading bots, sniper bots, copy-trading tools, token launchers, wallet monitors, and analytics dashboards. PumpApi also supports PumpSwap, Raydium, and Meteora, so the same bot can work across multiple Solana platforms through one API. **Should I build my own Pump.fun trading and Data Stream parser?** **No.** A complete custom implementation can take months of work and will still be slower than using PumpApi. PumpApi handles a large amount of internal complexity for you. We understand the common requirements of Pump.fun bot developers and already handle problems such as incorrect event parsing, high latency, transactions that fail to land, program-specific errors, and changes to the underlying Solana programs. We monitor program updates so you do not have to continually update your own parser and transaction implementation. Most of the infrastructure your bot needs is already available through PumpApi. Copy the [complete PumpApi documentation](https://pumpapi.io/llms-full.txt) into your coding AI and describe what you want it to build. For the shortest and simplest implementation, ask it to use [Lightning mode](/trade-api.md). It’s much easier to ask us to add a feature you need than to try to build it yourself. **How much does PumpApi cost?** The **[Data Stream](/stream.md) and [Historical Replay](/historical-replay.md) are FREE**. Buy and sell transactions through the [Trade API](/trade-api.md) cost **0.25% of trade volume**. See the [Fees page](/fees.md) for the current fees for all other operations. **What is the difference between Lightning and Local transactions?** With **[Lightning transactions](/trade-api.md)**, PumpApi builds, signs, and sends the transaction directly to Solana for you. Lightning mode requires you to provide the private key or apiKey of the dedicated trading wallet used by your bot. In return, PumpApi can handle the complete transaction flow, achieve maximum speed and a **100% landing rate**, and keep your bot code clean and as short as possible. We recommend Lightning mode because it is the fastest and simplest option to integrate. With **[Local transactions](/trade-api.md)**, PumpApi builds the transaction and returns it to your application. Local mode is slower because your application must sign and send the transaction itself, but you do not need to send your private key to PumpApi. Your private key stays in your own application, giving you full control over signing and RPC delivery. Usually this method is used by Web app builders - your users sign transactions themselves via wallet extensions (Phantom, Solflare, Backpack…). Request an unsigned transaction from us with the user's publicKey, pass it to the wallet extension for signing, then broadcast it. **Local transaction flow:** `Your bot → PumpApi → Your bot receives an unsigned transaction → Solana (your bot signs and sends it through your RPC)` **Lightning transaction flow:** `Your bot → PumpApi → Solana` **Do I need to send my private key to PumpApi?** **Not when using [Local transactions](/trade-api.md).** Your application sends only the public key to PumpApi, receives the prepared transaction, and signs it locally. Your private key remains in your own application. **Lightning mode requires the private key or apiKey of the dedicated trading wallet used by your bot.** This allows PumpApi to build, sign, and send the transaction directly to Solana, which provides maximum speed, a **100% landing rate**, and much shorter and cleaner bot code. We recommend Lightning mode because it is the simplest and fastest workflow. Choose Local mode instead if keeping transaction signing entirely inside your application is a requirement. **How do I generate a new Solana wallet?** We recommend keeping your main wallet separate from the funds used for automated trading. Create a dedicated Solana wallet for your bot and transfer only the amount you intend to trade with. Keep the generated private key secret. Anyone who has it can control the wallet and its funds. * Python * JavaScript * Rust * Go Install the dependency: ```bash pip install solders ``` Generate the wallet: ```python from solders.keypair import Keypair keypair = Keypair() print("Your Solana base58 private key:", keypair) print("Your Solana base58 public key:", keypair.pubkey()) ``` Install the dependencies: ```bash npm install @solana/web3.js bs58 ``` Generate the wallet: ```javascript const { Keypair } = require('@solana/web3.js'); const bs58 = require('bs58').default; const keypair = Keypair.generate(); console.log('Your Solana base58 private key:', bs58.encode(keypair.secretKey)); console.log('Your Solana base58 public key:', keypair.publicKey.toBase58()); ``` Add the dependencies to `Cargo.toml`: ```toml [dependencies] solana-sdk = "2" bs58 = "0.5" ``` Generate the wallet: ```rust use solana_sdk::signature::{Keypair, Signer}; fn main() { let keypair = Keypair::new(); let private_key = bs58::encode(keypair.to_bytes()).into_string(); println!("Your Solana base58 private key: {}", private_key); println!("Your Solana base58 public key: {}", keypair.pubkey()); } ``` Install the dependency: ```bash go get github.com/gagliardetto/solana-go ``` Generate the wallet: ```go package main import ( "fmt" "log" solana "github.com/gagliardetto/solana-go" ) func main() { privateKey, err := solana.NewRandomPrivateKey() if err != nil { log.Fatal(err) } fmt.Println("Your Solana base58 private key:", privateKey.String()) fmt.Println("Your Solana base58 public key:", privateKey.PublicKey().String()) } ``` **What is Historical Replay?** [Historical Replay](/historical-replay.md) is a **FREE archive of past [Data Stream](/stream.md) events**. You can use it to backtest trading strategies, replay previous market conditions, research token launches, and test your bot before using it in live trading. [Read the Historical Replay documentation](/historical-replay.md). **Which pools do you support?** We support the following platforms for both trading and data stream APIs: * pump.fun * pump-amm * Raydium Launchpad (including Bonk) * Raydium CPMM * Meteora Launchpad (including Bags, moonshot) * Meteora DAMM V1 * Meteora DAMM V2 * Meteora DLMM In addition, we also support: * Native Solana (SOL) transfers * Token transfers **How can I have more than 2 connections to the data stream?** We send a very large number of transactions, so to avoid overloading our server, there is a strict limit of 1 connection per IP address. You can use ZeroMQ (highly recommended; it's extremely simple to use). The idea is straightforward: You run a single instance that receives all transactions from our server. Then, from that instance, you share each transaction using the PUB/SUB method. Here's how it works: You send data to a specific port, for example, 8939. Then the SUB (subscribers — your two, three, or more bots) connect to this port and receive all the transactions. This way, you only have one connection for all three bots. ZeroMQ is currently the most efficient solution (latency is practically nonexistent — measured in nanoseconds). But you can also use WebSockets to stream locally (a bit slower — latency in microseconds). This method may be better because you only need to change one URL from "wss://stream.pumpapi.io" to "ws://127.0.0.1:9999": Here's an example of the **data stream sender** (just run it and do not close it): **ZeroMQ method. Super fast. Requires a few changes on the bot side** * Python * JavaScript * Rust * Go ```python import asyncio import websockets import zmq # pip install pyzmq import sys ctx = zmq.Context() if sys.platform == "win32": sock = ctx.socket(zmq.PUB) sock.bind("tcp://127.0.0.1:8939") else: sock = ctx.socket(zmq.PUB) sock.bind("ipc://8939") # On Linux, IPC is slightly faster than TCP async def connect_pumpapi_stream(): while True: try: async with websockets.connect("wss://stream.pumpapi.io") as ws: while True: msg = await ws.recv() sock.send(msg) except Exception as e: print(e) await asyncio.sleep(1) asyncio.run(connect_pumpapi_stream()) ``` ```javascript const WebSocket = require('ws'); const zmq = require('zeromq'); async function createStreamer() { const sock = new zmq.Publisher(); if (process.platform === 'win32') { await sock.bind('tcp://127.0.0.1:8939'); } else { await sock.bind('ipc://8939'); // On Linux, IPC is slightly faster than TCP } async function connectPumpApiStream() { while (true) { try { const ws = new WebSocket('wss://stream.pumpapi.io'); ws.on('message', async (msg) => { await sock.send(msg); }); ws.on('error', (error) => { console.error(error); }); ws.on('close', () => { console.log('Connection closed, reconnecting...'); }); // Wait for connection to close await new Promise((resolve) => { ws.on('close', resolve); }); await new Promise(resolve => setTimeout(resolve, 1000)); } catch (error) { console.error(error); await new Promise(resolve => setTimeout(resolve, 1000)); } } } connectPumpApiStream(); } createStreamer(); ``` ```rust use tokio_tungstenite::{connect_async, tungstenite::Message}; use zmq::{Context, Socket, PUB}; use futures_util::{SinkExt, StreamExt}; use std::time::Duration; #[tokio::main] async fn main() { let context = Context::new(); let sock = context.socket(PUB).unwrap(); if cfg!(target_os = "windows") { sock.bind("tcp://127.0.0.1:8939").unwrap(); } else { sock.bind("ipc://8939").unwrap(); // On Linux, IPC is slightly faster than TCP } connect_pumpapi_stream(sock).await; } async fn connect_pumpapi_stream(sock: Socket) { loop { match connect_async("wss://stream.pumpapi.io").await { Ok((ws_stream, _)) => { let (mut write, mut read) = ws_stream.split(); while let Some(msg) = read.next().await { match msg { Ok(Message::Text(text)) => { if let Err(e) = sock.send(&text, 0) { eprintln!("Error sending message: {}", e); } } Ok(Message::Binary(data)) => { if let Err(e) = sock.send(&data, 0) { eprintln!("Error sending message: {}", e); } } Err(e) => { eprintln!("WebSocket error: {}", e); break; } _ => {} } } } Err(e) => { eprintln!("Connection error: {}", e); tokio::time::sleep(Duration::from_secs(1)).await; } } } } ``` ```go package main import ( "context" "fmt" "log" "runtime" "time" "github.com/gorilla/websocket" "github.com/pebbe/zmq4" ) func main() { ctx, err := zmq4.NewContext() if err != nil { log.Fatal(err) } defer ctx.Term() sock, err := ctx.NewSocket(zmq4.PUB) if err != nil { log.Fatal(err) } defer sock.Close() if runtime.GOOS == "windows" { err = sock.Bind("tcp://127.0.0.1:8939") } else { err = sock.Bind("ipc://8939") // On Linux, IPC is slightly faster than TCP } if err != nil { log.Fatal(err) } connectPumpApiStream(sock) } func connectPumpApiStream(sock *zmq4.Socket) { for { conn, _, err := websocket.DefaultDialer.Dial("wss://stream.pumpapi.io", nil) if err != nil { fmt.Printf("Connection error: %v\n", err) time.Sleep(1 * time.Second) continue } for { _, message, err := conn.ReadMessage() if err != nil { fmt.Printf("Read error: %v\n", err) conn.Close() break } _, err = sock.SendBytes(message, 0) if err != nil { fmt.Printf("Send error: %v\n", err) } } time.Sleep(1 * time.Second) } } ``` ****Here's an example of your bot that receives transactions (the getter):**** * Python * JavaScript * Rust * Go **Synchronous version:** ```python import zmq # there's also asynchonios package zmq.asyncio import sys import orjson # or json ctx = zmq.Context() if sys.platform == "win32": sock = ctx.socket(zmq.SUB) sock.connect("tcp://127.0.0.1:8939") else: sock = ctx.socket(zmq.SUB) sock.connect("ipc://8939") # On Linux, IPC is slightly faster than TCP sock.setsockopt_string(zmq.SUBSCRIBE, "") while True: msg = sock.recv() msg = orjson.loads(msg) print(msg) ``` **Asynchronous version:** ```python import zmq.asyncio import sys import orjson import asyncio ctx = zmq.asyncio.Context() if sys.platform == "win32": sock = ctx.socket(zmq.SUB) sock.connect("tcp://127.0.0.1:8939") else: sock = ctx.socket(zmq.SUB) sock.connect("ipc://8939") # On Linux, IPC is slightly faster than TCP sock.setsockopt_string(zmq.SUBSCRIBE, "") async def runner(): while True: msg = await sock.recv() msg = orjson.loads(msg) print(msg) asyncio.run(runner()) ``` **Synchronous version:** ```javascript const zmq = require('zeromq'); async function createClient() { const sock = new zmq.Subscriber(); if (process.platform === 'win32') { sock.connect('tcp://127.0.0.1:8939'); } else { sock.connect('ipc://8939'); // On Linux, IPC is slightly faster than TCP } sock.subscribe(''); // Subscribe to all messages for await (const [msg] of sock) { const data = JSON.parse(msg.toString()); console.log(data); } } createClient(); ``` **Promise-based version:** ```javascript const zmq = require('zeromq'); async function createAsyncClient() { const sock = new zmq.Subscriber(); if (process.platform === 'win32') { sock.connect('tcp://127.0.0.1:8939'); } else { sock.connect('ipc://8939'); // On Linux, IPC is slightly faster than TCP } sock.subscribe(''); // Subscribe to all messages while (true) { try { const [msg] = await sock.receive(); const data = JSON.parse(msg.toString()); console.log(data); } catch (error) { console.error('Error receiving message:', error); } } } createAsyncClient(); ``` **Synchronous version:** ```rust use zmq::{Context, SUB}; use serde_json::Value; fn main() { let context = Context::new(); let sock = context.socket(SUB).unwrap(); if cfg!(target_os = "windows") { sock.connect("tcp://127.0.0.1:8939").unwrap(); } else { sock.connect("ipc://8939").unwrap(); // On Linux, IPC is slightly faster than TCP } sock.set_subscribe(b"").unwrap(); // Subscribe to all messages loop { let msg = sock.recv_bytes(0).unwrap(); let data: Value = serde_json::from_slice(&msg).unwrap(); println!("{}", data); } } ``` **Asynchronous version:** ```rust use tokio_zmq::{prelude::*, Sub}; use serde_json::Value; use futures::StreamExt; #[tokio::main] async fn main() { let mut sock = Sub::new().unwrap(); if cfg!(target_os = "windows") { sock.connect("tcp://127.0.0.1:8939").unwrap(); } else { sock.connect("ipc://8939").unwrap(); // On Linux, IPC is slightly faster than TCP } sock.set_subscribe("").unwrap(); // Subscribe to all messages let mut stream = sock.stream(); while let Some(msg) = stream.next().await { match msg { Ok(multipart) => { if let Some(data) = multipart.get(0) { match serde_json::from_slice::(data) { Ok(parsed) => println!("{}", parsed), Err(e) => eprintln!("JSON parse error: {}", e), } } } Err(e) => eprintln!("Receive error: {}", e), } } } ``` **Synchronous version:** ```go package main import ( "encoding/json" "fmt" "log" "runtime" "github.com/pebbe/zmq4" ) func main() { ctx, err := zmq4.NewContext() if err != nil { log.Fatal(err) } defer ctx.Term() sock, err := ctx.NewSocket(zmq4.SUB) if err != nil { log.Fatal(err) } defer sock.Close() if runtime.GOOS == "windows" { err = sock.Connect("tcp://127.0.0.1:8939") } else { err = sock.Connect("ipc://8939") // On Linux, IPC is slightly faster than TCP } if err != nil { log.Fatal(err) } err = sock.SetSubscribe("") // Subscribe to all messages if err != nil { log.Fatal(err) } for { msg, err := sock.RecvBytes(0) if err != nil { log.Printf("Receive error: %v", err) continue } var data interface{} if err := json.Unmarshal(msg, &data); err != nil { log.Printf("JSON parse error: %v", err) continue } fmt.Println(data) } } ``` **Goroutine-based version:** ```go package main import ( "encoding/json" "fmt" "log" "runtime" "time" "github.com/pebbe/zmq4" ) func main() { ctx, err := zmq4.NewContext() if err != nil { log.Fatal(err) } defer ctx.Term() sock, err := ctx.NewSocket(zmq4.SUB) if err != nil { log.Fatal(err) } defer sock.Close() if runtime.GOOS == "windows" { err = sock.Connect("tcp://127.0.0.1:8939") } else { err = sock.Connect("ipc://8939") // On Linux, IPC is slightly faster than TCP } if err != nil { log.Fatal(err) } err = sock.SetSubscribe("") // Subscribe to all messages if err != nil { log.Fatal(err) } // Message processing goroutine go func() { for { msg, err := sock.RecvBytes(0) if err != nil { log.Printf("Receive error: %v", err) time.Sleep(100 * time.Millisecond) continue } var data interface{} if err := json.Unmarshal(msg, &data); err != nil { log.Printf("JSON parse error: %v", err) continue } fmt.Println(data) } }() // Keep main goroutine alive select {} } ``` **WebSockets method. Fast. No changes required. You just need to change the link on the bot side to `ws://127.0.0.1:9999`.** * Python * JavaScript * Rust * Go ```python import asyncio import websockets clients = set() async def client_handler(websocket): clients.add(websocket) try: await websocket.wait_closed() finally: clients.remove(websocket) async def relay(): print("Relay started.") while True: try: async with websockets.connect("wss://stream.pumpapi.io") as ws: async for msg in ws: for client in list(clients): asyncio.create_task(client.send(msg)) except Exception as e: print(e) await asyncio.sleep(0.2) print("Reconnecting...") async def main(): server = await websockets.serve(client_handler, "localhost", 9999) await relay() asyncio.run(main()) ``` ```javascript const WebSocket = require('ws'); const clients = new Set(); const server = new WebSocket.Server({ port: 9999, host: 'localhost' }); server.on('connection', (ws) => { clients.add(ws); ws.on('close', () => { clients.delete(ws); }); }); async function relay() { console.log('Relay started.'); while (true) { try { const ws = new WebSocket('wss://stream.pumpapi.io'); ws.on('message', (msg) => { for (const client of clients) { if (client.readyState === WebSocket.OPEN) { client.send(msg); } } }); await new Promise((resolve, reject) => { ws.on('close', resolve); ws.on('error', reject); }); } catch (e) { console.log(e); await new Promise(resolve => setTimeout(resolve, 200)); console.log('Reconnecting...'); } } } relay(); ``` ```rust use tokio_tungstenite::{connect_async, tungstenite::Message, WebSocketStream}; use tokio::net::{TcpListener, TcpStream}; use tokio_tungstenite::accept_async; use std::collections::HashSet; use std::sync::Arc; use tokio::sync::Mutex; use futures_util::{SinkExt, StreamExt}; use std::time::Duration; type Clients = Arc>>>; #[tokio::main] async fn main() { let clients: Clients = Arc::new(Mutex::new(HashSet::new())); let clients_clone = Arc::clone(&clients); tokio::spawn(async move { let listener = TcpListener::bind("127.0.0.1:9999").await.unwrap(); while let Ok((stream, _)) = listener.accept().await { let clients = Arc::clone(&clients_clone); tokio::spawn(async move { if let Ok(ws_stream) = accept_async(stream).await { { let mut clients_lock = clients.lock().await; clients_lock.insert(ws_stream); } } }); } }); relay(clients).await; } async fn relay(clients: Clients) { println!("Relay started."); loop { match connect_async("wss://stream.pumpapi.io").await { Ok((ws_stream, _)) => { let (mut write, mut read) = ws_stream.split(); while let Some(msg) = read.next().await { match msg { Ok(Message::Text(text)) => { let mut clients_lock = clients.lock().await; for client in clients_lock.iter_mut() { let _ = client.send(Message::Text(text.clone())).await; } } Ok(Message::Binary(data)) => { let mut clients_lock = clients.lock().await; for client in clients_lock.iter_mut() { let _ = client.send(Message::Binary(data.clone())).await; } } Err(e) => { println!("{}", e); break; } _ => {} } } } Err(e) => { println!("{}", e); tokio::time::sleep(Duration::from_millis(200)).await; println!("Reconnecting..."); } } } } ``` ```go package main import ( "fmt" "log" "net/http" "sync" "time" "github.com/gorilla/websocket" ) var clients = make(map[*websocket.Conn]bool) var clientsMutex sync.Mutex var upgrader = websocket.Upgrader{ CheckOrigin: func(r *http.Request) bool { return true }, } func handleClient(w http.ResponseWriter, r *http.Request) { conn, err := upgrader.Upgrade(w, r, nil) if err != nil { return } clientsMutex.Lock() clients[conn] = true clientsMutex.Unlock() defer func() { clientsMutex.Lock() delete(clients, conn) clientsMutex.Unlock() conn.Close() }() for { _, _, err := conn.ReadMessage() if err != nil { break } } } func relay() { fmt.Println("Relay started.") for { conn, _, err := websocket.DefaultDialer.Dial("wss://stream.pumpapi.io", nil) if err != nil { fmt.Println(err) time.Sleep(200 * time.Millisecond) fmt.Println("Reconnecting...") continue } for { _, message, err := conn.ReadMessage() if err != nil { fmt.Println(err) conn.Close() break } clientsMutex.Lock() for client := range clients { go func(c *websocket.Conn) { c.WriteMessage(websocket.TextMessage, message) }(client) } clientsMutex.Unlock() } time.Sleep(200 * time.Millisecond) fmt.Println("Reconnecting...") } } func main() { http.HandleFunc("/", handleClient) go func() { log.Fatal(http.ListenAndServe(":9999", nil)) }() relay() } ``` **Why do you send all transactions through the Data Stream? Can my computer handle that?** Some users worry that we're sending too many transactions — but in reality, it’s not as much as it might sound. We send around 300-400 transactions per second, covering **all events across all pools** and **all solana and token transfers**, and each transaction is **very small in size**. Even older processors can easily handle this load. In fact, most modern servers, desktops, and laptops would be capable of processing **over 30,000** of these lightweight events per second without any special optimization. So there's no need to worry — your machine can handle it just fine. We designed it this way to ensure faster delivery and greater flexibility. Instead of requiring you to query us for updates or specific token transfers, you receive everything in real time — instantly, and with much less complexity on your side. **Where is your server located? I want the lowest possible latency!** Our server is located in **Frankfurt am Main**, close to the Solana RPC infrastructure (68% of validators are in Europe, most of them in Frankfurt). This helps ensure the lowest possible latency for trading and data stream. Your server location is very important: if it's in America, you can lose up to 200 ms. If you're running infrastructure or bots, we recommend hosting them as close to Frankfurt as possible for the best performance. Even if you're not in Frankfurt — or your server isn't — don’t worry! Thanks to efficient message delivery and lightweight transactions, performance will still be **very fast** and more than sufficient for most use cases. Have a question? Ask us in our [Telegram group](https://t.me/pumpapi_devs) --- ## Fees ### PumpApi Fees PumpApi keeps pricing simple and transparent. | Operation | Fee | | ------------------ | --------------------------------- | | Data Stream | **FREE** | | Historical Replay | **FREE** | | Trade (buy/sell) | **0.25 %** of trade volume | | Create Token | **10 000 lamports** (0.00001 SOL) | | Claim Cashback | **10 000 lamports** (0.00001 SOL) | | Initiate migration | **10 000 lamports** (0.00001 SOL) | | Wrap SOL | **10 000 lamports** (0.00001 SOL) | | Get Token Info | **10 000 lamports** (0.00001 SOL) | | Get Balances | **10 000 lamports** (0.00001 SOL) | | Burn Tokens | **10 000 lamports** (0.00001 SOL) | | Transfer | **10 000 lamports** (0.00001 SOL) | --- ## Get Balances ### Get Balances – Solana API Use this endpoint to fetch the **SOL balance and all SPL token balances** (both `spl-token` and `spl-token-2022`) for a wallet in a single request. A small fee is charged from the `privateKey`. #### Endpoint[​](#endpoint "Direct link to Endpoint") `POST https://api.pumpapi.io` #### Request Body[​](#request-body "Direct link to Request Body") | Field | Required | Description | | ------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | | `action` | Yes | Must be **`"getBalances"`** | | `privateKey` | Yes\* | Private key of the wallet that pays the fee. **Not required if you pass `apiKey` instead.** | | `apiKey` | No\* | Pass it instead of `privateKey` if you prefer not to send your private key. Generate one on the **[Trade API](/trade-api.md)** page (🔑 spoiler). | | `publicKey` | No | Wallet address whose balances you want to fetch. Defaults to the address derived from `privateKey`. | #### 📦 Code Examples[​](#-code-examples "Direct link to 📦 Code Examples") * Python * JavaScript * Rust * Go ```python import requests url = "https://api.pumpapi.io" data = { "action": "getBalances", "privateKey": "base58_private_key", # or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) # "publicKey": "optional_other_wallet_address", } response = requests.post(url, json=data) print(response.json()) ``` ```javascript import axios from "axios"; const url = "https://api.pumpapi.io"; const data = { action: "getBalances", privateKey: "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) // publicKey: "optional_other_wallet_address", }; axios .post(url, data) .then((res) => console.log(res.data)) .catch((err) => console.error(err)); ``` ```rust use reqwest::Client; use serde_json::json; #[tokio::main] async fn main() -> Result<(), Box> { let client = Client::new(); let res = client .post("https://api.pumpapi.io") .json(&json!({ "action": "getBalances", "privateKey": "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) // "publicKey": "optional_other_wallet_address" })) .send() .await? .text() .await?; println!("{}", res); Ok(()) } ``` ```go package main import ( "bytes" "encoding/json" "fmt" "net/http" ) func main() { url := "https://api.pumpapi.io" data := map[string]any{ "action": "getBalances", "privateKey": "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) // "publicKey": "optional_other_wallet_address", } jsonData, _ := json.Marshal(data) resp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonData)) if err != nil { panic(err) } defer resp.Body.Close() var result any _ = json.NewDecoder(resp.Body).Decode(&result) fmt.Printf("%v\n", result) } ``` #### Example Response[​](#example-response "Direct link to Example Response") `solBalance` is a plain number in SOL. Each entry under `tokenBalances` is keyed by the token mint address, and `balance`. Tokens sitting in non-ATA accounts are skipped. ```jsonc { "solBalance": 0.4231, "tokenBalances": { "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v": { "balance": 12.5, "tokenProgram": "spl-token" }, "H74CYmXgMkYHYuSRsZt6RJb4NYp2u72Vw8BS5huApump": { "balance": 1000, "tokenProgram": "spl-token-2022" // "frozen": true // appears only if you hit a scam token that froze your account (you can still burn such tokens) } } } ``` *** Need help? Join our [Telegram group](https://t.me/pumpapi_devs). --- ## Get Token Info ### Get Token Info – API Use this endpoint to request the **current on‑chain token info** of any token by its mint address. > **Heads‑up!**
• We charge a fixed fee of 10,000 lamports.
• For real‑time prices you can use our **[WebSocket stream](/stream.md)**. #### Endpoint[​](#endpoint "Direct link to Endpoint") `POST https://api.pumpapi.io` #### Request Body[​](#request-body "Direct link to Request Body") | Field | Description | | ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `privateKey` | Fee wallet. **Not required if you pass `apiKey` instead.** | | `apiKey` | **Optional. Not required.** Pass it instead of `privateKey` if you prefer not to send your private key. Generate one on the **[Trade API](/trade-api.md)** page (🔑 spoiler). | | `action` | Must be **"getTokenInfo"** | | `mint` | Mint address of the token | | `quoteMint` | You need to provide this if the token exists only in pools where the second token is not Solana | | `poolId` | Provide this to get info about a specific pool | The response JSON returns the current price in SOL per token, total supply, pool name, decimals, burned liquidity, and the reserves of Solana (or another quote token) and the token. If a token has multiple pools, we return data from the largest one. #### 📦 Code Examples[​](#-code-examples "Direct link to 📦 Code Examples") * Python * JavaScript * Rust * Go ```python import requests url = "http://api.pumpapi.io" data = { "privateKey": "base58_private_key", # fee taken from this wallet | or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "getTokenInfo", "mint": "token_address", } response = requests.post(url, json=data) print(response.json()) # {"price":2.795899348462258e-8,"pool":"pump","vTokensInBondingCurve":1072999999.999999,"vQuoteInBondingCurve":30.000000009,"supply":1000000000,"timestamp":1753230239232} ``` ```javascript import axios from 'axios'; const data = { privateKey: "base58_private_key", // fee taken from this wallet | or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) action: "getTokenInfo", mint: "token_address" }; axios.post('http://api.pumpapi.io', data) .then(res => console.log(res.data)) // {"price":2.795899348462258e-8,"pool":"pump","vTokensInBondingCurve":1072999999.999999,"vQuoteInBondingCurve":30.000000009,"supply":1000000000,"timestamp":1753230239232} .catch(err => console.error(err)); ``` ```rust use reqwest::Client; use serde_json::json; #[tokio::main] async fn main() -> Result<(), Box> { let client = Client::new(); let res = client .post("http://api.pumpapi.io") .json(&json!({ "privateKey": "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "getTokenInfo", "mint": "token_address" })) .send() .await? .text() .await?; println!("{}", res); // {"price":2.795899348462258e-8,"pool":"pump","vTokensInBondingCurve":1072999999.999999,"vQuoteInBondingCurve":30.000000009,"supply":1000000000,"timestamp":1753230239232} Ok(()) } ``` ```go package main import ( "bytes" "encoding/json" "fmt" "net/http" ) func main() { data := map[string]interface{}{ "privateKey": "base58_private_key", // fee taken from this wallet | or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "getTokenInfo", "mint": "token_address", } jsonData, _ := json.Marshal(data) resp, err := http.Post("http://api.pumpapi.io", "application/json", bytes.NewBuffer(jsonData)) if err != nil { panic(err) } defer resp.Body.Close() var result map[string]interface{} json.NewDecoder(resp.Body).Decode(&result) fmt.Println(result) // map[price:0.0123] } ``` --- ## Historical Replay ### Historical Replay Starting from **April 18, 2026**, we save everything our [Data Stream](/stream.md) emits, **every hour**. Perfect for **backtesting strategies**, replaying market conditions, research, or anything else you can think of. #### How it works[​](#how-it-works "Direct link to How it works") Every hour we flush all incoming events to a compressed archive named after the **UTC hour** it covers: ```text https://replay.pumpapi.io/YEAR/MONTH/DAY/HOUR.jsonl.zst ``` For example, the events between `2026-04-18 00:00:00 UTC` and `2026-04-18 01:00:00 UTC` live at: ```text https://replay.pumpapi.io/2026/04/18/01.jsonl.zst ``` We use **zstandard (zst) compression** so downloads are as fast as possible: * **~400 MB** per hour compressed * **~2 GB** in memory after decompression * **~1 second** to decompress one hour Each line in the decompressed file is a single JSON event — the exact same format you get from the live Data Stream. #### Browsing available archives[​](#browsing-available-archives "Direct link to Browsing available archives") You can browse what's saved directly in your browser: * `https://replay.pumpapi.io/2026/` — list all months in 2026 * `https://replay.pumpapi.io/2026/04/` — list all days in April 2026 * `https://replay.pumpapi.io/2026/04/18/` — list all hourly files for April 18 *** #### Example: Replay the last N hours[​](#example-replay-the-last-n-hours "Direct link to Example: Replay the last N hours") The snippets below take a `HOURS` variable and stream every event from that window. For example, if it's currently `12:45 UTC` and `HOURS = 2`, you'll replay every event between `10:00` and `12:00` UTC. * Python * JavaScript * Rust * Go ```python import asyncio from datetime import datetime, timezone, timedelta import orjson as json # or use the standard json module (orjson is faster) import aiohttp import zstandard as zstd HOURS = 2 # last 2 hours ALLOW_GAPS = False async def fetch(session, hour_dt): url = f"https://replay.pumpapi.io/{hour_dt:%Y/%m/%d/%H}.jsonl.zst" print(f"[fetch] {url}") async with session.get(url) as r: if r.status == 404: if not ALLOW_GAPS: raise RuntimeError(f"missing: {url}") return None r.raise_for_status() return await r.read() async def main(): now = datetime.now(timezone.utc).replace(minute=0, second=0, microsecond=0) hours = [now - timedelta(hours=i) for i in range(HOURS, 0, -1)] dctx = zstd.ZstdDecompressor() async with aiohttp.ClientSession(timeout=aiohttp.ClientTimeout()) as session: for hour_dt in hours: compressed = await fetch(session, hour_dt) if compressed is None: continue print('downloaded') decompressed = dctx.decompress(compressed) print('decompressed') for line in decompressed.splitlines(): event = json.loads(line.decode()) print(event) if __name__ == "__main__": asyncio.run(main()) ``` ```javascript import { ZstdInit } from '@oneidentity/zstd-js'; const HOURS = 2; // last 2 hours const ALLOW_GAPS = false; async function fetchHour(hourDt) { const y = hourDt.getUTCFullYear(); const m = String(hourDt.getUTCMonth() + 1).padStart(2, '0'); const d = String(hourDt.getUTCDate()).padStart(2, '0'); const h = String(hourDt.getUTCHours()).padStart(2, '0'); const url = `https://replay.pumpapi.io/${y}/${m}/${d}/${h}.jsonl.zst`; console.log(`[fetch] ${url}`); const res = await fetch(url); if (res.status === 404) { if (!ALLOW_GAPS) throw new Error(`missing: ${url}`); return null; } if (!res.ok) throw new Error(`HTTP ${res.status}: ${url}`); return new Uint8Array(await res.arrayBuffer()); } async function main() { const { ZstdSimple } = await ZstdInit(); const now = new Date(); now.setUTCMinutes(0, 0, 0); const hours = []; for (let i = HOURS; i > 0; i--) { hours.push(new Date(now.getTime() - i * 3600 * 1000)); } const decoder = new TextDecoder(); for (const hourDt of hours) { const compressed = await fetchHour(hourDt); if (compressed === null) continue; console.log('downloaded'); const decompressed = ZstdSimple.decompress(compressed); console.log('decompressed'); const text = decoder.decode(decompressed); for (const line of text.split('\n')) { if (!line) continue; const event = JSON.parse(line); console.log(event); } } } main().catch(console.error); ``` ```rust use chrono::{Duration, Timelike, Utc}; use reqwest::Client; use std::io::{BufRead, BufReader}; use zstd::stream::read::Decoder; const HOURS: i64 = 2; // last 2 hours const ALLOW_GAPS: bool = false; #[tokio::main] async fn main() -> Result<(), Box> { let client = Client::new(); let now = Utc::now() .with_minute(0).unwrap() .with_second(0).unwrap() .with_nanosecond(0).unwrap(); let hours: Vec<_> = (1..=HOURS) .rev() .map(|i| now - Duration::hours(i)) .collect(); for hour_dt in hours { let url = format!( "https://replay.pumpapi.io/{}.jsonl.zst", hour_dt.format("%Y/%m/%d/%H") ); println!("[fetch] {}", url); let res = client.get(&url).send().await?; if res.status().as_u16() == 404 { if !ALLOW_GAPS { return Err(format!("missing: {}", url).into()); } continue; } let compressed = res.error_for_status()?.bytes().await?; println!("downloaded"); let decoder = Decoder::new(&compressed[..])?; let reader = BufReader::new(decoder); println!("decompressed"); for line in reader.lines() { let line = line?; if line.is_empty() { continue; } let event: serde_json::Value = serde_json::from_str(&line)?; println!("{}", event); } } Ok(()) } ``` ```go package main import ( "bufio" "bytes" "encoding/json" "fmt" "io" "net/http" "time" "github.com/klauspost/compress/zstd" ) const ( HOURS = 2 // last 2 hours ALLOW_GAPS = false ) func fetchHour(hourDt time.Time) ([]byte, error) { url := fmt.Sprintf( "https://replay.pumpapi.io/%s.jsonl.zst", hourDt.Format("2006/01/02/15"), ) fmt.Printf("[fetch] %s\n", url) resp, err := http.Get(url) if err != nil { return nil, err } defer resp.Body.Close() if resp.StatusCode == 404 { if !ALLOW_GAPS { return nil, fmt.Errorf("missing: %s", url) } return nil, nil } if resp.StatusCode >= 400 { return nil, fmt.Errorf("HTTP %d: %s", resp.StatusCode, url) } return io.ReadAll(resp.Body) } func main() { now := time.Now().UTC().Truncate(time.Hour) var hours []time.Time for i := HOURS; i > 0; i-- { hours = append(hours, now.Add(-time.Duration(i)*time.Hour)) } for _, hourDt := range hours { compressed, err := fetchHour(hourDt) if err != nil { panic(err) } if compressed == nil { continue } fmt.Println("downloaded") decoder, err := zstd.NewReader(bytes.NewReader(compressed)) if err != nil { panic(err) } fmt.Println("decompressed") scanner := bufio.NewScanner(decoder) scanner.Buffer(make([]byte, 1024*1024), 64*1024*1024) for scanner.Scan() { var event map[string]interface{} if err := json.Unmarshal(scanner.Bytes(), &event); err != nil { panic(err) } fmt.Println(event) } decoder.Close() } } ``` *** Backtesting When you backtest on replay data, remember that a **huge portion** of transactions on AMMs like pump.fun are sent through [Jito Bundles](/jito-bundles.md). A bundle must be treated as **one big atomic transaction** — you cannot insert your own transaction in the middle of one. Bundles are not explicitly labeled in the event stream, but you can detect them heuristically: * Every event has a **millisecond-precision timestamp**. Transactions inside the same bundle are executed simultaneously, so their timestamps are almost identical — typically within **1–3 ms** of each other. * Bundled transactions usually **interact with the same token**. A solid rule of thumb: treat any group of transactions that hit the **same token within ~3 ms** as a single bundled event. For certainty, you can cross-check any suspicious cluster on . Also, add a **slightly larger-than-usual latency buffer** to your simulation. Real execution will always be a bit slower than replay, and being conservative here prevents your backtest from looking more profitable than reality. `localTimestamp` In the replay archives you'll encounter an extra field that **does not exist** in the live Data Stream: `localTimestamp`. It's the time at which **our replay server** in Frankfurt am Main (Germany) received the transaction — which may be slightly later than what you'd observe on your end in real time. **You generally don't need it** for backtesting purposes, but it can be useful for checking whether your own server had good latency at a given moment. *** Need help? Join our [Telegram group](https://t.me/pumpapi_devs). --- ## Jito Bundles ### Jito Bundles **Jito Bundles** let you send **up to 5 transactions** in a single atomic package — **all or nothing**. Either every transaction lands, or none of them do. Unlike [Actions](/actions.md), the transactions inside a bundle are **independent** from each other on-chain. To an outside observer, they look like completely unrelated transactions — but they are guaranteed to execute together, in order, with **no possibility for anyone to sandwich or front-run between them**. #### Why use Jito Bundles?[​](#why-use-jito-bundles "Direct link to Why use Jito Bundles?") * **Token creators**: launch a token and buy it from multiple wallets in a way that looks like organic, unrelated buys — while staying 100% protected from snipers squeezing in between your transactions. * **Fast account cleanup**: sell everything across multiple transactions at once. * **Massive batch operations**: combine with [Actions](/actions.md) to pack multiple operations into each transaction — e.g. 4 sells per tx × 5 txs = **20 sells in one bundle**. For simple transfers, you can fit **~150 transfers in a single bundle**. #### Endpoint[​](#endpoint "Direct link to Endpoint") `POST https://api.pumpapi.io` *** #### Basic Structure[​](#basic-structure "Direct link to Basic Structure") Just send your usual requests wrapped inside a `transactions` array: ```json { "transactions": [ { /* tx1 */ }, { /* tx2 */ }, { /* tx3 */ }, { /* tx4 */ }, { /* tx5 */ } ] } ``` Each transaction in the array follows the exact same format as a normal [Trade API](/trade-api.md) call. Everything we support works inside bundles — including [Actions](/actions.md) (so you can nest actions inside each transaction) and `guaranteedDelivery` (continuous re-sending of your transaction, perfect for sells). Just place these flags **above** the `transactions` array. *** #### Jito Tip and Jito tip payer[​](#jito-tip-and-jito-tip-payer "Direct link to Jito Tip and Jito tip payer") You can specify `jitoTip` and its payer **above** the `transactions` array to set it globally for the whole bundle: ```json { "jitoTip": 0.00001, "transactions": [ { /* tx1 */ }, { /* tx2 */ } ] } ``` info * If `jitoTip` is not set at the top level, the value from the **last transaction** in the array will be used. * If it's not specified anywhere, we fall back to the **minimum Jito tip of `0.00001 SOL`** (the minimum Jito requires). * If `privateKey` or `apiKey` (for lightning mode) or `publicKey` (for local mode) is not specified above the `transactions` block, the payer of the **last transaction** covers the Jito tip. priority Fee is ignored inside bundles Inside a Jito Bundle, `priorityFee` has **no effect** — bundles are routed through the Jito Block Engine, which doesn't care about Solana priority fees. **Only `jitoTip` determines how fast your bundle lands.** You can safely omit `priorityFee` from every transaction in the bundle. *** #### Example: Create a Token and Buy from 4 Other Wallets[​](#example-create-a-token-and-buy-from-4-other-wallets "Direct link to Example: Create a Token and Buy from 4 Other Wallets") This is the classic use case — launch a token, have the dev wallet buy on creation, and then buy from 4 additional wallets in separate transactions that look unrelated to outside observers. * Python * JavaScript * Rust * Go ```python import requests url = "https://api.pumpapi.io" data = { "jitoTip": 0.00001, "transactions": [ { "privateKey": "dev_wallet_private_key", # or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "create", "name": "PumpApi", "symbol": "PAPI", "description": "Fast API for Pump.fun, Raydium, Meteora", "imageURL": "https://pumpapi.io/img/pumpapi_logo.webp", "website": "https://pumpapi.io", "telegram": "https://t.me/YOUR_TG", "x": "https://x.com/realpumpapi", "mintRef": "0", # set a temporary reference for the new token "initialTradeAction": "buy", # dev buy "amount": 0.5, "denominatedInQuote": True, "slippage": 99, }, { "privateKey": "wallet_2_private_key", # or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "buy", "mintRef": "0", # reuse the mintRef we set during create "amount": 0.3, "denominatedInQuote": True, "slippage": 99, }, { "privateKey": "wallet_3_private_key", # or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "buy", "mintRef": "0", # reuse the mintRef we set during create "amount": 0.3, "denominatedInQuote": True, "slippage": 99, }, { "privateKey": "wallet_4_private_key", # or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "buy", "mintRef": "0", # reuse the mintRef we set during create "amount": 0.3, "denominatedInQuote": True, "slippage": 99, }, { "privateKey": "wallet_5_private_key", # or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "buy", "mintRef": "0", # reuse the mintRef we set during create "amount": 0.3, "denominatedInQuote": True, "slippage": 99, } ] } response = requests.post(url, json=data) print(response.json()) ``` ```javascript import axios from 'axios'; const data = { jitoTip: 0.0001, transactions: [ { privateKey: "dev_wallet_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) action: "create", name: "PumpApi", symbol: "PAPI", description: "Fast API for Pump.fun, Raydium, Meteora", imageURL: "https://pumpapi.io/img/pumpapi_logo.webp", website: "https://pumpapi.io", telegram: "https://t.me/YOUR_TG", x: "https://x.com/realpumpapi", mintRef: "0", // set a temporary reference for the new token initialTradeAction: "buy", // dev buy amount: 0.5, denominatedInQuote: true, slippage: 99, }, { privateKey: "wallet_2_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) action: "buy", mintRef: "0", // reuse the mintRef we set during create amount: 0.3, denominatedInQuote: true, slippage: 99, }, { privateKey: "wallet_3_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) action: "buy", mintRef: "0", // reuse the mintRef we set during create amount: 0.3, denominatedInQuote: true, slippage: 99, }, { privateKey: "wallet_4_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) action: "buy", mintRef: "0", // reuse the mintRef we set during create amount: 0.3, denominatedInQuote: true, slippage: 99, }, { privateKey: "wallet_5_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) action: "buy", mintRef: "0", // reuse the mintRef we set during create amount: 0.3, denominatedInQuote: true, slippage: 99, } ] }; axios.post("https://api.pumpapi.io", data) .then(response => console.log(response.data)) .catch(error => console.error(error)); ``` ```rust use reqwest::Client; use serde_json::json; #[tokio::main] async fn main() -> Result<(), Box> { let client = Client::new(); let res = client .post("https://api.pumpapi.io") .json(&json!({ "jitoTip": 0.00001, "transactions": [ { "privateKey": "dev_wallet_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "create", "name": "PumpApi", "symbol": "PAPI", "description": "Fast API for Pump.fun, Raydium, Meteora", "imageURL": "https://pumpapi.io/img/pumpapi_logo.webp", "website": "https://pumpapi.io", "telegram": "https://t.me/YOUR_TG", "x": "https://x.com/realpumpapi", "mintRef": "0", // set a temporary reference for the new token "initialTradeAction": "buy", // dev buy "amount": 0.5, "denominatedInQuote": true, "slippage": 99, }, { "privateKey": "wallet_2_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "buy", "mintRef": "0", // reuse the mintRef we set during create "amount": 0.3, "denominatedInQuote": true, "slippage": 99, }, { "privateKey": "wallet_3_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "buy", "mintRef": "0", // reuse the mintRef we set during create "amount": 0.3, "denominatedInQuote": true, "slippage": 99, }, { "privateKey": "wallet_4_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "buy", "mintRef": "0", // reuse the mintRef we set during create "amount": 0.3, "denominatedInQuote": true, "slippage": 99, }, { "privateKey": "wallet_5_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "buy", "mintRef": "0", // reuse the mintRef we set during create "amount": 0.3, "denominatedInQuote": true, "slippage": 99, } ] })) .send() .await? .text() .await?; println!("{}", res); Ok(()) } ``` ```go package main import ( "bytes" "encoding/json" "fmt" "net/http" ) func main() { data := map[string]interface{}{ "jitoTip": 0.00001, "transactions": []map[string]interface{}{ { "privateKey": "dev_wallet_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "create", "name": "PumpApi", "symbol": "PAPI", "description": "Fast API for Pump.fun, Raydium, Meteora", "imageURL": "https://pumpapi.io/img/pumpapi_logo.webp", "website": "https://pumpapi.io", "telegram": "https://t.me/YOUR_TG", "x": "https://x.com/realpumpapi", "mintRef": "0", // set a temporary reference for the new token "initialTradeAction": "buy", // dev buy "amount": 0.5, "denominatedInQuote": true, "slippage": 99, }, { "privateKey": "wallet_2_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "buy", "mintRef": "0", // reuse the mintRef we set during create "amount": 0.3, "denominatedInQuote": true, "slippage": 99, }, { "privateKey": "wallet_3_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "buy", "mintRef": "0", // reuse the mintRef we set during create "amount": 0.3, "denominatedInQuote": true, "slippage": 99, }, { "privateKey": "wallet_4_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "buy", "mintRef": "0", // reuse the mintRef we set during create "amount": 0.3, "denominatedInQuote": true, "slippage": 99, }, { "privateKey": "wallet_5_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "buy", "mintRef": "0", // reuse the mintRef we set during create "amount": 0.3, "denominatedInQuote": true, "slippage": 99, }, }, } jsonData, _ := json.Marshal(data) resp, err := http.Post("https://api.pumpapi.io", "application/json", bytes.NewBuffer(jsonData)) if err != nil { panic(err) } defer resp.Body.Close() var result map[string]interface{} json.NewDecoder(resp.Body).Decode(&result) fmt.Println(result) } ``` *** #### Response Format[​](#response-format "Direct link to Response Format") ```json { "signatures": [ "signature1", "signature2", "signature3", "signature4", "signature5" ], "err": "", "timestamp": utc_timestamp_ms, "bundleUUIDs":["bundle_uuid"] // If the transaction does not land, you can check the reason on explorer.jito.wtf by providing the bundle UUID. // "trades": [{"poolId": "pool_id_used", "mint": "mint_address_used", "quoteMint": "quote_mint_address_used", "pool": "name_of_the_amm"}] ← only present if the bundle contained purchase or sale // "createdMints": ["created_mint_address"] ← only present if the bundle contained a "create" action // ...other extra fields may appear depending on which actions you performed inside the bundle } ``` * `signatures` — array of transaction signatures, one per transaction in the bundle (up to 5). * `err` — `""` on success, or the error message if the bundle failed. * `timestamp` — current timestamp in miliseconds. * `bundleUUIDs` — A list containing one bundle UUID. If the transaction does not land, you can check the reason on explorer.jito.wtf by providing the bundle UUID. * `createdMints` — **only included when the bundle creates one or more tokens**. Contains the mint addresses of the newly created tokens. * Other extra fields may appear depending on which actions you performed inside the bundle. *** #### Actions vs. Jito Bundles[​](#actions-vs-jito-bundles "Direct link to Actions vs. Jito Bundles") | | Actions | Jito Bundles | | ------------ | --------------------------------------------------- | ------------------------------------------------ | | What it does | Combines multiple operations into **1 transaction** | Combines multiple transactions into **1 bundle** | | Use case | Multi-step logic in one atomic tx | Atomic ordering of separate txs | See the [Actions](/actions.md) page for details. And remember — the two can be **combined**: nest Actions inside each transaction of a Jito Bundle to pack even more operations into a single atomic package. *** #### Local (Unsigned) Transactions[​](#local-unsigned-transactions "Direct link to Local (Unsigned) Transactions") Local transactions are fully supported for Jito Bundles. Head over to the [Trade API](/trade-api.md) page for a local-transactions example and adapt it to the `transactions` array format shown above. Important Jito Bundles can **only** be submitted to the Jito Block Engine, which enforces strict rate limits for unauthorized users — typically only **~1 out of every 5 transactions** will be accepted for a new wallet. To raise these limits you must apply through the [Jito Discord](https://discord.gg/jito). **This is why we strongly recommend using the lightning version** (the default examples shown above on this page) — it's both faster and dramatically simpler, with no rate-limit headaches. *** Need help? Join our [Telegram group](https://t.me/pumpapi_devs). --- ## Legal ### Terms of Use **Last updated:** December 27, 2025 By accessing or using **PumpApi** (the “Service”) you agree to these Terms of Use (“Terms”).
If you do not agree with any part of the Terms, you must not use the Service. **PumpApi is not affiliated with, endorsed by, or formally connected to pump.fun, Raydium, PumpSwap or any other third‑party protocol.** *** #### 1. Eligibility & Compliance[​](#1-eligibility--compliance "Direct link to 1. Eligibility & Compliance") * You are solely responsible for complying with all laws and regulations that apply to you. * You must not use the Service if doing so is illegal where you live or if you are subject to any sanctions or restrictions. *** #### 2. Fees[​](#2-fees "Direct link to 2. Fees") PumpApi currently charges a **0.25 % trading fee**.
If we change the fee, we will notify users via our **Telegram channel**. The fee that applies to a transaction is the one displayed (or returned) at the time the request is submitted. *** #### 3. Risk Disclosure[​](#3-risk-disclosure "Direct link to 3. Risk Disclosure") * Trading cryptocurrencies and meme coins is highly volatile and involves significant risk. * You understand that blockchain transactions are irreversible and that network conditions, smart‑contract bugs, or other technical issues can cause unexpected losses or delays. * **PumpApi provides only software that forwards your instructions to public blockchain networks; we do not execute trades on your behalf nor hold custody of your assets.** *** #### 4. No Warranty[​](#4-no-warranty "Direct link to 4. No Warranty") The Service is provided **“as is” and “as available”** without warranties of any kind—express, implied, or statutory—including, but not limited to, warranties of merchantability, fitness for a particular purpose, accuracy, or availability. *** #### 5. Limitation of Liability[​](#5-limitation-of-liability "Direct link to 5. Limitation of Liability") To the maximum extent permitted by law, **PumpApi and its team are not liable for any direct, indirect, incidental, special, consequential, or exemplary damages** arising from or in connection with your use of the Service **— even if those losses result from bugs, outages, or errors on our side.**
Your sole remedy for dissatisfaction with the Service is to stop using it. *** #### 6. Changes to the Service or Terms[​](#6-changes-to-the-service-or-terms "Direct link to 6. Changes to the Service or Terms") * We may modify, suspend, or discontinue the Service at any time without liability. * We may update these Terms by posting a revised version. Continued use of the Service after changes become effective constitutes acceptance of the new Terms. *** #### 7. Contact[​](#7-contact "Direct link to 7. Contact") Questions? Email us at ****. *** **PumpApi** — Faster, cheaper, smarter meme‑coin trading. --- ## Migrate Pump Fun ### Migrate Pump.fun Want to **buy or sell first** the moment a token migrates? On Pump.fun you can **initiate the migration yourself** — and act before anyone else. #### How It Works[​](#how-it-works "Direct link to How It Works") Migration can only be initialized during a short window when `tokensInPool == 0`. After a few seconds, the Pump.fun keeper will initialize the migration automatically — but **you can do it first**. No admin access required. Anyone can call it. Just call the `migrate` action and you'll trigger the migration. This action is fail-safe, meaning your transaction will not fail even if someone executes it before you. You can even test it on already migrated tokens. *** #### Buy or Sell on Migration[​](#buy-or-sell-on-migration "Direct link to Buy or Sell on Migration") If you also want to trade at migration time, you have two options: * **[Jito Bundles](/jito-bundles.md) (recommended)** — send `migrate` and the trade as **two separate transactions** inside one atomic bundle. Simpler, faster, and no CPI workarounds needed. * **[Actions](/actions.md)** — pack `migrate` + trade into **one transaction**. Requires a wSOL workaround due to Solana's CPI limit. Pick a tab below. * Jito Bundles (recommended) * Actions (1 transaction) #### Jito Bundles Approach[​](#jito-bundles-approach "Direct link to Jito Bundles Approach") With [Jito Bundles](/jito-bundles.md), `migrate` and the trade live in **separate transactions** inside one atomic bundle. Both land together or neither lands — and because each transaction has its own CPI budget, you don't need any wSOL tricks. The flow is dead simple: * **tx1** — `migrate` (initiates the migration) * **tx2** — `buy` or `sell` (executes immediately after migration) ##### Example Request[​](#example-request "Direct link to Example Request") ```json { "jitoTip": 0.00001, "transactions": [ { "privateKey": "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "migrate", "mint": "token_address", "quoteMint": "quote_token_address", // usually wsol address, but it can also be usdc }, { "privateKey": "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "buy", "mint": "token_address", "quoteMint": "quote_token_address", // usually wsol address, but it can also be usdc "amount": 0.2, "denominatedInQuote": true, "slippage": 200 } ] } ``` That's it. No `wrapSol`, no `disableSolWrapper`, no CPI math. ##### Code Example[​](#code-example "Direct link to Code Example") The example below listens to the stream and fires a Jito Bundle (migrate + buy) the moment `tokensInPool == 0`. * Python * JavaScript * Rust * Go ```python import websockets import orjson as json # or use the standard json module (orjson is faster) import asyncio import aiohttp url = "https://api.pumpapi.io" async def pumpapi_data_stream(): async with websockets.connect("wss://stream.pumpapi.io/") as websocket: async for message in websocket: event = json.loads(message) if event.get("pool") == "pump" and event.get("tokensInPool") == 0: print(event) data = { "jitoTip": 0.00001, "transactions": [ { "privateKey": "base58_private_key", # or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "migrate", "mint": event["mint"], "quoteMint": event["quoteMint"], }, { "privateKey": "base58_private_key", # or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "buy", # or "sell" "mint": event["mint"], "quoteMint": event["quoteMint"], "amount": 0.2, "denominatedInQuote": True, "slippage": 200, }, ], } async with aiohttp.ClientSession() as session: async with session.post(url, json=data) as response: text = await response.text() print(text) asyncio.run(pumpapi_data_stream()) ``` ```javascript import WebSocket from 'ws'; import axios from 'axios'; const url = "https://api.pumpapi.io"; async function pumpApiDataStream() { const ws = new WebSocket("wss://stream.pumpapi.io/"); ws.on("message", async (message) => { const event = JSON.parse(message); if (event.pool === "pump" && event.tokensInPool === 0) { console.log(event); const data = { jitoTip: 0.00001, transactions: [ { privateKey: "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) action: "migrate", mint: event.mint, quoteMint: event.quoteMint, }, { privateKey: "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) action: "buy", // or "sell" mint: event.mint, quoteMint: event.quoteMint, amount: 0.2, denominatedInQuote: true, slippage: 200, }, ], }; const response = await axios.post(url, data); console.log(response.data); } }); ws.on("error", (err) => console.error("WebSocket error:", err)); } pumpApiDataStream(); ``` ```rust use futures_util::StreamExt; use reqwest::Client; use serde_json::{json, Value}; use tokio_tungstenite::connect_async; use tungstenite::Message; #[tokio::main] async fn main() -> Result<(), Box> { let url = "https://api.pumpapi.io"; let client = Client::new(); let (ws_stream, _) = connect_async("wss://stream.pumpapi.io/").await?; let (_, mut read) = ws_stream.split(); while let Some(msg) = read.next().await { let msg = msg?; if let Message::Text(text) = msg { let event: Value = serde_json::from_str(&text)?; if event["pool"] == "pump" && event["tokensInPool"] == 0 { println!("{}", event); let res = client .post(url) .json(&json!({ "jitoTip": 0.00001, "transactions": [ { "privateKey": "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "migrate", "mint": event["mint"], "quoteMint": event["quoteMint"], }, { "privateKey": "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "buy", // or "sell" "mint": event["mint"], "quoteMint": event["quoteMint"], "amount": 0.2, "denominatedInQuote": true, "slippage": 200 } ] })) .send() .await? .text() .await?; println!("{}", res); } } } Ok(()) } ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io" "log" "net/http" "github.com/gorilla/websocket" ) const apiURL = "https://api.pumpapi.io" func postJSON(data map[string]interface{}) { body, _ := json.Marshal(data) resp, err := http.Post(apiURL, "application/json", bytes.NewBuffer(body)) if err != nil { log.Println("HTTP error:", err) return } defer resp.Body.Close() respBody, _ := io.ReadAll(resp.Body) fmt.Println(string(respBody)) } func main() { conn, _, err := websocket.DefaultDialer.Dial("wss://stream.pumpapi.io/", nil) if err != nil { log.Fatal("WebSocket error:", err) } defer conn.Close() for { _, message, err := conn.ReadMessage() if err != nil { log.Println("Read error:", err) break } var event map[string]interface{} if err := json.Unmarshal(message, &event); err != nil { continue } pool, _ := event["pool"].(string) tokensInPool, _ := event["tokensInPool"].(float64) if pool == "pump" && tokensInPool == 0 { fmt.Println(event) postJSON(map[string]interface{}{ "jitoTip": 0.00001, "transactions": []map[string]interface{}{ { "privateKey": "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "migrate", "mint": event["mint"], "quoteMint": event["quoteMint"], }, { "privateKey": "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "buy", // or "sell" "mint": event["mint"], "quoteMint": event["quoteMint"], "amount": 0.2, "denominatedInQuote": true, "slippage": 200, }, }, }) } } } ``` #### Actions Approach[​](#actions-approach "Direct link to Actions Approach") With [Actions](/actions.md), `migrate` and the trade are packed into **one transaction**. This is more compact, but it runs into Solana's CPI limit and requires a wSOL workaround. CPI Limit — Important Solana has a **CPI limit of 64**. Migration with a trade is a complex operation, so you need to optimize your request carefully. **You cannot use regular SOL** for the trade — wrapping SOL inline takes too many CPI calls. You must use **Wrapped SOL (wSOL)** instead. ##### Step 1 — Wrap your SOL (separate transaction)[​](#step-1--wrap-your-sol-separate-transaction "Direct link to Step 1 — Wrap your SOL (separate transaction)") Call `wrapSol` in advance to convert SOL into wSOL: ```python data = { "privateKey": "base58_private_key", # or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "wrapSol", "amount": "0.5", # wrap any amount — it's safe, not a trade "priorityFee": "0.00002001", } ``` You can wrap a large amount — it's not a trade, just an internal Solana instruction. When you later sell 100% of wSOL, the account closes and all funds return to SOL automatically. ##### Step 2 — Set `disableSolWrapper: "true"`[​](#step-2--set-disablesolwrapper-true "Direct link to step-2--set-disablesolwrapper-true") Always pass `"disableSolWrapper": "true"` in your migrate request. Without it, the transaction will fail with an **Unknown program error**. note If you only want to **initiate migration without trading**, you don't need to wrap SOL or set `disableSolWrapper`. Just call `migrate` directly. ##### Example Request[​](#example-request-1 "Direct link to Example Request") ```json { "privateKey": "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "migrate", "initialTradeAction": "buy", "disableSolWrapper": "true", "mint": "token_address", "quoteMint": "quote_token_address", // usually wsol address, but it can also be usdc "amount": "0.01", "denominatedInQuote": "true", "slippage": "200", "priorityFee": "0.00019" } ``` ##### Code Example[​](#code-example-1 "Direct link to Code Example") The example below wraps 0.5 SOL, then listens to the stream and triggers migration + buy the moment `tokensInPool == 0`. * Python * JavaScript * Rust * Go ```python import websockets import orjson as json # or use the standard json module (orjson is faster) import asyncio import aiohttp url = "https://api.pumpapi.io" async def pumpapi_data_stream(): async with websockets.connect("wss://stream.pumpapi.io/") as websocket: # Step 1 — wrap SOL before migration data = { "privateKey": "base58_private_key", # or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "wrapSol", "amount": "0.5", # safe to wrap any amount "priorityFee": "0.00002001", } async with aiohttp.ClientSession() as session: async with session.post(url, json=data) as response: text = await response.json() print(f"Wrapped SOL -> {text}") # Step 2 — wait for migration window and act first async for message in websocket: event = json.loads(message) if event.get("pool") == "pump" and event.get("tokensInPool") == 0: print(event) data = { "privateKey": "base58_private_key", "action": "migrate", "initialTradeAction": "buy", # remove this line to migrate only "disableSolWrapper": True, "mint": event["mint"], "quoteMint": event["quoteMint"], "amount": "0.2", "denominatedInQuote": "true", "slippage": "200", "priorityFee": "0.00002001", } async with aiohttp.ClientSession() as session: async with session.post(url, json=data) as response: text = await response.text() print(text) asyncio.run(pumpapi_data_stream()) ``` ```javascript import WebSocket from 'ws'; import axios from 'axios'; const url = "https://api.pumpapi.io"; async function pumpApiDataStream() { // Step 1 — wrap SOL before migration const wrapData = { privateKey: "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) action: "wrapSol", amount: "0.5", priorityFee: "0.00002001", }; const wrapResponse = await axios.post(url, wrapData); console.log("Wrapped SOL ->", wrapResponse.data); // Step 2 — wait for migration window and act first const ws = new WebSocket("wss://stream.pumpapi.io/"); ws.on("message", async (message) => { const event = JSON.parse(message); if (event.pool === "pump" && event.tokensInPool === 0) { console.log(event); const migrateData = { privateKey: "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) action: "migrate", initialTradeAction: "buy", // remove this line to migrate only disableSolWrapper: true, mint: event.mint, quoteMint: event.quoteMint, amount: "0.2", denominatedInQuote: "true", slippage: "200", priorityFee: "0.00002001", }; const response = await axios.post(url, migrateData); console.log(response.data); } }); ws.on("error", (err) => console.error("WebSocket error:", err)); } pumpApiDataStream(); ``` ```rust use futures_util::StreamExt; use reqwest::Client; use serde_json::{json, Value}; use tokio_tungstenite::connect_async; use tungstenite::Message; #[tokio::main] async fn main() -> Result<(), Box> { let url = "https://api.pumpapi.io"; let client = Client::new(); // Step 1 — wrap SOL before migration let wrap_res = client .post(url) .json(&json!({ "privateKey": "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "wrapSol", "amount": "0.5", "priorityFee": "0.00002001" })) .send() .await? .text() .await?; println!("Wrapped SOL -> {}", wrap_res); // Step 2 — wait for migration window and act first let (ws_stream, _) = connect_async("wss://stream.pumpapi.io/").await?; let (_, mut read) = ws_stream.split(); while let Some(msg) = read.next().await { let msg = msg?; if let Message::Text(text) = msg { let event: Value = serde_json::from_str(&text)?; if event["pool"] == "pump" && event["tokensInPool"] == 0 { println!("{}", event); let res = client .post(url) .json(&json!({ "privateKey": "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "migrate", "initialTradeAction": "buy", // remove this line to migrate only "disableSolWrapper": true, "mint": event["mint"], "quoteMint": event["quoteMint"], "amount": "0.2", "denominatedInQuote": "true", "slippage": "200", "priorityFee": "0.00002001" })) .send() .await? .text() .await?; println!("{}", res); } } } Ok(()) } ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io" "log" "net/http" "github.com/gorilla/websocket" ) const apiURL = "https://api.pumpapi.io" func postJSON(data map[string]interface{}) { body, _ := json.Marshal(data) resp, err := http.Post(apiURL, "application/json", bytes.NewBuffer(body)) if err != nil { log.Println("HTTP error:", err) return } defer resp.Body.Close() respBody, _ := io.ReadAll(resp.Body) fmt.Println(string(respBody)) } func main() { // Step 1 — wrap SOL before migration fmt.Println("Wrapping SOL...") postJSON(map[string]interface{}{ "privateKey": "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "wrapSol", "amount": "0.5", "priorityFee": "0.00002001", }) // Step 2 — wait for migration window and act first conn, _, err := websocket.DefaultDialer.Dial("wss://stream.pumpapi.io/", nil) if err != nil { log.Fatal("WebSocket error:", err) } defer conn.Close() for { _, message, err := conn.ReadMessage() if err != nil { log.Println("Read error:", err) break } var event map[string]interface{} if err := json.Unmarshal(message, &event); err != nil { continue } pool, _ := event["pool"].(string) tokensInPool, _ := event["tokensInPool"].(float64) if pool == "pump" && tokensInPool == 0 { fmt.Println(event) postJSON(map[string]interface{}{ "privateKey": "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "migrate", "initialTradeAction": "buy", // remove this line to migrate only "disableSolWrapper": true, "mint": event["mint"], "quoteMint": event["quoteMint"], "amount": "0.2", "denominatedInQuote": "true", "slippage": "200", "priorityFee": "0.00002001", }) } } } ``` *** #### Endpoint[​](#endpoint "Direct link to Endpoint") `POST https://api.pumpapi.io` #### Local Transactions[​](#local-transactions "Direct link to Local Transactions") Local transactions are supported for both approaches above, but will be slower. Use the same logic as on the [Trade API](/trade-api.md) page. *** Need help? Join our [Telegram group](https://t.me/pumpapi_devs). --- ## Partners ### Partners [🚀 Want to list your project here? →](/get-listed) The projects below are powered by **pumpapi.io**. All projects listed here are independent services operated by their own teams. We love seeing what they build with PumpApi, but we don't operate or audit them — as always, do your own research before using any third-party service. ##### [GhostFi ↗](https://ghostfi.dev/) [GhostFi is a private trading engine for Solana memecoins. It watches the entire stream, kills the traps on sight and executes your strategy — with keys that never leave you.](https://ghostfi.dev/) ##### [PAIF.fun ↗](https://paif.fun/) [PAIF.fun is a Solana trading hub with customizable swing, sniper and DCA bots, paper and live trading, token intelligence, creator-wallet leaderboards and copy trading](https://paif.fun/) --- ## Stream ### Data Stream – WebSocket API Use this endpoint to stream live: * Solana and tokens transfers * Pump.fun * PumpSwap * Raydium Launchpad (Bonk) * Raydium-CPMM * Meteora Launchpad (Bags, moonshot) * Meteora DAMM V1 * Meteora DAMM V2 * Meteora DLMM Subscribing delivers every event the moment it happens — **transfers, token creations, buys, sells, migrations, pool creations, adding and removing liquidity, and creator fee claims.** #### Endpoint[​](#endpoint "Direct link to Endpoint") ```text wss://stream.pumpapi.io/ ``` **Filter on the client.** The server sends *all* events.
**One connection only.** Open a single WebSocket per client and [reuse it](/FAQ.md).
**Reconnect logic.** Connections can drop (for example, due to server-side updates or your network issues). You should implement automatic reconnection in your client. #### 📦 Code Examples[​](#-code-examples "Direct link to 📦 Code Examples") * Python * JavaScript * Rust * Go ```python import asyncio import websockets import orjson as json # or use the standard json module (orjson is faster) async def pumpapi_data_stream(): uri = "wss://stream.pumpapi.io/" async with websockets.connect(uri) as websocket: async for message in websocket: event = json.loads(message) print(event) # {'action': 'buy', 'pool': 'pump', ...} asyncio.run(pumpapi_data_stream()) ``` ```javascript import WebSocket from 'ws'; // npm i ws const ws = new WebSocket('wss://stream.pumpapi.io/'); ws.on('message', data => { const event = JSON.parse(data); console.log(event); // { action: 'create', pool: 'pump', ... } }); ws.on('error', console.error); ``` ```rust // [package] // name = "pumpapi_stream" // version = "0.1.0" // edition = "2024" // [dependencies] // tokio = { version = "1", features = ["macros", "rt-multi-thread"] } // tokio-tungstenite = { version = "0.29", features = ["rustls-tls-webpki-roots"] } // futures-util = "0.3" // serde_json = "1" // url = "2" // rustls = { version = "0.23", features = ["ring"] } use futures_util::StreamExt; use serde_json::Value; use tokio_tungstenite::{connect_async, tungstenite::Message}; #[tokio::main] async fn main() { rustls::crypto::ring::default_provider() .install_default() .expect("Failed to install crypto provider"); let (mut ws, _) = connect_async("wss://stream.pumpapi.io/") .await .expect("Failed to connect"); while let Some(msg) = ws.next().await { if let Ok(Message::Binary(bin)) = msg { let text = std::str::from_utf8(&bin).unwrap(); let event: Value = serde_json::from_str(text).unwrap(); println!("{}", event); } } } ``` ```go package main import ( "context" "encoding/json" "fmt" "log" "nhooyr.io/websocket" ) func main() { ctx := context.Background() c, _, err := websocket.Dial(ctx, "wss://stream.pumpapi.io/", nil) if err != nil { log.Fatal(err) } defer c.Close(websocket.StatusNormalClosure, "") for { _, data, err := c.Read(ctx) if err != nil { log.Fatal(err) } var event map[string]interface{} json.Unmarshal(data, &event) fmt.Println(event) } } ``` ##### Event Examples[​](#event-examples "Direct link to Event Examples") * Transfer * Create * Trade * Migration * Create Pool * Liquidity Change * Claim Fees ```json { "signature": "3mGAAs4CkM86s3bN8Jkt2EZRGf7ZVkbgNk2pV3STrEof8nCdFg5kqWdFyohp23uFVwierCvdeuXBzy3QDwNdaX4L", "action": "transfer", "txSigner": "YubQzu18FDqJRyNfG8JqHmsdbxhnoQqcKUHBdUkN6tP", "transfers": [ { "from": "YubQzu18FDqJRyNfG8JqHmsdbxhnoQqcKUHBdUkN6tP", "to": "2XxKhfVBna1Jjs5PdCQmjAXHg6NnFXoNVEHfEz2ZnnL8", "amount": 500.0, "isSolana": False, "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", "programsUsed": [] }, { "from": "YubQzu18FDqJRyNfG8JqHmsdbxhnoQqcKUHBdUkN6tP", "to": "2XxKhfVBna1Jjs5PdCQmjAXHg6NnFXoNVEHfEz2ZnnL8", "amount": 0.00002, "isSolana": True, <----- is TRUE when mint is Sol or WSOL (wrapped sol) "mint": "So11111111111111111111111111111111111111111", "programsUsed": [] } ], "postBalances": { "YubQzu18FDqJRyNfG8JqHmsdbxhnoQqcKUHBdUkN6tP": { "sol": 0.015701352, "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v": 0.0, }, "2XxKhfVBna1Jjs5PdCQmjAXHg6NnFXoNVEHfEz2ZnnL8": { "sol": 2.628047189, "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v": 500.0, } }, "addressLookupTables": [], "priorityFee": 0.000005, "block": 388677942, "timestamp": 1766513012579 } ``` * Pump.Fun * Raydium Launchpad (Bonk) * Meteora Launchpad (Bags, moonshot) ```json { "signature": "58zv6eEs2Y9ARPt9VSdpo6h3A4sg2ijgNftk8vXGvjoHQEiMqgoL6mNnWX9uZ26WS6mtzWuXduf8vuhUwUKJ73Wk", "action": "create", "poolId": "EzW8aPTiayL6zNw3rpPTDiPsbPFfNcn7TNB8BstbUYh9", "mint": "AvxohnS3SSJRfw4h9u2am5DTRrNv9HY5je7EdqpVSA2i", "quoteMint": "So11111111111111111111111111111111111111112", "txSigner": "3dxmSSoSbLpmyZZTJhGP4w9DUPLCrMyyUNpb6eL8e3Rf", "initialBuy": 97545454.545454, "quoteAmount": 3.0, "tokensInPool": 695554545.454546, "quoteInPool": 3.0, "vTokensInBondingCurve": 975454545.454546, "vQuoteInBondingCurve": 33.0, "price": 3.383038210624416e-8, "marketCapQuote": 33.83038210624416, "poolFeeRate": 0.0125, "name": "CHUD", "symbol": "CHUD", "uri": "https://metadata.j7tracker.com/metadata/2456cf930d0a4a0e.json", "supply": 1000000000, "pool": "pump", "creatorFeeAddress": "3dxmSSoSbLpmyZZTJhGP4w9DUPLCrMyyUNpb6eL8e3Rf", "mayhemMode": False, "cashbackEnabled": True, "breakdown": [ {"action": "buy", "trader": "3dxmSSoSbLpmyZZTJhGP4w9DUPLCrMyyUNpb6eL8e3Rf", "tokenAmount": 97545454.545454, "quoteAmount": 3.0} ], "decimals": 6, "mintAuthority": None, "freezeAuthority": None, "tokenProgram": "spl-token-2022", "tokenExtensions": { "metadataPointer": {}, "tokenMetadata": {} }, "tradersInvolved": { "3dxmSSoSbLpmyZZTJhGP4w9DUPLCrMyyUNpb6eL8e3Rf": {} }, "programsUsed": [], "postBalances": { "3dxmSSoSbLpmyZZTJhGP4w9DUPLCrMyyUNpb6eL8e3Rf": { "sol": 38.017511052, "AvxohnS3SSJRfw4h9u2am5DTRrNv9HY5je7EdqpVSA2i": 97545454.545454, "So11111111111111111111111111111111111111112": 0.0 }, }, "addressLookupTables": ["J7tuiJanfndJWHzdLEgxFVwFkdyaryi96tjxwhPgckse"], "priorityFee": 0.00016, "block": 401114006, "timestamp": 1771427621579 } ``` ```json { "signature": "3LweLX1CG8qV17EmUztAw6isAZdY8sk2ZmHjiGhC6oY6BvdYQousXDivsSPi2xCf99PDdVAgqDBfyiLniTcmHNqR", "action": "create", "poolId": "FADuSqhV5nQqxCapi2PDvKnNnBBqg8DZEEvVGviELXrk", "mint": "HnXKZ5GRemRnKUP7wBcmrVcRYkFvQNKq8FtLj3gB1ray", "quoteMint": "So11111111111111111111111111111111111111112", "txSigner": "tAg2tgyHmkGTsmq8wBSKsGvUUgoH37cxmCfRUZSXdtB", "initialBuy": 151903987.89698, "quoteAmount": 5.0, "tokensInPool": 848096012.10302, "quoteInPool": 4.9475, "vTokensInBondingCurve": 921121617.699402, "vQuoteInBondingCurve": 34.948352951, "price": 3.7941084303598455e-8, "marketCapQuote": 37.94108430359845, "poolFeeRate": 0.0105, "name": "arrest", "symbol": "aarrest", "uri": "https://ipfs.io/ipfs/bafkreih2bzlff4xrkehmezdzirl6ybawtth24niqtjc6qwnordbhydglaq", "supply": 1000000000, "pool": "raydium-launchpad", "platform": "custom", "launchpadConfig": "4Bu96XjU84XjPDSpveTVf6LYGCkfW5FK7SNkREWcEfV4", "migrationThresholds": { "quote": 85.0 }, "breakdown": [ {"action": "buy", "trader": "tAg2tgyHmkGTsmq8wBSKsGvUUgoH37cxmCfRUZSXdtB", "tokenAmount": 848096012.10302, "quoteAmount": 5.0} ], "decimals": 6, "mintAuthority": None, "freezeAuthority": None, "tokenProgram": "spl-token", "tokenExtensions": {}, "tradersInvolved": { "tAg2tgyHmkGTsmq8wBSKsGvUUgoH37cxmCfRUZSXdtB": {} }, "programsUsed": [], "postBalances": { "tAg2tgyHmkGTsmq8wBSKsGvUUgoH37cxmCfRUZSXdtB": { "sol": 84.914642124, "HnXKZ5GRemRnKUP7wBcmrVcRYkFvQNKq8FtLj3gB1ray": 151903987.89698, "So11111111111111111111111111111111111111112": 0.0 }, }, "addressLookupTables": ["AcL1Vo8oy1ULiavEcjSUcwfBSForXMudcZvDZy5nzJkU"], "priorityFee": 0.000025, "block": 401380627, "timestamp": 1771532401666 } ``` ```json { "signature": "4gDNN8nDdoi84oUW4vb7yKQhsR8kZ5wTiF92REqDiDREGijh7P6VhNeW3QHSozKWA1vCN3GVLjYZfYuetMLjDvtb", "action": "create", "poolId": "BDLE4vLJ94mp9tEbTNRhf16vaNJ1cWfUrn5ePfx4EWpv", "mint": "CBy1rMkQAHH2Jq8fDsHYTQJBy8S83saHMHM4674TPMuX", "quoteMint": "So11111111111111111111111111111111111111112", "txSigner": "6Ed7RBZrKVAq2V67CpNUGJXp4Avnz25KjVzJCq7LaLYz", "initialBuy": 984498429.538417, "quoteAmount": 23.0, "tokensInPool": 13034155.851211, "quoteInPool": 23.0, "price": 1.7741917491987863e-6, "marketCapQuote": 1774.1917491987863, "poolFeeRate": 0.0025, "name": "Tesla AI", "symbol": "Tesla AI", "uri": "https://ipfs.io/ipfs/bafkreigcmxnxj2gteuf6oti2orhztqxp4ngtesaayw2xnmbp6h4pxspgba", "supply": 1000000000, "pool": "meteora-launchpad", "lockedLiquidityAfterMigration": "10%", <--- Beware of values below 100%, as they could lead to a rug pull after the migration. "poolFeeRateAfterMigration": 0.001, "migrationThresholds": { "quote": 30.0 }, "launchpadConfig": "E6MQpAxta1AQhsDii3trQrGVooqjkwKQ4LgwZ4SCVgo", "breakdown": [ {"action": "buy", "trader": "6Ed7RBZrKVAq2V67CpNUGJXp4Avnz25KjVzJCq7LaLYz", "tokenAmount": 984498429.538417, "quoteAmount": 23.0} ], "decimals": 6, "mintAuthority": None, "freezeAuthority": None, "tokenProgram": "spl-token", "tokenExtensions": {}, "tradersInvolved": { "6Ed7RBZrKVAq2V67CpNUGJXp4Avnz25KjVzJCq7LaLYz": {} }, "programsUsed": [], "postBalances": { "6Ed7RBZrKVAq2V67CpNUGJXp4Avnz25KjVzJCq7LaLYz": { "sol": 85.220508079, "CBy1rMkQAHH2Jq8fDsHYTQJBy8S83saHMHM4674TPMuX": 984498429.538417, "So11111111111111111111111111111111111111112": 0.0 }, }, "addressLookupTables": [], "priorityFee": 0.00005, "block": 400339537, "timestamp": 1771124275539 } ``` * Pump.Fun * Pump AMM * Raydium CPMM * Raydium Launchpad (Bonk) * Meteora Launchpad (Bags, moonshot) * Meteora DAMM V1 * Meteora DAMM V2 * Meteora DLMM ```json { "signature": "aoX15zAJCTXbmVirQxU2z8i23oTNkmMMeF1kpfGhREF6kheevuU5dEf9DFPxCqEzr7ecEJ7QeSkMNZzrBdLh3Se", "action": "buy", "poolId": "CXDVWmsmAsnobrNomKzbSGQ4yK2aJn94biJb2WBk5sgY", "mint": "7cmGMpnkZT5LptdGLfmTRCjYMJyNaeebxqs3iNHDpump", "quoteMint": "So11111111111111111111111111111111111111112", "txSigner": "DXfvedfYGSzZLWZ1xELJBnmFjhuk31vqEsD7BD56WLsg", "tokenAmount": 100982650.051702, "quoteAmount": 5.531851847, "tokensInPool": 437834050.619027, "quoteInPool": 14.849481467, "vTokensInBondingCurve": 717734050.619027, "vQuoteInBondingCurve": 44.849481467, "price": 6.248760446619256e-8, "marketCapQuote": 62.487604466192565, "name": "イーロン・マッスグ", "symbol": "Elon", "uri": "https://ipfs.io/ipfs/bafkreiczvj3ymnvaebp77kce7mltzlkaja6eukyaw4cepwymfhx3ay7fky", "supply": 1000000000.0, "poolFeeRate": 0.0125, "pool": "pump", "creatorFeeAddress": "E4Cs6yziKcGGA5YJ1oMweHwxR3aaJghLuSUj3NgkuzR1", "mayhemMode": False, "cashbackEnabled": True, "breakdown": [ {"action": "buy", "trader": "9428AwJJhrZZfhrdbJ8J2hZ5USwnbKJyUhrJvi8b4gfD", "tokenAmount": 42360259.934646, "quoteAmount": 2.145283949}, {"action": "buy", "trader": "ErKiKGyrSZJKg9Gv3E2CfV7hDFtmEacVvhZEaR1toMRL", "tokenAmount": 31433841.42323, "quoteAmount": 1.749629628}, {"action": "buy", "trader": "DXfvedfYGSzZLWZ1xELJBnmFjhuk31vqEsD7BD56WLsg", "tokenAmount": 27188548.693826, "quoteAmount": 1.63693827} ], "decimals": 6, "mintAuthority": None, "freezeAuthority": None, "tokenProgram": "spl-token-2022", "tokenExtensions": { "metadataPointer": {}, "tokenMetadata": {} }, "tradersInvolved": { "9428AwJJhrZZfhrdbJ8J2hZ5USwnbKJyUhrJvi8b4gfD": {}, "ErKiKGyrSZJKg9Gv3E2CfV7hDFtmEacVvhZEaR1toMRL": {}, "DXfvedfYGSzZLWZ1xELJBnmFjhuk31vqEsD7BD56WLsg": {} }, "programsUsed": [ "H4xyaFSrJ7gkxQhuDXBBzFYwRR8voNqAEYp5VaxyPRy", "G3UGQFQPkqywATsPMSiUBVa7mnJk8c1596nXcyVv8Xgz", "47NQGJvv6fAFD2jTYwRvPsubs2mU1bTE742GVVjyaZ4v" ], "postBalances": { "DXfvedfYGSzZLWZ1xELJBnmFjhuk31vqEsD7BD56WLsg": { "sol": 0.110920139, "7cmGMpnkZT5LptdGLfmTRCjYMJyNaeebxqs3iNHDpump": 27188548.693826, "So11111111111111111111111111111111111111112": 0.0 }, "9428AwJJhrZZfhrdbJ8J2hZ5USwnbKJyUhrJvi8b4gfD": { "sol": 0.096850355, "7cmGMpnkZT5LptdGLfmTRCjYMJyNaeebxqs3iNHDpump": 42360259.934646, "So11111111111111111111111111111111111111112": 0.0 }, "ErKiKGyrSZJKg9Gv3E2CfV7hDFtmEacVvhZEaR1toMRL": { "sol": 0.158586696, "7cmGMpnkZT5LptdGLfmTRCjYMJyNaeebxqs3iNHDpump": 31433841.42323, "So11111111111111111111111111111111111111112": 0.0 } }, "addressLookupTables": [ "7mFD2mUtRS65XstiSAvCJuYmdesZoQwCwRJhq1p3eRMe" ], "priorityFee": 0.000015, "block": 437055886, "timestamp": 1785796194106 } ``` * Pool created by Pump.Fun migration * Custom pool * Token-USDC pool (without SOL) ```json { "signature": "63NbM8aanc3y2NjNp18sEFwv65qW4qzYLfQod8gmEGrGhKiBiGBH7fsHZ7MWbXLNP6RGTCznP4fGQu3YboCkdkwD", "action": "buy", "poolId": "BP7s98rTsd5xTr2CgSVd9Lcpie3KF5yAkmohUgAp1No4", "mint": "E9qgYkgok8aCFXWuvQiYM8krmDbeTuARLgrBjThWpump", "quoteMint": "So11111111111111111111111111111111111111112", "txSigner": "52oc72vjNbpUhF7jNE1pPAvc17JwBTyxybFp3u7PvetG", "tokenAmount": 321548.585603, "quoteAmount": 0.33830352, "tokensInPool": 135059178.605839, "quoteInPool": 142.435011367, "price": 1.0546118585741353e-6, "marketCapQuote": 1054.6034417168921, "name": "Always Up", "symbol": "Au", "uri": "https://ipfs.io/ipfs/QmR3v8nbSgWizdgCroDZWmk6pJJCaSJefzZERVDRUanRKN", "supply": 999424080, "poolFeeRate": 0.012, "pool": "pump-amm", "poolCreatedBy": "pump", <--- pool created through a pump.fun migration. You can trust these pools — you will be able to sell. "burnedLiquidity": "100%", <--- means that no one has the ability to withdraw liquidity and perform a rug pull. But it doesn’t have to be 100% — even 30% of burned liquidity can be good, depending on the situation "creatorFeeAddress": "HRs5oryur4seP4ei1VUqV3j82HMGuvQrjsEzASHed8Ud", "mayhemMode": False, "cashbackEnabled": False, "virtualQuoteInPool": 0.0, "breakdown": [ {"action": "buy", "trader": "52oc72vjNbpUhF7jNE1pPAvc17JwBTyxybFp3u7PvetG", "tokenAmount": 321548.585603, "quoteAmount": 0.33830352} ], "decimals": 6, "mintAuthority": None, "freezeAuthority": None, "tokenProgram": "spl-token-2022", "tokenExtensions": { "metadataPointer": {}, "tokenMetadata": {} }, "tradersInvolved": { "52oc72vjNbpUhF7jNE1pPAvc17JwBTyxybFp3u7PvetG": {} }, "programsUsed": [], "postBalances": { "52oc72vjNbpUhF7jNE1pPAvc17JwBTyxybFp3u7PvetG": { "sol": 1.986860538, "E9qgYkgok8aCFXWuvQiYM8krmDbeTuARLgrBjThWpump": 321548.585603, "So11111111111111111111111111111111111111112": 118.994959332 }, }, "addressLookupTables": [], "priorityFee": 0.000012511, "block": 388731952, "timestamp": 1766534221298 } ``` ```json { "signature": "3BS3QLu7Fv2xC7t65NELaZgwD7hB2maKXBqgp9GH5qtHNoesK6okE1p2h1kxK97QpSALMmvhNraw6FZ6skEn2shV", "action": "sell", "poolId": "AjotwbNS5iJxZn4GqJ6xx3qwMk9veqPh16omBZj2gW8s", "mint": "5MJzrhrw72cgm5XFUS8gf8puJYAzo5tJi18KimzFHxSM", "quoteMint": "So11111111111111111111111111111111111111112", "txSigner": "J7E1skXzMR6omFEhz7NxTD6R9LxXPgP1kUxnd3rRvvNs", "tokenAmount": 254489.459739, "quoteAmount": 0.614039516, "tokensInPool": 728331144.293985, "quoteInPool": 1756.730934593, "price": 2.411994802578303e-6, "marketCapQuote": 2411.9947992420152, "name": "squid", "symbol": "QUID", "uri": "https://ipfs.io/ipfs/QmX6WiVXmDFc49AxyzsevEvdMygrfpnJvSYjGNFNftZmjY", "supply": 999999998.616793, "poolFeeRate": 0.003, "pool": "pump-amm", "poolCreatedBy": "custom", <--- Be careful with pools on pump-amm where poolCreatedBy is not "pump" "burnedLiquidity": "0%", <--- SCAM pool. 0% means that it’s possible to withdraw all the liquidity (remove 100% of the tokens and 100% SOL from the pool), so you will not be able sell bought tokens after that. "creatorFeeAddress": None, "mayhemMode": False, "cashbackEnabled": False, "virtualQuoteInPool": 0.0, "breakdown": [ {"action": "buy", "trader": "J7E1skXzMR6omFEhz7NxTD6R9LxXPgP1kUxnd3rRvvNs", "tokenAmount": 525838.707808, "quoteAmount": 1.270126649}, {"action": "sell", "trader": "AhzkNJn96fWhvdixph4DGCoykGj39fSYcVBxYcpKEHTr", "tokenAmount": 780328.167547, "quoteAmount": 1.884166165} ], "decimals": 6, "mintAuthority": None, "freezeAuthority": None, "tokenProgram": "spl-token", "tokenExtensions": {}, "tradersInvolved": { "J7E1skXzMR6omFEhz7NxTD6R9LxXPgP1kUxnd3rRvvNs": {}, "AhzkNJn96fWhvdixph4DGCoykGj39fSYcVBxYcpKEHTr": {} }, "programsUsed": [], "postBalances": { "J7E1skXzMR6omFEhz7NxTD6R9LxXPgP1kUxnd3rRvvNs": { "sol": 0.076338771, "5MJzrhrw72cgm5XFUS8gf8puJYAzo5tJi18KimzFHxSM": 5217338.579393, "So11111111111111111111111111111111111111112": 0.0 }, "AhzkNJn96fWhvdixph4DGCoykGj39fSYcVBxYcpKEHTr": { "sol": 2.187016752, "5MJzrhrw72cgm5XFUS8gf8puJYAzo5tJi18KimzFHxSM": 4218638.691638, "So11111111111111111111111111111111111111112": 0.0 } }, "addressLookupTables": [ "8NkCVgdWUKLiykSWBDcapSUuvFWb8QbVWLau1ayTakbv" ], "priorityFee": 0.00001, "block": 437035686, "timestamp": 1785787648153 } ``` ```json { "signature": "2XUWkeeKuZxz8kApj774PpGgcUyR9tZLAKwT6pHNNQcXsTBB6yxdDDPgr9TB4HiFpbExStKG2SnqpQTHqj9mYAay", "action": "sell", "poolId": "2uF4Xh61rDwxnG9woyxsVQP7zuA6kLFpb3NvnRQeoiSd", <--- you can open this address on solscan.io and see that there’s no SOL in this pool — only USDC and the token. To buy this token, you first need to buy the quoteToken (USDC) elsewhere. "mint": "pumpCmXqMfrsAkQ5r49WcJnRayYRqmXz6ae8H7H9Dfn", "quoteMint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", <--- address of the second token involved (in this case USDC) "txSigner": "FkaLnX17cXZGyeu3kZGdHCNdFMJJzBrPPYVvd18B3MZp", "tokenAmount": 382028.596844, "quoteAmount": 1827.399274, "tokensInPool": 2439935577.067193, "quoteInPool": 11669383.973787, "price": 0.004782660691317769, "marketCapQuote": 4007388345.6877337, "name": "Pump", "symbol": "PUMP", "uri": "https://ipfs.io/ipfs/bafkreibcglldkfdekdkxgumlveoe6qv3pbiceypkwtli33clbzul7leo4m", "supply": 837899362788.2843, "poolFeeRate": 0.003, "pool": "pump-amm", "poolCreatedBy": "custom", "burnedLiquidity": "0%", <--- in this particular case, 0% is not a problem because this poolId is the official PUMP-USDC pool from the pump.fun team. "creatorFeeAddress": None, "mayhemMode": False, "cashbackEnabled": False, "virtualQuoteInPool": 0.0, "breakdown": [ {"action": "sell", "trader": "FkaLnX17cXZGyeu3kZGdHCNdFMJJzBrPPYVvd18B3MZp", "tokenAmount": 382028.596844, "quoteAmount": 1827.399274} ], "decimals": 6, "mintAuthority": None, "freezeAuthority": None, "tokenProgram": "spl-token-2022", "tokenExtensions": { "transferHook": {}, "metadataPointer": {}, "tokenMetadata": {} }, "tradersInvolved": { "FkaLnX17cXZGyeu3kZGdHCNdFMJJzBrPPYVvd18B3MZp": {} }, "programsUsed": [], "postBalances": { "FkaLnX17cXZGyeu3kZGdHCNdFMJJzBrPPYVvd18B3MZp": { "sol": 127.073886204, "pumpCmXqMfrsAkQ5r49WcJnRayYRqmXz6ae8H7H9Dfn": 24492559.437621, "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v": 2006277.014475 } }, "addressLookupTables": [], "priorityFee": 0.000018544, "block": 441622567, "timestamp": 1787658023473 } ``` * Pool created by Raydium Launchpad (Bonk) migration * Token-Token pool (without SOL) ```json { "signature": "2CHuzsiFN94ptUneFuSUCn9miTCTnUX4AWSczCpzAFAa3Mb9RruLPuyTBRYYFXWKPNXSNMqAHJm3zGYuDE6aHcEw", "action": "sell", "poolId": "4UN6WPJhfB9eoQq4XUwWiDj7NguW4iw9rx4iGBUguXcT", "mint": "6Tph3SxbAW12BSJdCevVV9Zujh97X69d5MJ4XjwKmray", "quoteMint": "So11111111111111111111111111111111111111112", "txSigner": "91WuBL56WNkLeXiFPQ1B1zDrHYNWo3KiC8Gp3FeJVCay", "tokenAmount": 142506.761471, "quoteAmount": 0.200875025, "tokensInPool": 143086855.207232, "quoteInPool": 201.996832141, "price": 1.4117078179435069e-6, "marketCapQuote": 1411.489916606684, "name": "CyreneAI", "symbol": "CYAI", "uri": "https://ipfs.io/ipfs/bafkreicmxqxbc25ktl32ec5zmnqnxgxzj3yp2xwospj5c4nl3w3i2vkccu", "supply": 999829979.0, "poolFeeRate": 0.003, "pool": "raydium-cpmm", "poolCreatedBy": "raydium-launchpad", <---- pool created by raydium-launchpad (usually bonk), so you can trust it. "burnedLiquidity": "91%", "breakdown": [ {"action": "sell", "trader": "HU23r7UoZbqTUuh3vA7emAGztFtqwTeVips789vqxxBw", "tokenAmount": 142506.761471, "quoteAmount": 0.200875025} ], "decimals": 6, "mintAuthority": None, "freezeAuthority": None, "tokenProgram": "spl-token", "tokenExtensions": {}, "tradersInvolved": { "HU23r7UoZbqTUuh3vA7emAGztFtqwTeVips789vqxxBw": {} }, "programsUsed": ["JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4"], "postBalances": { "91WuBL56WNkLeXiFPQ1B1zDrHYNWo3KiC8Gp3FeJVCay": { "sol": 0.010042113, "6Tph3SxbAW12BSJdCevVV9Zujh97X69d5MJ4XjwKmray": 37617.953108746, "So11111111111111111111111111111111111111112": 0.0 }, "HU23r7UoZbqTUuh3vA7emAGztFtqwTeVips789vqxxBw": { "sol": 2.803769208, "6Tph3SxbAW12BSJdCevVV9Zujh97X69d5MJ4XjwKmray": 61635.816808, "So11111111111111111111111111111111111111112": 5.163847908 }, }, "addressLookupTables": ["3oy9ojnsDzqmMNi87Gs7Hn5v3MPVqnWjG9k8BmzKR7yW", "4h3dhpTxyfwrFu6P8ouYttbgZkzguD5KS1verbfCZ4YW", "DUFCguoT5MSFrUq1fCLkaL6B3Z2K6g7cz4CN1JDtasjB"], "priorityFee": 0.000015, "block": 388738247, "timestamp": 1766536690846 } ``` ```json { "signature": "Rr2bAWDLx4XV4b7faUXuXWm4SmLZrU6dxfpo1MZ1ji9sM47pLmMujZbnTFfsfBgth4JQtaaAT19bw8vg6isEs2w", "action": "buy", "poolId": "Hx7hLugyG3h7LVgYGTzdNXJFd6gYMHeyji2qTHFcy9F", "mint": "BUF78MFWRunrSk7ViSwwQUGyJskVFo5uUfWspKUnTity", <---- one memecoin "quoteMint": "69G8CpUVZAxbPMiEBrfCCCH445NwFxH6PzVL693Xpump", <— another memecoin (usually it’s Solana or stablecoins, but this pool uses another volatile token). To buy this token, you first need to buy the quoteToken elsewhere. "txSigner": "GxDC9e7SP9mzhDo4re5HbpLa2RW7gB9DtmThx4i4pXSq", "tokenAmount": 56264.646799964, "quoteAmount": 370.952623, "tokensInPool": 89525497.30657841, "quoteInPool": 585524.721433, "price": 0.006540312414326854, "marketCapQuote": 6037576.399403305, "name": "Trinity", "symbol": "TRINITY", "uri": "https://gateway.pinata.cloud/ipfs/QmZZbhBTqhoFhtJmrFGFW1d4JoU5utj6B6xWDX28b7Nnj8", "supply": 923132721.6384522, "poolFeeRate": 0.0105, "pool": "raydium-cpmm", "poolCreatedBy": "custom", "burnedLiquidity": "52%", "breakdown": [ {"action": "buy", "trader": "GxDC9e7SP9mzhDo4re5HbpLa2RW7gB9DtmThx4i4pXSq", "tokenAmount": 56264.646799964, "quoteAmount": 370.952623} ], "decimals": 9, "mintAuthority": None, "freezeAuthority": None, "tokenProgram": "spl-token", "tokenExtensions": {}, "tradersInvolved": { "GxDC9e7SP9mzhDo4re5HbpLa2RW7gB9DtmThx4i4pXSq": {} }, "programsUsed": [ "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4", "NinafKYvKDCH26v6uEpfDjyuDjjpbdfhiPjrJV6FTFs" ], "postBalances": { "GxDC9e7SP9mzhDo4re5HbpLa2RW7gB9DtmThx4i4pXSq": { "sol": 28.996026075, "BUF78MFWRunrSk7ViSwwQUGyJskVFo5uUfWspKUnTity": 0.0, "69G8CpUVZAxbPMiEBrfCCCH445NwFxH6PzVL693Xpump": 0.0 } }, "addressLookupTables": [ "9SvnEa8bqMNjYyxT4zKhCVhTPoZ1EhVTNEi1DwQHgJCS", "4UThg4zVo1FHWHHMM74nkvHtXD8P6vVc9AGEiPgfXVr8", "HhxyCx3HxK3akqD9fgFZkFUBiC8sXdkfqVkXopF72jA9", "edvM3tz11ENKhmoNwp8t7iNKKiF2nciCRdaZpAdZL7k" ], "priorityFee": 5.054e-6, "block": 437041079, "timestamp": 1785789926221 } ``` ```json { "signature": "5kLZfmUnb7mDnXyNZXSVGWcUdj8BFkyLauycWMYpM6j2GPg9VFjgRnyGdqU1yij8wWahseVj5AwXeyBTw8m2oDpj", "action": "buy", "poolId": "BnHRVmtz66soqmGifK7725TXzxUN2oBEhVDs2LjkhYN6", "mint": "rz9G7vCQBxPNrejMv4iVa3UyuxJasBAjjsmDnhnbonk", "quoteMint": "USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB", <--- Address of the second token involved (in this case, USD1). To trade in this pool, you first need to buy the quoteMint (USD1) "txSigner": "HKHMrsfW9rDc1KrT1gU4AmC5A2hvVqwRMujN5eegMLX8", "tokenAmount": 0.227592, "quoteAmount": 0.000012, "tokensInPool": 239942135.99963, "quoteInPool": 10714.496586, "vTokensInBondingCurve": 312967741.595121, "vQuoteInBondingCurve": 15126.386725, "price": 0.00004833209533961698, "marketCapQuote": 48332.095339616986, "name": "BONKEY", "symbol": "BONKEY", "uri": "https://ipfs.io/ipfs/QmNwXK3y8ATQybkpQ4RRSgBFQbdxzjwEWn8CFZUiDjhfGb", "supply": 999997533.0, "poolFeeRate": 0.013, "pool": "raydium-launchpad", "platform": "bonk", <--- can be "bonk", "raydium-launchlab", or "custom". Anyone can create a platform on the Raydium launchpad — Bonk is just one of them "launchpadConfig": "FfYek5vEz23cMkWsdJwG2oa6EphsvXSHrGpdALN4g6W1", "migrationThresholds": { "quote": 12500.0 }, "decimals": 6, "mintAuthority": None, "breakdown": [ {"action": "buy", "trader": "HKHMrsfW9rDc1KrT1gU4AmC5A2hvVqwRMujN5eegMLX8", "tokenAmount": 0.227592, "quoteAmount": 0.000012} ], "freezeAuthority": None, "tokenProgram": "spl-token", "tokenExtensions": {}, "tradersInvolved": { "HKHMrsfW9rDc1KrT1gU4AmC5A2hvVqwRMujN5eegMLX8": {} }, "postBalances": { "HKHMrsfW9rDc1KrT1gU4AmC5A2hvVqwRMujN5eegMLX8": { "sol": 0.03145508, "rz9G7vCQBxPNrejMv4iVa3UyuxJasBAjjsmDnhnbonk": 384.336172, "USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB": 19.400235 }, }, "priorityFee": 0.000006, "block": 388764798, "timestamp": 1766547117907 } ``` ```json { "signature": "5RKRyZ5E4EjezdhkpnvtPXJoR2hLpHispSrAEWebCAEjheni3D6UrciBWN3becVaaEnZBS69XcdnvvLDRENzUEJv", "action": "buy", "poolId": "3DrHmGXh9LVFFxz5yGmgm8jagHijqhXvSQyjhus1etPa", "mint": "3DsdCFH1RGfaV1CUSJzbmYQ7vFSsVuEFK1tHRVAiBAGS", "quoteMint": "So11111111111111111111111111111111111111112", "txSigner": "13NZSDSMRvP75Y97UnDxD12LCTDtaXsmbyABSqyz8yDP", "tokenAmount": 2921696.077137405, "quoteAmount": 0.26, "tokensInPool": 469002275.1985069, "quoteInPool": 26.757985773, "price": 8.756358166765358e-8, "marketCapQuote": 87.56358166765358, "name": "Christ Bags", "symbol": "CHRIST", "uri": "https://ipfs.io/ipfs/QmdDzoyXSZN3MxRF3rguF3QrP7XhrW5jybK3VenxXgK7L2", "supply": 999999999, "poolFeeRate": 0.02, "pool": "meteora-launchpad", "lockedLiquidityAfterMigration": "100%", <--- Beware of values below 100%, as they could lead to a rug pull after the migration. "poolFeeRateAfterMigration": 0.02, <--- Check this: if it’s, for example, 0.1 (the maximum future fee allowed), you will lose 10% on each trade. "migrationThresholds": { "quote": 85.0 }, "launchpadConfig": "A1z7xx4Vr24q2P6Hy7ee4Xo7RtQraM93M9FdTobmL3G9", "breakdown": [ {"action": "buy", "trader": "13NZSDSMRvP75Y97UnDxD12LCTDtaXsmbyABSqyz8yDP", "tokenAmount": 2921696.077137405, "quoteAmount": 0.26} ], "decimals": 9, "mintAuthority": None, "freezeAuthority": None, "tokenProgram": "spl-token", "tokenExtensions": {}, "tradersInvolved": { "13NZSDSMRvP75Y97UnDxD12LCTDtaXsmbyABSqyz8yDP": {} }, "postBalances": { "13NZSDSMRvP75Y97UnDxD12LCTDtaXsmbyABSqyz8yDP": { "sol": 3.757488496, "3DsdCFH1RGfaV1CUSJzbmYQ7vFSsVuEFK1tHRVAiBAGS": 2921696.077137405, "So11111111111111111111111111111111111111112": 0.0 }, }, "priorityFee": 0.000055, "block": 400331273, "timestamp": 1771121062458 } ``` ```json { "signature": "4XRntfX8s4ryHi9XckbvPSFHeuhZ5AinoieybTRFuW39XW8ue9jheT4hDMj7eZnPt1Wc6XXkUHJNKt3H6VRCErXU", "action": "buy", "poolId": "ERgpKaq59Nnfm9YRVAAhnq16cZhHxGcDoDWCzXbhiaNw", "mint": "J1toso1uCk3RLmjorhTtrVwY9HJ7X8V9yYac6Y7kGCPn", "quoteMint": "So11111111111111111111111111111111111111112", "txSigner": "BCdcmLAuYx2RCGGCZhWuP9fgiZje2pBRrjLHr1qH4nZL", "tokenAmount": 0.111010032, "quoteAmount": 0.13997, "tokensInPool": 13603.81205579, "quoteInPool": 9693.056530216, "price": 1.2611303844898412, "marketCapQuote": 13431882.291044032, "name": "Jito Staked SOL", "symbol": "JitoSOL", "uri": "https://storage.googleapis.com/token-metadata/JitoSOL.json", "supply": 7700706.0, "poolFeeRate": 0.0001, "pool": "meteora-damm-v1", "poolCreatedBy": "custom", "burnedLiquidity": "0%", "curveType": "StableSwap", "breakdown": [ {"action": "buy", "trader": "BCdcmLAuYx2RCGGCZhWuP9fgiZje2pBRrjLHr1qH4nZL", "tokenAmount": 0.111010032, "quoteAmount": 0.13997} ], "decimals": 9, "mintAuthority": "6iQKfEyhr3bZMotVkW6beNZz5CPAkiwvgV2CTje9pVSS", "freezeAuthority": None, "tokenProgram": "spl-token", "tokenExtensions": {}, "tradersInvolved": { "BCdcmLAuYx2RCGGCZhWuP9fgiZje2pBRrjLHr1qH4nZL": {} }, "postBalances": { "BCdcmLAuYx2RCGGCZhWuP9fgiZje2pBRrjLHr1qH4nZL": { "sol": 0.640961276, "J1toso1uCk3RLmjorhTtrVwY9HJ7X8V9yYac6Y7kGCPn": 0.111010032, "So11111111111111111111111111111111111111112": 0.0 }, }, "priorityFee": 0.000005, "block": 400345180, "timestamp": 1771126482369 } ``` ```json { "signature": "4XMDoJJt5HK97oWcqyjSKVw8pJY8McSy6KnEFiutuxWwkiqmmWwrrN2AtCBED77cz35gkitB6JatGD4cZzLFTXk5", "action": "buy", "poolId": "Fy62YfCBu2z4hmLk3m68XrtBBLHtZXY1Si5rtVsrsRvs", "mint": "E9vNSVzuwWcmsFkbSVWXAhbPwETJv4aM8Lvs5ympump", "quoteMint": "So11111111111111111111111111111111111111112", "txSigner": "7zZ2vRvqyP5Ey9qy4s2593DTg8J4sNYWrmcNnmDE4F9B", "tokenAmount": 105775.084401, "quoteAmount": 0.610509458, "tokensInPool": 2944583.780026, "quoteInPool": 17.588974243, "price": 5.973331244963443e-6, "marketCapQuote": 5973.331244963442, "name": "Ichikawa Coin", "symbol": "ICHIĆO", "uri": "https://metadata.rapidlaunch.io/metadata/520895cc-38b2-4217-a2b1-aaaf939ce079.json", "supply": 990396929.0, "poolFeeRate": 0.001, "pool": "meteora-damm-v2", "poolCreatedBy": "meteora-launchpad", "burnedLiquidity": "10%", "minPrice": 5.421214630269583e-23, "maxPrice": 1.844605071373595e16, "breakdown": [ {"action": "buy", "trader": "7zZ2vRvqyP5Ey9qy4s2593DTg8J4sNYWrmcNnmDE4F9B", "tokenAmount": 105775.084401, "quoteAmount": 0.610509458} ], "decimals": 6, "mintAuthority": None, "freezeAuthority": None, "tokenProgram": "spl-token", "tokenExtensions": {}, "tradersInvolved": { "7zZ2vRvqyP5Ey9qy4s2593DTg8J4sNYWrmcNnmDE4F9B": {} }, "postBalances": { "7zZ2vRvqyP5Ey9qy4s2593DTg8J4sNYWrmcNnmDE4F9B": { "sol": 0.00290572, "E9vNSVzuwWcmsFkbSVWXAhbPwETJv4aM8Lvs5ympump": 105775.15211, "So11111111111111111111111111111111111111112": 0.034105369 }, }, "priorityFee": 0.000005, "block": 400350764, "timestamp": 1771128655157 } ``` ```json { "signature": "3KawMPWFEv3NAD2EebvKvNXVjAUnGHuVjyu2cgwFatxZwjGqm1AB9BUJQ7wVXEeBWBAqYeoFDJZ75X2yZ9ghMrcz", "action": "buy", "poolId": "6e7V9eegCHw997T72MxgwwJipZ6GJyZF8NvjkzT1rvpN", "mint": "9cRCn9rGT8V2imeM2BaKs13yhMEais3ruM3rPvTGpump", "quoteMint": "So11111111111111111111111111111111111111112", "txSigner": "7dGrdJRYtsNR8UYxZ3TnifXGjGc9eRYLq9sELwYpuuUu", "tokenAmount": 2144.072797, "quoteAmount": 4.702360369, "tokensInPool": 3794059.376787, "quoteInPool": 14244.689403313, "price": 0.002184133191419135, "marketCapQuote": 2184007.027149466, "name": "The Black Bull", "symbol": "ANSEM", "uri": "https://meta.uxento.io/data/7f4c8448-c38e-4c34-aa37-a28cff9806d0", "supply": 999942236.0, "poolFeeRate": 0.0041298, "pool": "meteora-dlmm", "binStep": 20, "breakdown": [ {"action": "buy", "trader": "7dGrdJRYtsNR8UYxZ3TnifXGjGc9eRYLq9sELwYpuuUu", "tokenAmount": 2144.072797, "quoteAmount": 4.702360369} ], "decimals": 6, "mintAuthority": None, "freezeAuthority": None, "tokenProgram": "spl-token-2022", "tokenExtensions": { "metadataPointer": {}, "tokenMetadata": {} }, "tradersInvolved": { "7dGrdJRYtsNR8UYxZ3TnifXGjGc9eRYLq9sELwYpuuUu": {} }, "programsUsed": [ "King7ki4SKMBPb3iupnQwTyjsq294jaXsgLmJo8cb7T" ], "postBalances": { "7dGrdJRYtsNR8UYxZ3TnifXGjGc9eRYLq9sELwYpuuUu": { "sol": 194.928638958, "9cRCn9rGT8V2imeM2BaKs13yhMEais3ruM3rPvTGpump": 0.000492, "So11111111111111111111111111111111111111112": 3601.874546701 } }, "addressLookupTables": [ "AsQLhBq3xodjpZfpqoY4hZb5YmEM9HzoE9FjUnv7z2Qw" ], "priorityFee": 0.000037585, "block": 435154460, "timestamp": 1784994123306 } ``` * Pump AMM * Meteora DAMM V1 * Meteora DAMM V2 ```json { "signature": "nyxdgkkUYWLsBzpK3Nqi3pECLbbhvogxUNrR5oghsExttMo5MBvmQhMCCK4oxnKt3pMggikAu2DzUK8EQUSzite", "action": "migrate", "poolId": "AoFvnKze1iRQEggPz9LHEvGRc6gL4k2oqr4y6M7btznv", "mint": "vPXpn63usdnU928rMi2NYWKzmDy5ZwzP24Gd2Qnpump", "quoteMint": "So11111111111111111111111111111111111111112", "txSigner": "9akWW699L1GU74z1Tr1yeU4UmdDVQY5GboeSvPGUxL7g", "initialBuy": 0.0, "quoteAmount": 0.0, "tokensInPool": 206900000.0, "quoteInPool": 67.405853768, "price": 4.1077988910584825e-7, "marketCapQuote": 410.77988910584827, "name": "@everyone buy this coin", "symbol": "@everyone", "uri": "https://ipfs.io/ipfs/bafkreihfi7dd4xo5ka6dkt2f6rfrzylcwaz44zds3gqsmld6r7czedd4ly", "supply": 1000000000.0, "quoteSupply": 0.0, "poolFeeRate": 0.0125, "pool": "pump-amm", "poolCreatedBy": "pump", "burnedLiquidity": "100%", "creatorFeeAddress": "9akWW699L1GU74z1Tr1yeU4UmdDVQY5GboeSvPGUxL7g", "mayhemMode": False, "cashbackEnabled": False, "virtualQuoteInPool": 17.584505288, "decimals": 6, "mintAuthority": None, "freezeAuthority": None, "tokenProgram": "spl-token-2022", "tokenExtensions": { "metadataPointer": {}, "tokenMetadata": {} }, "tradersInvolved": { "FFaeDLKvvBd4HH1A4kNx5ht8ZRSqiVY2L3Pvo7G7eBWj": {} }, "programsUsed": [ "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P" ], "postBalances": { "9akWW699L1GU74z1Tr1yeU4UmdDVQY5GboeSvPGUxL7g": { "sol": 128.923773133, "vPXpn63usdnU928rMi2NYWKzmDy5ZwzP24Gd2Qnpump": 0.0, "So11111111111111111111111111111111111111112": 0.0 }, "FFaeDLKvvBd4HH1A4kNx5ht8ZRSqiVY2L3Pvo7G7eBWj": { "sol": 0.0, "vPXpn63usdnU928rMi2NYWKzmDy5ZwzP24Gd2Qnpump": 0.0, "So11111111111111111111111111111111111111112": 0.0 } }, "addressLookupTables": [ "2WhJW3hSgVK2XR7o19SjAUk7xAfbPuBJy6ChDAJBTSsU" ], "priorityFee": 5e-6, "block": 441650564, "timestamp": 1787668279005 } ``` ```json { "signature": "AgmvLnh4DR52FmPvGmPYLwmSihhU59iMe9F9TNXSsPLgV9JokAjzxrjAmQBPvXiv88noYD5ieWQzWtLefoafmEZ", "action": "migrate", "poolId": "5DuwQd3MAiCcugJG24tq3TJ5MHCuWpZJywbkgMTYao6h", "mint": "DHuyFyr5vwMa9hC71i1nqg7kZ4PfxBG5FEm7TqrsxgUb", "quoteMint": "So11111111111111111111111111111111111111112", "txSigner": "CQdrEsYAxRqkwmpycuTwnMKggr3cr9fqY8Qma4J9TudY", "initialBuy": 0.0, "quoteAmount": 0.0, "tokensInPool": 23989059.724993, "quoteInPool": 11.976219064, "price": 4.992367021172813e-7, "marketCapQuote": 499.2367021172813, "name": "BIG JOHN MACHINE 🎶", "symbol": "BIGJOHN", "uri": "https://static-create.jup.ag/metadata/575UoSuXVqMgKwDXLD56HFCUJFC6uyGN4CZbWG32jups.json", "supply": 1000000000, "poolFeeRate": 0.0025, "pool": "meteora-damm-v1", "poolCreatedBy": "meteora-launchpad", "burnedLiquidity": "0%", "curveType": "ConstantProduct", "decimals": 6, "mintAuthority": None, "freezeAuthority": None, "tokenProgram": "spl-token", "tokenExtensions": {}, "tradersInvolved": { "FhVo3mqL8PW5pH5U2CN4XE33DokiyZnUwuGpH2hmHLuM": {} }, "programsUsed": [], "postBalances": { "CQdrEsYAxRqkwmpycuTwnMKggr3cr9fqY8Qma4J9TudY": { "sol": 734.855638775, "DHuyFyr5vwMa9hC71i1nqg7kZ4PfxBG5FEm7TqrsxgUb": 0.0, "So11111111111111111111111111111111111111112": 0.0 }, "FhVo3mqL8PW5pH5U2CN4XE33DokiyZnUwuGpH2hmHLuM": { "sol": 3.982328788, "DHuyFyr5vwMa9hC71i1nqg7kZ4PfxBG5FEm7TqrsxgUb": 950341742.050433, "So11111111111111111111111111111111111111112": 0.08390853 }, }, "addressLookupTables": [], "priorityFee": 0.000005, "block": 400336821, "timestamp": 1771123217240 } ``` ```json { "signature": "4pqYzmMniFutZgzeKzVYcQxAQab872RLG5mGeTcAEBzZ9uLmELTpEXsrt3hsrHvSB8jYnW9HGRWxAYPZsypmdyBY", "action": "migrate", "poolId": "GCv2qtGK2Qzi7df9dU6urKzo9WcsrU3fDjwkpddPYn7x", "mint": "CBy1rMkQAHH2Jq8fDsHYTQJBy8S83saHMHM4674TPMuX", "quoteMint": "So11111111111111111111111111111111111111112", "txSigner": "CQdrEsYAxRqkwmpycuTwnMKggr3cr9fqY8Qma4J9TudY", "initialBuy": 0.0, "quoteAmount": 0.0, "tokensInPool": 9980000.042297, "quoteInPool": 29.939999999, "price": 3e-6, "marketCapQuote": 3000.0, "name": "Tesla AI", "symbol": "Tesla AI", "uri": "https://ipfs.io/ipfs/bafkreigcmxnxj2gteuf6oti2orhztqxp4ngtesaayw2xnmbp6h4pxspgba", "supply": 1000000000, "poolFeeRate": 0.001, "pool": "meteora-damm-v2", "poolCreatedBy": "meteora-launchpad", "burnedLiquidity": "10%", "minPrice": 5.421214630269583e-23, "maxPrice": 1.844605071373595e16, "decimals": 6, "mintAuthority": None, "freezeAuthority": None, "tokenProgram": "spl-token", "tokenExtensions": {}, "tradersInvolved": { "FhVo3mqL8PW5pH5U2CN4XE33DokiyZnUwuGpH2hmHLuM": {} }, "programsUsed": [], "postBalances": { "CQdrEsYAxRqkwmpycuTwnMKggr3cr9fqY8Qma4J9TudY": { "sol": 733.888408191, "CBy1rMkQAHH2Jq8fDsHYTQJBy8S83saHMHM4674TPMuX": 0.0, "So11111111111111111111111111111111111111112": 0.0 }, "FhVo3mqL8PW5pH5U2CN4XE33DokiyZnUwuGpH2hmHLuM": { "sol": 3.982328788, "CBy1rMkQAHH2Jq8fDsHYTQJBy8S83saHMHM4674TPMuX": 2495224.029264, "So11111111111111111111111111111111111111112": 0.060411783 }, }, "addressLookupTables": [], "priorityFee": 0.000016962, "block": 400343572, "timestamp": 1771125858449 } ``` * Pump AMM * Raydium CPMM * Meteora DAMM V1/V2 * Meteora DLMM ```json { "signature": "3BiAqMmm2dX4GjLdajKQnSTMLTC3oQzRVVTEKvKeFu7jSAcE3kFVq7u3BpoSasx77U2rBTArRgqossfiGaTP1iDh", "action": "createPool", "poolId": "8yEwjGT16re94WAahxrvMg79smn5B8rzZgPTNWFzkW3K", "mint": "DGvxoH8zEmatVbMMydMFDhsiofdgK2cFn6dPccNJ6hEg", "quoteMint": "So11111111111111111111111111111111111111112", "txSigner": "JBHqRGJ9rVGzHg3DqzbFkh235kjvEiEMhBMQsU4fiAon", "initialBuy": 0.0, <--- can be initialSell "quoteAmount": 0.0, "tokensInPool": 1000000000.0, "quoteInPool": 200.0, "price": 2e-7, "marketCapQuote": 200.0000002, "name": "Internet Boy", "symbol": "IBOY", "uri": "https://ipfs.io/ipfs/QmZ88vh4MEMBQVqrG9ZRqUS8fedg5cQ1TTJxAYYfPESWCk", "supply": 1000000001.0, "poolFeeRate": 0.003, "pool": "pump-amm", "poolCreatedBy": "custom", <-- will always be "custom" in createPool events. If it’s "pump" or "raydium-launchpad", then it’s a migration event. But technically, these events are the same: migration = the memecoin launchpad creates the pool and burns liquidity; createPool = anyone else creates a pool. "burnedLiquidity": "0%", <-- a typical scam pool. They create a pool with a lot of liquidity, but they can remove it later because it isn’t burned. The higher the burnedLiquidity, the lower the risk of a rug pull by the liquidity providers. This is what happens after they get enough buyers Z2QxTU9Z9njczyF9akMJbzhRotDRbU1ieByXQhPn4MgW6BcdJUvqYkATG5EyWyRCuG3HKZd3ms7CRjLZ5TdGhep (they remove 100% of the liquidity — not the initial 200 SOL, but 100% of the current SOL reserves, so they pull 270 SOL out of the pool). "creatorFeeAddress": None, "mayhemMode": False, "cashbackEnabled": False, "virtualTokensInPool": 0.0, "decimals": 6, "mintAuthority": None, "freezeAuthority": None, "tokenProgram": "spl-token", "tokenExtensions": {}, "tradersInvolved": { "JBHqRGJ9rVGzHg3DqzbFkh235kjvEiEMhBMQsU4fiAon": {} }, "programsUsed": [], "postBalances": { "JBHqRGJ9rVGzHg3DqzbFkh235kjvEiEMhBMQsU4fiAon": { "sol": 295.721913722, "DGvxoH8zEmatVbMMydMFDhsiofdgK2cFn6dPccNJ6hEg": 0.0, "So11111111111111111111111111111111111111112": 0.0 }, }, "addressLookupTables": [], "priorityFee": 0.00003, "block": 388775128, "timestamp": 1766551163729 } ``` ```json { "signature": "4j6NuFZSfXehhVVe9fw9dqwohWXUqcHVv53uGq5ypyQoh6ZhJFVworjC7EVNCJugvyayNP241ibadi4hjYbALFVi", "action": "createPool", "poolId": "JBAdtP9nYk95z44KRrb8gHffUUr4HVKkuXDKReZ5HyXg", "mint": "67BmAvfRHoxGPxbSMArCgmsLHfZnHFEhs7tiQSiXstY", "quoteMint": "So11111111111111111111111111111111111111112", "txSigner": "B2pbyEKzER21sJuKzTsAN6Ve2u6iaQ4fyS56Gf3zfRDL", "initialBuy": 0.0, "quoteAmount": 0.0, "tokensInPool": 90000000.0, "quoteInPool": 0.5, "price": 5.555555555555556e-9, "marketCapQuote": 5.555555555555556, "name": "ChilledFrogBoss", "symbol": "CFB", "uri": "https://cyan-accused-cattle-749.mypinata.cloud/ipfs/QmY5gZSVqLdm5Yy5Hq8niXWicn3amYxkM8HXN91iMieCEw", "supply": 1000000000, "poolFeeRate": 0.003, "pool": "raydium-cpmm", "poolCreatedBy": "custom", "burnedLiquidity": "0%", "decimals": 9, "mintAuthority": "B2pbyEKzER21sJuKzTsAN6Ve2u6iaQ4fyS56Gf3zfRDL", "freezeAuthority": "B2pbyEKzER21sJuKzTsAN6Ve2u6iaQ4fyS56Gf3zfRDL", "tokenProgram": "spl-token", "tokenExtensions": {}, "tradersInvolved": { "B2pbyEKzER21sJuKzTsAN6Ve2u6iaQ4fyS56Gf3zfRDL": {} }, "programsUsed": [], "postBalances": { "B2pbyEKzER21sJuKzTsAN6Ve2u6iaQ4fyS56Gf3zfRDL": { "sol": 0.270431131, "67BmAvfRHoxGPxbSMArCgmsLHfZnHFEhs7tiQSiXstY": 910000000.0, "So11111111111111111111111111111111111111112": 0.0 }, }, "addressLookupTables": ["AcL1Vo8oy1ULiavEcjSUcwfBSForXMudcZvDZy5nzJkU"], "priorityFee": 0.00002, "block": 388778410, "timestamp": 1766552453146 } ``` ```json { "signature": "1Xg2MAQ45srS1jEsimDe56cKxp6YhC2gKPq25zMgz9r11inJH8LFi7unX7443TXaGKV1FLsZvEVLyLyRN1DzsPN", "action": "createPool", "poolId": "GBbDy9g2TrqS1n39D2CbfNmaUdMtzAahbpxvDirfmznH", "mint": "GuMGpj1ATXZHfBQzdPiQCu464icCGt9b2FX9YqrqBAGS", "quoteMint": "So11111111111111111111111111111111111111112", "txSigner": "5tnydcUMvUuc3a9UqmUHdyiiHN6u6EQynsK5M76zVfHo", "initialBuy": 0.0, "quoteAmount": 0.0, "tokensInPool": 96888.172006218, "quoteInPool": 0.54154636, "price": 5.589396549855622e-6, "marketCapQuote": 5589.396393352518, "poolFeeRate": 0.5, <-- 50% fee per trade — that’s a scam. The fee can change over time; by the time you read this, it will be 10%. "supply": 999999972, "pool": "meteora-damm-v2", "poolCreatedBy": "custom", "burnedLiquidity": "0%", "minPrice": 5.421214630269582e-20, "maxPrice": 1.844605071373595e19, "decimals": 9, "mintAuthority": None, "freezeAuthority": None, "tokenProgram": "spl-token", "tokenExtensions": {}, "tradersInvolved": { "5tnydcUMvUuc3a9UqmUHdyiiHN6u6EQynsK5M76zVfHo": {} }, "programsUsed": [], "postBalances": { "5tnydcUMvUuc3a9UqmUHdyiiHN6u6EQynsK5M76zVfHo": { "sol": 2.523200098, "GuMGpj1ATXZHfBQzdPiQCu464icCGt9b2FX9YqrqBAGS": 0.0, "So11111111111111111111111111111111111111112": 0.0 }, }, "addressLookupTables": [], "priorityFee": 0.000046625, "block": 400339554, "timestamp": 1771124281945 } ``` ```json { "signature": "XZN1ooX7HiFgdMveGby78EzaXquHMZFryWBnfEQqR1gXxJv4ERyUo2x1DMqmtGZekJWNNU8Kb8G9YCQdr5MeXTX", "action": "createPool", "poolId": "9ABBHyDD8AUEMZ4kSM94ooHUYnM9wkFkpntsvzXVFT3a", "mint": "A6VCH3tPhzLVkVHKPJtQXkxtVStjYyGHe3Lodo37D8En", "quoteMint": "XsDoVfqeBukxuZHWhdvWHBhgEHjGNst4MLodqsJHzoB", "txSigner": "7D4KoVp5ra6ggwbECz19mWBsqCEMK1XbqSkpMi46M2TW", "initialBuy": 0.0, "quoteAmount": 0.0, "tokensInPool": 1e-9, "quoteInPool": 1e-9, "price": 9.98383852335128e-10, "marketCapQuote": 0.9983838523351279, "name": "Curve Doge", "symbol": "CDOGE", "uri": "https://example.com/cdoge.json", "supply": 1000000000, "quoteSupply": 229638, "poolFeeRate": 0.02, "pool": "meteora-dlmm", "decimals": 6, "mintAuthority": None, "freezeAuthority": None, "tokenProgram": "spl-token", "tokenExtensions": {}, "tradersInvolved": { "7D4KoVp5ra6ggwbECz19mWBsqCEMK1XbqSkpMi46M2TW": {} }, "programsUsed": [], "postBalances": { "7D4KoVp5ra6ggwbECz19mWBsqCEMK1XbqSkpMi46M2TW": { "sol": 0.297730779, "A6VCH3tPhzLVkVHKPJtQXkxtVStjYyGHe3Lodo37D8En": 1000000000.0, "XsDoVfqeBukxuZHWhdvWHBhgEHjGNst4MLodqsJHzoB": 0.00278233 } }, "addressLookupTables": [], "priorityFee": 0.0000653, "block": 435145919, "timestamp": 1784990526741 } ``` * Add Liquidity * Remove Liquidity - Pump AMM - Raydium CPMM - Meteora DAMM V1 - Meteora DAMM V2 - Meteora DLMM ```json { "signature": "4RcdMbUqHFCcMbZk3uCK8GyyAF5T8FtHkQq7ev1rwNvyw4W3Zr8ADkbqRBTVGGYT8EvLrYuu9WHnBznJgMYVADUm", "action": "add", "poolId": "9HQoGtkzxsjDxCNRSLbGNtGGawvB2N1QBUnxksWHMgbn", "mint": "BV2CATw6dAcxxAoZ73P14DTXzbKTUZR41X7EXpKWpump", "quoteMint": "So11111111111111111111111111111111111111112", "txSigner": "2d6xLct3G6NiJ8kpPSqvW3KGCUXxPfhLsZkpJST1jQWG", "tokenAmount": 2227444.803763, "quoteAmount": 0.166734053, "tokensInPool": 561786808.85806, "quoteInPool": 42.052216573, "price": 7.485440368113883e-8, "marketCapQuote": 74.85068094708055, "name": "GRUG", "symbol": "GRUG", "uri": "https://ipfs.io/ipfs/bafkreib4w6p74mauf7kfrkbez6w2ltfateeooqvwlrj7yq7nhpxo42dwoe", "supply": 999657834.0, "poolFeeRate": 0.0125, "pool": "pump-amm", "poolCreatedBy": "pump", "burnedLiquidity": "100%", "creatorFeeAddress": None, "mayhemMode": False, "cashbackEnabled": False, "virtualQuoteInPool": 0.0, "breakdown": [ {"action": "add", "trader": "2d6xLct3G6NiJ8kpPSqvW3KGCUXxPfhLsZkpJST1jQWG", "tokenAmount": 2227444.803763, "quoteAmount": 0.166734053} ], "decimals": 6, "mintAuthority": None, "freezeAuthority": None, "tokenProgram": "spl-token", "tokenExtensions": {}, "tradersInvolved": { "2d6xLct3G6NiJ8kpPSqvW3KGCUXxPfhLsZkpJST1jQWG": {} }, "programsUsed": [], "postBalances": { "2d6xLct3G6NiJ8kpPSqvW3KGCUXxPfhLsZkpJST1jQWG": { "sol": 0.242303832, "BV2CATw6dAcxxAoZ73P14DTXzbKTUZR41X7EXpKWpump": 0.000107, "So11111111111111111111111111111111111111112": 0.0 }, }, "addressLookupTables": [], "priorityFee": 0.0000051, "block": 388781273, "timestamp": 1766553569793 } ``` ```json { "signature": "5vg11Cwm4ajx4fgWHQKbu7PyKZj6CTktETBUmbCeVGDzWA1XE248c759b8iACXJNLBUkfH5B1gENMADg8d4D5Jbh", "action": "add", "poolId": "25oAdGCecRGkEP6xi6u9AQoXPP4qRZkLindjRZMVfpR1", "mint": "Augv5FR4mErhX8ge1aYBcos47E4D8jjMDcdggktcENp8", "quoteMint": "So11111111111111111111111111111111111111112", "txSigner": "9n54dhmAUnG2Tcdpnax4j2BDcZ1tj94uARZJekuH4hPQ", "tokenAmount": 0.00002, "quoteAmount": 0.01949851, "tokensInPool": 0.001825, "quoteInPool": 1.830396541, "price": 1002.9570087671233, "marketCapQuote": 21061094.227100823, "name": "ONLY REALTOR COIN", "symbol": "ORC", "uri": "https://ipfs.io/ipfs/QmQvMvkAgKXuCPLtA5r1cXp4N4emJPBfGe6uNtjUWpU7FE", "supply": 20999, "poolFeeRate": 0.003, "pool": "raydium-cpmm", "poolCreatedBy": "custom", "burnedLiquidity": "0%", "breakdown": [ {"action": "add", "trader": "9n54dhmAUnG2Tcdpnax4j2BDcZ1tj94uARZJekuH4hPQ", "tokenAmount": 0.00002, "quoteAmount": 0.01949851} ], "decimals": 6, "mintAuthority": None, "freezeAuthority": None, "tokenProgram": "spl-token", "tokenExtensions": {}, "tradersInvolved": { "9n54dhmAUnG2Tcdpnax4j2BDcZ1tj94uARZJekuH4hPQ": {} }, "programsUsed": [], "postBalances": { "9n54dhmAUnG2Tcdpnax4j2BDcZ1tj94uARZJekuH4hPQ": { "sol": 0.037875236, "Augv5FR4mErhX8ge1aYBcos47E4D8jjMDcdggktcENp8": 13708.133606, "So11111111111111111111111111111111111111112": 0.0 }, }, "addressLookupTables": ["AcL1Vo8oy1ULiavEcjSUcwfBSForXMudcZvDZy5nzJkU", "djNNuekoTvdeY5CfgpXxjae7KoAgNMaJx1nHt6fEPdN", "2JhxPwZXYfuRkERFmHAnM1rMHNZS5J9TpLzVadovYrb7"], "priorityFee": 0.00002, "block": 388917961, "timestamp": 1766607265405 } ``` ```json { "signature": "5E4d1U2g7m4ywzQ3sqDCHNDo6DWeZkGwEniyWtspqAwYkmKhSUVybgLmdemRKS85WMkFULomU4gjJR4xH7xGwcJ5", "action": "add", "poolId": "HSemLnpwZ3fk9iNNMPUCXs6NSQoi7y3N941ExYz9ANBq", "mint": "9223LqDuoJXyhCtvi54DUQPGS8Xf29kUEQRr7Sfhmoon", "quoteMint": "So11111111111111111111111111111111111111112", "txSigner": "GEY2VzZkkpNmwX8aRoLi74E6dR5NUaMKNTzqZ2f7wVMW", "tokenAmount": 6455.543579235, "quoteAmount": 0.863042007, "tokensInPool": 22783593.656629577, "quoteInPool": 3045.993730175, "price": 0.00013369241815321245, "marketCapQuote": 123314.52253589759, "name": "LOOK", "symbol": "LOOK", "uri": "https://moonitcdn.io/1756937273905-ow3ja.json", "supply": 922374281, "poolFeeRate": 0.01, "pool": "meteora-damm-v1", "poolCreatedBy": "custom", "burnedLiquidity": "30%", "curveType": "ConstantProduct", "breakdown": [ {"action": "add", "trader": "GEY2VzZkkpNmwX8aRoLi74E6dR5NUaMKNTzqZ2f7wVMW", "tokenAmount": 6455.543579235, "quoteAmount": 0.863042007} ], "decimals": 9, "mintAuthority": None, "freezeAuthority": None, "tokenProgram": "spl-token", "tokenExtensions": {}, "tradersInvolved": { "GEY2VzZkkpNmwX8aRoLi74E6dR5NUaMKNTzqZ2f7wVMW": {} }, "programsUsed": [], "postBalances": { "GEY2VzZkkpNmwX8aRoLi74E6dR5NUaMKNTzqZ2f7wVMW": { "sol": 0.346101101, "9223LqDuoJXyhCtvi54DUQPGS8Xf29kUEQRr7Sfhmoon": 65.207511276, "So11111111111111111111111111111111111111112": 0.0 }, }, "addressLookupTables": [], "priorityFee": 0.000246648, "block": 400338772, "timestamp": 1771123976775 } ``` ```json { "signature": "3EvVjD2h2pdk75v9HujmDmWGJc6iq1p8DeR3s3VUsvpqnVgDygBANCJDuaJRic12twnWb3Xzaqe3jbw3qrZtLUSd", "action": "add", "poolId": "gyhSWHoCF37x8hHras8Uu5xdczS76qubkQtJuxstdJe", "mint": "HbYgynsDksniFLXNa3BkCTiaEBzQMW5oty4FhTHPpump", "quoteMint": "So11111111111111111111111111111111111111112", "txSigner": "8LWBRWyhQtqNZozDWuaiYVvFEk8aY1bBVxZm3FF4ZLYy", "tokenAmount": 2706.339287, "quoteAmount": 0.188476828, "tokensInPool": 2706.339286, "quoteInPool": 0.188476827, "price": 0.00006964271936271334, "marketCapQuote": 69642.70898594815, "name": "Pepe Bismol", "symbol": "pepebismol", "uri": "https://ipfs.io/ipfs/QmVdeEDvqd2mULzo6WstotJMXMgPpcPB6vaEKk1d9oQdmC", "supply": 999840297, "poolFeeRate": 0.060820011276, "pool": "meteora-damm-v2", "poolCreatedBy": "custom", "burnedLiquidity": "0%", "minPrice": 5.421214630269583e-23, "maxPrice": 1.844605071373595e16, "breakdown": [ {"action": "add", "trader": "8LWBRWyhQtqNZozDWuaiYVvFEk8aY1bBVxZm3FF4ZLYy", "tokenAmount": 2706.339287, "quoteAmount": 0.188476828} ], "decimals": 6, "mintAuthority": None, "freezeAuthority": None, "tokenProgram": "spl-token-2022", "tokenExtensions": { "metadataPointer": {}, "tokenMetadata": {} }, "tradersInvolved": { "8LWBRWyhQtqNZozDWuaiYVvFEk8aY1bBVxZm3FF4ZLYy": {} }, "programsUsed": [], "postBalances": { "8LWBRWyhQtqNZozDWuaiYVvFEk8aY1bBVxZm3FF4ZLYy": { "sol": 0.212402626, "HbYgynsDksniFLXNa3BkCTiaEBzQMW5oty4FhTHPpump": 8739.761632, "So11111111111111111111111111111111111111112": 0.0 }, }, "addressLookupTables": [], "priorityFee": 0.0001106, "block": 400342500, "timestamp": 1771125438883 } ``` ```json { "signature": "4yGYxnUbA1Mhsa46WygJKfVwbhTJojqj2wt3T9tEdDcozxUTAAKM3gK9QKWPMvknnE4QaEB96wtcuFJ5Xhxg5Tz1", "action": "add", "poolId": "91wDPahKCJK3RmWo5p8wcN7dk828hFNgzxaoBh6rTJFX", "mint": "2vBS6D5mTPbQHChbZevmJ3Ck4uyrmdhbt1LkbyLopump", "quoteMint": "So11111111111111111111111111111111111111112", "txSigner": "8P5UA7vhuBw3Egzo2qA2TuBQzUJQeGg7QXZeEgNNQuUF", "tokenAmount": 0.0, "quoteAmount": 0.999999978, "tokensInPool": 11795677.746157, "quoteInPool": 127.98591301500001, "price": 3.9173718940446665e-6, "marketCapQuote": 3773.975183543577, "name": "The Meme Note", "symbol": "MEMENOTE", "uri": "https://metadata.j7tracker.io/metadata/VQb1smdA45.json", "supply": 963394665.0, "poolFeeRate": 0.036875, "pool": "meteora-dlmm", "binStep": 100, "breakdown": [ {"action": "add", "trader": "8P5UA7vhuBw3Egzo2qA2TuBQzUJQeGg7QXZeEgNNQuUF", "tokenAmount": 0.0, "quoteAmount": 0.999999978} ], "decimals": 6, "mintAuthority": None, "freezeAuthority": None, "tokenProgram": "spl-token-2022", "tokenExtensions": { "metadataPointer": {}, "tokenMetadata": {} }, "tradersInvolved": { "8P5UA7vhuBw3Egzo2qA2TuBQzUJQeGg7QXZeEgNNQuUF": {} }, "programsUsed": [], "postBalances": { "8P5UA7vhuBw3Egzo2qA2TuBQzUJQeGg7QXZeEgNNQuUF": { "sol": 2.764490421, "2vBS6D5mTPbQHChbZevmJ3Ck4uyrmdhbt1LkbyLopump": 0.0, "So11111111111111111111111111111111111111112": 0.0 } }, "addressLookupTables": [], "priorityFee": 0.000040258, "block": 435154256, "timestamp": 1784994035044 } ``` * Pump AMM * Raydium CPMM * Meteora DAMM V1 * Meteora DAMM V2 * Meteora DLMM ```json { "signature": "5zXxY5qU4N7DGyCri9BvFo5JncuzQEoG6nDENyMSTR3hEuyJjJu6qjxi8bpUAkjhMGEgvBBLp2oAFPbbnLsEXVmW", "action": "remove", "poolId": "CGrZd8oMudu4MUQ5f6U8yDsyy3HuRZQ3pyf8vfXQhWHw", "mint": "DjFxES1DPXMpM6T8uyGGiDSD6wNuU6PgiZo4cKCp5m1s", "quoteMint": "So11111111111111111111111111111111111111112", "txSigner": "4JC5G8UT4aS4Kp7btmcXMpDmhrE6RnFVyqMHEaqPWUh9", "tokenAmount": 719110792.99595, "quoteAmount": 118.986806369, "tokensInPool": 0.007801, "quoteInPool": 2e-9, "price": 2.5637738751442124e-7, "marketCapQuote": 256.37738751442123, "name": "Kang and Kodos", "symbol": "RIGELLIANS", "uri": "https://ipfs.io/ipfs/bafkreieunst7vs32grcfa7q2t5bgzs6vp6ld6w5i6kwvc3pnyhhpa22wtm", "supply": 1420377, "poolFeeRate": 0.003, "pool": "pump-amm", "poolCreatedBy": "custom", "burnedLiquidity": "100%", "creatorFeeAddress": None, "mayhemMode": False, "cashbackEnabled": False, "virtualTokensInPool": 0.0, "breakdown": [ {"action": "remove", "trader": "4JC5G8UT4aS4Kp7btmcXMpDmhrE6RnFVyqMHEaqPWUh9", "tokenAmount": 719110792.99595, "quoteAmount": 118.986806369} ], "decimals": 6, "mintAuthority": None, "freezeAuthority": None, "tokenProgram": "spl-token", "tokenExtensions": {}, "tradersInvolved": { "4JC5G8UT4aS4Kp7btmcXMpDmhrE6RnFVyqMHEaqPWUh9": {} }, "programsUsed": [], "postBalances": { "4JC5G8UT4aS4Kp7btmcXMpDmhrE6RnFVyqMHEaqPWUh9": { "sol": 120.07498847, "4JC5G8UT4aS4Kp7btmcXMpDmhrE6RnFVyqMHEaqPWUh9": 719110792.99595, "So11111111111111111111111111111111111111112": 0.0 }, }, "addressLookupTables": [], "priorityFee": 0.000005007, "block": 401632295, "timestamp": 1771631430774 } ``` ```json { "signature": "5xqf14tscxYzW289huZCEnLoLycva2GWgNNjzv2sdr2ef54N38GZNBT6eKTsJ7vQTthcBQRdAJ6fojjZpwzPzXNn", "action": "remove", "poolId": "5ypKmP8avEyja9L5wwBiCb7fFVNsow34BZMEutnvHCg5", "mint": "3pAFFgZDNXHxFNTKA1oQhb1xc13zvZcxHs97kSuTL6sc", "quoteMint": "So11111111111111111111111111111111111111112", "txSigner": "281oNgtPvWuDydiD53rV5x2C2pqCAjp9Y7ef2AwPCkbY", "tokenAmount": 684176482.1057463, "quoteAmount": 3.29323859, "tokensInPool": 0.001442371, "quoteInPool": 1e-9, "price": 6.933029019579567e-7, "marketCapQuote": 693.3029019579567, "name": "PRESENTS", "symbol": "PRESENTS", "uri": "https://ipfs.io/ipfs/QmRBnXwinyR9P1biQjPyE2R5NQjCPXnFdXoEFWoPG9bEzP", "supply": 925798448, "poolFeeRate": 0.003, "pool": "raydium-cpmm", "poolCreatedBy": "custom", "burnedLiquidity": "100%", "breakdown": [ {"action": "remove", "trader": "281oNgtPvWuDydiD53rV5x2C2pqCAjp9Y7ef2AwPCkbY", "tokenAmount": 684176482.1057463, "quoteAmount": 3.29323859} ], "decimals": 9, "mintAuthority": "11111111111111111111111111111111", "freezeAuthority": "11111111111111111111111111111111", "tokenProgram": "spl-token-2022", "tokenExtensions": { "metadataPointer": {}, "tokenMetadata": {} }, "tradersInvolved": { "281oNgtPvWuDydiD53rV5x2C2pqCAjp9Y7ef2AwPCkbY": {} }, "programsUsed": [], "postBalances": { "281oNgtPvWuDydiD53rV5x2C2pqCAjp9Y7ef2AwPCkbY": { "sol": 3.917406512, "3pAFFgZDNXHxFNTKA1oQhb1xc13zvZcxHs97kSuTL6sc": 784176482.105746218, "So11111111111111111111111111111111111111112": 0.0 }, }, "addressLookupTables": ["AcL1Vo8oy1ULiavEcjSUcwfBSForXMudcZvDZy5nzJkU"], "priorityFee": 0.00002, "block": 388922045, "timestamp": 1766608876866 } ``` ```json { "signature": "nbMSuM43o881zf3532dc1VwoephsPVQET7qHWbtVkKsvUf8MPsnKmxGZXYvJv8eJWV2ri3GbnZw9XNdVybZ2ghP", "action": "remove", "poolId": "4uaMaLTZzDu6sS6HrpeqJzyRNEJg8pEA4JsrhFijkE4T", "mint": "8tsjtkX1W1S8HgTGfZcgT89KSbwsvKunuGsgjbyLrzVY", "quoteMint": "So11111111111111111111111111111111111111112", "txSigner": "7XrX7jF4zzkKQDaDsbuC3pj83JDzRY3RPZk3yWvU5s82", "tokenAmount": 1745042.086581, "quoteAmount": 13.04651297, "tokensInPool": 2036334.162997, "quoteInPool": 0.171096754, "price": 8.402194350468797e-8, "marketCapQuote": 84.02194350468797, "name": "App Orbit Sprint", "symbol": "PORTALA", "uri": "https://static-create.jup.ag/metadata/GmFjDjN7JJvNAi5Q2ZEd76y8zf8Mp93xrai9wLmJjups.json", "supply": 999999999, "poolFeeRate": 0.0025, "pool": "meteora-damm-v1", "poolCreatedBy": "meteora-launchpad", "burnedLiquidity": "0%", "curveType": "ConstantProduct", "breakdown": [ {"action": "remove", "trader": "7XrX7jF4zzkKQDaDsbuC3pj83JDzRY3RPZk3yWvU5s82", "tokenAmount": 1745042.086581, "quoteAmount": 13.04651297} ], "decimals": 6, "mintAuthority": None, "freezeAuthority": None, "tokenProgram": "spl-token", "tokenExtensions": {}, "tradersInvolved": { "7XrX7jF4zzkKQDaDsbuC3pj83JDzRY3RPZk3yWvU5s82": {} }, "programsUsed": [], "postBalances": { "7XrX7jF4zzkKQDaDsbuC3pj83JDzRY3RPZk3yWvU5s82": { "sol": 114.520711111, "8tsjtkX1W1S8HgTGfZcgT89KSbwsvKunuGsgjbyLrzVY": 51032.333456, "So11111111111111111111111111111111111111112": 14.533922452 }, }, "addressLookupTables": ["Gfjt2PyyG3QN6MBcdd1FMAMLuy8irQHdsvXNsL4vifeV"], "priorityFee": 0.000545, "block": 400340374, "timestamp": 1771124606807 } ``` ```json { "signature": "hGJg8XvEhZD5f58Ax3yRhnXsHKkdzvTK5LjtKA4dGYAbqhATukV1rArPHSPDkUMJoDzKvzF25zky9o36iUn6wnC", "action": "remove", "poolId": "tGTx97Xrp8tEgsK3nWBujLPB6T4DgMEtMaCaUs2fiha", "mint": "3VrfrhvXwD8XuDCDc6X9uPTHBsXw1teQdid2jY8wpump", "quoteMint": "So11111111111111111111111111111111111111112", "txSigner": "2YKdzgVQi4eZ5tE8RYr545TAwtnNPCP2mfrERAV36Y1g", "tokenAmount": 3326528.497957, "quoteAmount": 14.551444434, "tokensInPool": 990369614.27755, "quoteInPool": 0.000603407, "price": 6.092811216043966e-13, "marketCapQuote": 0.0006092811216043966, "name": "Dollar", "symbol": "Dollar", "uri": "https://ipfs.io/ipfs/bafkreidgjleag62to6kggaykcqbu6bz3rgwalrxoe5yvdmjccpfopusbzq", "supply": 974974136, "poolFeeRate": 0.001, "pool": "meteora-damm-v2", "poolCreatedBy": "meteora-launchpad", "burnedLiquidity": "10%", "minPrice": 5.421214630269583e-23, "maxPrice": 1.844605071373595e16, "breakdown": [ {"action": "remove", "trader": "2YKdzgVQi4eZ5tE8RYr545TAwtnNPCP2mfrERAV36Y1g", "tokenAmount": 3326528.497957, "quoteAmount": 14.551444434} ], "decimals": 6, "mintAuthority": None, "freezeAuthority": None, "tokenProgram": "spl-token", "tokenExtensions": {}, "tradersInvolved": { "2YKdzgVQi4eZ5tE8RYr545TAwtnNPCP2mfrERAV36Y1g": {} }, "programsUsed": [], "postBalances": { "2YKdzgVQi4eZ5tE8RYr545TAwtnNPCP2mfrERAV36Y1g": { "sol": 96.909165946, "3VrfrhvXwD8XuDCDc6X9uPTHBsXw1teQdid2jY8wpump": 3327058.086698, "So11111111111111111111111111111111111111112": 0.0 }, }, "addressLookupTables": [], "priorityFee": 0.00001, "block": 400343275, "timestamp": 1771125739619 } ``` ```json { "signature": "4PQRQuu4AjbN3A2k4AtrXJBXyXkk62ieMDYJMu3arYv9iU7Gyc29XZUsZvEWzWiUa9FcFj1KFL5GRzKBASSeV2uF", "action": "remove", "poolId": "4bwdKNcrYbXHXR3TT7c7c2HDCj19C5ioUALF3j415dTN", "mint": "8gEtFeKeRt1QREkU51dRih9pQ39PyYpRRZTyLg2v5qFn", "quoteMint": "So11111111111111111111111111111111111111112", "txSigner": "GZ3d73ZHedK8fNDZozuEontUKq4EdEEYpeSMYXkDj1zx", "tokenAmount": 0.0, "quoteAmount": 0.623748125, "tokensInPool": 4464843.892727001, "quoteInPool": 137.59838746599996, "price": 7.861238417350486e-6, "marketCapQuote": 7507.438846443061, "name": "sharkdog", "symbol": "sharkdog", "uri": "https://ipfs.io/ipfs/bafkreiehic3i2doymbl7favt5akmshf3nhanlrzpoj6vmr2ubi6njo5pge", "supply": 954994423, "poolFeeRate": 0.036875, "pool": "meteora-dlmm", "binStep": 100, "breakdown": [ {"action": "remove", "trader": "GZ3d73ZHedK8fNDZozuEontUKq4EdEEYpeSMYXkDj1zx", "tokenAmount": 0.0, "quoteAmount": 0.623748125} ], "decimals": 6, "mintAuthority": None, "freezeAuthority": None, "tokenProgram": "spl-token-2022", "tokenExtensions": { "metadataPointer": {}, "tokenMetadata": {} }, "tradersInvolved": { "GZ3d73ZHedK8fNDZozuEontUKq4EdEEYpeSMYXkDj1zx": {} }, "programsUsed": [], "postBalances": { "GZ3d73ZHedK8fNDZozuEontUKq4EdEEYpeSMYXkDj1zx": { "sol": 14.567183534, "8gEtFeKeRt1QREkU51dRih9pQ39PyYpRRZTyLg2v5qFn": 30.61083, "So11111111111111111111111111111111111111112": 0.0 } }, "addressLookupTables": [], "priorityFee": 0.000054716, "block": 435170048, "timestamp": 1785000656862 } ``` * Claim Creator Fees - Pump.fun - Pump AMM ```json { "signature": "DHPuXjYK1GkWrC4DL7VNJDAvKM3AeQBafvG6rNCN5hnwtsaCfGvfitbcN9ieio6pYJvyjYG18d9SWEh698fH2hL", "action": "claimCreatorFees", "txSigner": "2bBRwhGoL4fRZk6g8NnhBZywsF8PdLJnBRfWDCEMogD2", "creatorFeeAddress": "2bBRwhGoL4fRZk6g8NnhBZywsF8PdLJnBRfWDCEMogD2", "feeMint": "sol", "feeAmount": 0.336336529, "pool": "pump", "programsUsed": [], "postBalances": { "2bBRwhGoL4fRZk6g8NnhBZywsF8PdLJnBRfWDCEMogD2": { "sol": 33.278186291 } }, "addressLookupTables": [], "priorityFee": 0.000011945, "block": 417521072, "timestamp": 1777893368907 } ``` ```json { "signature": "5A2caPgeDL1kJLrVtHeGvsZNL96CpX3XcivtCxso3LQp3iByCD36a5XBrG7NZuU7QaLiNV2qCuHvgEzYWFZsRbLP", "action": "claimCreatorFees", "txSigner": "BVuZyaJWoyPDVY6o4q1xs5tm7tDwbsUKQvfnWWaLWV56", "creatorFeeAddress": "BVuZyaJWoyPDVY6o4q1xs5tm7tDwbsUKQvfnWWaLWV56", "feeMint": "wsol", "feeAmount": 0.000651625, "pool": "pump-amm", "programsUsed": [], "postBalances": { "BVuZyaJWoyPDVY6o4q1xs5tm7tDwbsUKQvfnWWaLWV56": { "sol": 0.056120066, "So11111111111111111111111111111111111111112": 0.0 } }, "addressLookupTables": [], "priorityFee": 0.000155, "block": 417521010, "timestamp": 1777893345050 } ``` **How the stream works** 📨 The stream sends **events, not transactions**. A single transaction can produce many events (buys in different pools, transfers, a token creation, etc.) that all share the **same `signature`**. If you skip a signature you've already seen, you will drop most events. 🧮 Trades and liquidity changes arrive **aggregated**. If one transaction has a 5 SOL buy and a 4 SOL sell in the same pool, you receive a single `buy` event for 1 SOL. Need them separately? Read `breakdown` — it is always there and lists every trade with its own `trader` and amounts. 📑 Events of one transaction always arrive in this fixed order: **transfers → trades → liquidity changes (`add`/`remove`) → claim cashback**. #### Glossary[​](#glossary "Direct link to Glossary") | Field | Description | | ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `signature` | Transaction signature on the Solana blockchain. | | `action` | Event type — one of `transfer`, `create`, `buy`, `sell`, `migrate`, `createPool`, `add`, `remove`, `claimCashback` etc. 1 transaction can produce multiple events | | `poolId` | is the unique pool address. By using it, you can see the pool reserves. Tip 1: You can get the Solana price without any external API. Just check if poolId equals Gf7sXMoP8iRw4iiXmJ1nq4vxcRycbGXy5RL8a8LnTd3v. This is the largest SOL–USDC pool on pump-amm, so you can read the Solana price from it. Tip 2: You can pass this address to the trade API using 'poolId': 'address' to trade a token from a specific pool. This is useful for arbitrage. If you do not pass this parameter, we automatically choose the best pool. This means you can even trade USDC at the best price using our trading API, without visiting any websites. | | `mint` | Token mint address. | | `quoteMint` | The second token used in the trade. For example, in some pools you can buy a token only with USDC, USDT, or another token. Usually, it's the WSOL Address Sol11...2 | | `txSigner` | The public key of the account that sent the transaction and paid the priorityFee. Important: if you build a copy trader or something similar, use tradersInvolved, not txSigner. This is because sometimes traders send a transaction where txSigner is a different account, but the trade uses funds from the account you track. In this case, the account you track will be in the tradersInvolved dictionary. | | `tokenAmount` | Amount of `mint` tokens involved in the transaction. If the transaction contains several trades in this pool, this is their total - see `breakdown` field for each trade separately. | | `quoteAmount` | The amount of the `quoteMint` token (usually WSOL or USDC) involved in the transaction. If the transaction contains several trades in this pool, this is their total - see `breakdown` field for each trade separately. | | `tokensInPool` | Total amount of the main token (mint) currently in the liquidity pool. This shows how many tokens are available for trading on the token side. | | `quoteInPool` | Total amount of the quote token (quoteMint) locked in the liquidity pool. This field is present only when the quote token is NOT SOL (e.g. USDC, USDT). It represents liquidity on the quote side. | | `vTokensInBondingCurve` | Virtual token reserves in the bonding curve pool. Reflects liquidity available on the token side. This field is present only when the pool is `pump` or `raydium-launchpad`. | | `vQuoteInBondingCurve` | Virtual Quote reserves in the bonding curve pool. Reflects liquidity available on the Quote side. This field is present only when the pool is `pump` or `raydium-launchpad` | | `virtualQuoteInPool` | Present only in `pump-amm` pools. Shows the amount of virtual liquidity reserved for buybacks during the first 5 minutes after migration. The value is always around 17 SOL. | | `virtualTokensInPool` | Present only in `pump-amm` pools. The same as `virtualQuoteInPool`, but for reversed pools, where WSOL or a stablecoin is the base token. You can safely ignore this field — it is always `0.0`. | | `price` | Price in quoteMint (usually SOL) including this transaction’s impact. | | `marketCapQuote` | Market capitalization in Quote token (usually Solana, USDC, USDT) | | `pool` | Liquidity source. Before migration, the value is either `pump` or `raydium-launchpad`. After migration, `pump` → `pump-amm`, `raydium-launchpad` → `raydium-cpmm`, `meteora-launchpad` → `meteora-damm-v1`/ `meteora-damm-v2`. | | minPrice | Available only in Meteora DAMM V2. Indicates the minimum price configured for the pool. | | maxPrice | Available only in Meteora DAMM V2. Indicates the maximum price configured for the pool. | | curveType | Present only in Meteora DAMM V1. Indicates the formula used for price calculation. Can be `constantProduct` (the most common one, based on the quote-reserve/base-reserve ratio) or `StableSwap` (ideal for stablecoin-to-stablecoin pools, keeping the price close to 1:1 even when reserves differ). | | `binStep` | Present only in Meteora DLMM. The price step between adjacent bins, in basis points (e.g. `400` means each bin is 4% apart, `1` means 0.01%). In DLMM liquidity is not spread along a curve — it sits in discrete price bins, and only the bins near the current price are tradable at any moment. A larger `binStep` means coarser price granularity and a wider spread. Important: unlike constant-product pools, `tokensInPool` and `quoteInPool` here are the **totals across all bins**, so a DLMM pool can show large reserves while still giving heavy slippage on a small trade — the liquidity may sit in bins far from the current price. | | poolFeeRate | Indicates the current fee rate in the pool. Can range from 0 to 1, where 0.1 represents 10% and 0.001 represents 1%. | | `poolCreatedBy` | indicates who created the pool on pump-amm, raydium-cpmm, meteora-damm-v1, or meteora-damm-v2. If the pool was created by migration, the value is `pump`, `raydium-launchpad`, or `meteora-launchpad`. Pools migrated from pump and raydium-launchpad are considered trusted, but pools migrated from meteora-launchpad can be risky because Meteora allows config creators to choose how much liquidity share the pool creator receives after migration. Always check `lockedLiquidityAfterMigration` before relying on such pools. If the pool was created manually, the value is `custom`. Be cautious with these pools as well. | | `lockedLiquidityAfterMigration` | Present only in Meteora Launchpad. Shows what percentage of liquidity will be locked after migration. Beware of values below 100%, as the pool or launchpad creator can withdraw the liquidity after the migration (rug pull). | | `poolFeeRateAfterMigration` | Present only in Meteora Launchpad. Indicates what the poolFeeRate will be after migration. Meteora Launchpad allows values up to 0.1 (10%) | | `migrationThresholds` | Present only in Meteora Launchpad and Raydium Launchpad. Indicates the required `quoteInPool` or `tokensInPool` value for a migration to occur. Pump.fun always uses a fixed requirement of 85 SOL. | | `burnedLiquidity` | shows what percent of liquidity is burned (for example, `"99%"`). Liquidity means someone adds Solana (or another quote token) and tokens into the pool. Normally, liquidity providers earn fees from trades and can withdraw their share at any time. If one person owns 100% of the liquidity, they can withdraw 100% and drain the pool, even after others buy the token. Pools with 0% burned liquidity are very risky because the owner can rug pull, and you will not be able to sell the token. Launchpads like pump.fun and partly raydium-launchpad burn the right to withdraw liquidity after migration. So if a pool has 20–30% or more burned liquidity, it is a good sign, because this part will always stay in the pool for trading. | | `cashbackEnabled` | indicates whether you are accumulating cashback for trading in this pool. Such pools exist on pump.fun and pumpswap. To claim your accumulated cashback, call [claimCashback](/claim-cashback.md) | | `creatorFeeAddress` | It shows the address that receives the creator fees on pump.fun and pumpSwap if `cashbackEnabled` is `False`. Important: this address can change, since the real token creator has the right to modify it. Often, this address is the same as the one that originally created the token. The value may be `None` because not all pools have creator fees enabled. | | `feeMint` | Present only for `claimCreatorFees` events. Shows the token in which the fees were accumulated. For `pump.fun`, this is always `sol`. For `pump-amm`, this is usually `wsol`, but in rare custom pools it can be another token. | | `feeAmount` | Present only for `claimCreatorFees` events. Shows the amount of accumulated fees that was claimed. | | `mayhemMode` | Indicates whether “mayhem mode” is active for `pump` or `pump-amm` pools. `true` means mayhem mode is on, `false` means it’s off. (Other pool types don’t have this field.). Usually, you should avoid `mayhemMode` == `True`, because this means that pump.fun’s AI agent receives 1 billion tokens. If it sells before you, you will no longer be able to sell and may encounter a 6024 Overflow error. In such a case, try to sell as much as you can, then call our burn method with 100% to burn all remaining tokens and receive a rent fee refund (0.002 SOL). | | `launchpadConfig` | The address where the settings for the Meteora or Raydium launchpad are stored. Anyone can create their own config on these launchpad. | | `breakdown` | The same event split into individual trades, without aggregation. One transaction can contain several trades in the same pool (for example a bundle, where many wallets buy in one transaction). Top-level `tokenAmount` and `quoteAmount` are the sum of all of them, and `breakdown` shows each one separately: `action`, `trader`, `tokenAmount`, `quoteAmount`. | | `mintAuthority` | Address that has permission to mint new tokens. This **must always be `None`** — otherwise it’s a red flag for a potential *scam*. Only stablecoins usually have a non-`None` value. [More info](/tutorials/detect_scam_tokens.md) | | `freezeAuthority` | Address that can freeze token accounts. This **must always be `None`** — a non-`None` value can indicate a *honeypot* or *scam*. Only stablecoins may have this set for regulatory reasons. [More info](/tutorials/detect_scam_tokens.md) | | `tokenProgram` | Token program used to create the token — either `spl-token` (legacy) or `spl-token-2022` (newer standard). [More info](/tutorials/detect_scam_tokens.md) | | `tokenExtensions` | Token extensions are only present in `spl-token-2022` tokens. Be cautious — some extensions can be used by scammers! (This does **not** apply to tokens from pump.fun, Bonk, or other trusted launchpads.) Check our [guide](/tutorials/detect_scam_tokens.md) to learn which extensions are safe. | | `tradersInvolved` | Addresses that **actually executed the trade** (spent funds). This field is critical for copy trading and analytics. A transaction may be **signed and paid for** by one address (`txSigner`), while the **trade itself is executed** using funds from another address. In such cases, `txSigner` shows the fee-payer, but `tradersInvolved` contains the real trader. Always track accounts by `tradersInvolved`, not `txSigner`, or you may miss trades. [Visualization](https://prnt.sc/0y5d2_tMLucE) | | `programsUsed` | Programs the action was called through, for example a router or an aggregator like Jupiter. Each event has its own list. `[]` | | `addressLookupTables` | Address Lookup Tables (ALTs) are used to include more accounts than the transaction limit allows by referencing account indices within the tables. We send a list of the ALTs used. | | `postBalances` | Shows SOL and token balances of accounts involved in the transaction. Includes: the `txSigner`, all `tradersInvolved`, and — in the case of SOL transfers — both the sender and the receiver. In the case of token transfers, the SOL balance of the account that received the tokens is **not** included. | | `type` | Present in certain transfer and `claimCreatorFees` events. For transfer events, it indicates which method was used to perform the transfer, for example `token_account_closure` or `withdraw_from_nonce`. For `claimCreatorFees` events, it indicates the type of creator fee claim. The value can be `social`; for default creator fee claims, this field is absent. | | `isSolana` | Only in transfer events. Indicates whether the `mint` represents Solana. `True` if the mint is **native SOL** or **WSOL (Wrapped SOL)**; otherwise `False`. | | `priorityFee` | Shows how much was paid to send this transaction. Minimum is 0.000005 SOL (base network fee) plus an additional tip to increase the likelihood that a validator includes the transaction. | | `block` | Block number in which the transaction was included. New blocks are produced every 400 ms | | `timestamp` | Blockchain timestamp of transaction. | --- ## Trade Api ### Buy and Sell – API Use this to buy and sell tokens.
**Supported pools** * `Pump.fun` * `Raydium LaunchPad (including bonk)` * `Meteora LaunchPad (including Bags.fm, moonshot)` * `PumpSwap` * `Raydium CPMM` * `Meteora DAMM V1` * `Meteora DAMM V2` * `Meteora DLMM` #### Endpoint[​](#endpoint "Direct link to Endpoint") `POST https://api.pumpapi.io` * Lightning transactions⚡ (EASIER AND FASTER) * Local transactions (No private key required) #### ⚡ Lightning Transaction[​](#-lightning-transaction "Direct link to ⚡ Lightning Transaction") **Lightning transaction** is a method of sending transactions where we broadcast the transaction on your behalf.
This approach allows for: * 🚀 **Maximum transaction speed** * 🧩 **Minimal code complexity** By handling the transaction process internally, you don’t have to construct the transaction manually — we do it for you. > To use this feature, simply provide a wallet `privateKey` — it’s needed to sign and broadcast the transaction on your behalf. **🔑 Don't want to send your private key? Use `apiKey` instead (optional)** **This step is completely optional** — it's only for users who prefer not to send their private key over the network. An `apiKey` is an AES-256 encrypted form of your wallet's private key. Generate it once below, then simply pass `apiKey` instead of `privateKey` in **any** API request — everything else stays exactly the same. Create Wallet I want to use my own private key * Python * JavaScript * Rust * Go ```python import requests response = requests.post("https://wallet.pumpapi.io", json={ # "privateKey": "base58_private_key", # uncomment if you want to get an apiKey for your existing private key }) print(response.json()) # {"apiKey": "...", "publicKey": "...", "privateKey": "..."} ``` ```javascript import axios from 'axios'; axios.post('https://wallet.pumpapi.io', { // privateKey: "base58_private_key", // uncomment if you want to get an apiKey for your existing private key }) .then(response => console.log(response.data)) // { apiKey, publicKey, privateKey } .catch(error => console.error(error)); ``` ```rust use reqwest::Client; use serde_json::json; #[tokio::main] async fn main() -> Result<(), Box> { let client = Client::new(); let res = client.post("https://wallet.pumpapi.io") .json(&json!({ // "privateKey": "base58_private_key" // uncomment if you want to get an apiKey for your existing private key })) .send() .await? .text() .await?; println!("{}", res); // {"apiKey": "...", "publicKey": "...", "privateKey": "..."} Ok(()) } ``` ```go package main import ( "bytes" "encoding/json" "fmt" "net/http" ) func main() { data := map[string]interface{}{ // "privateKey": "base58_private_key", // uncomment if you want to get an apiKey for your existing private key } jsonData, _ := json.Marshal(data) resp, err := http.Post("https://wallet.pumpapi.io", "application/json", bytes.NewBuffer(jsonData)) if err != nil { panic(err) } defer resp.Body.Close() var result map[string]interface{} json.NewDecoder(resp.Body).Decode(&result) fmt.Println(result) // apiKey, publicKey, privateKey } ``` #### Request Body[​](#request-body "Direct link to Request Body") | Field | Description | | ------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `privateKey` | **Not required if `apiKey` is provided.** Private key in Base58 format. | | `apiKey` | **Not required if `privateKey` is provided.** Encrypted alternative to `privateKey` — pass it instead if you don't want to send a raw private key. All other fields and behavior stay exactly the same. Generate one in the spoiler above. | | `action` | `"buy"` or `"sell"` | | `mint` | Mint address of the token | | `quoteMint` | **Optional. Not required.** Use this only when you want to limit pool selection to pools where `mint` is paired with a specific quote token. If you do not provide `quoteMint`, we automatically choose the best available pool for `mint`; the quote token of that selected pool will be spent when buying or received when selling. | | `poolId` | **Optional. Not required.** provide this if you need to trade token from the specific pool. | | `amount` | Amount to trade. Use `'100%'` to sell all and get a 0.002 sol refund from the network | | `denominatedInQuote` | `"true"` if amount is in SOL (or any other quote token), `"false"` for token amount | | `slippage` | Slippage in percent (recommended: 20) | | `maxQuoteAmountIn`
`minBaseAmountOut`
`maxBaseAmountIn`
`minQuoteAmountOut` | **Optional. Not required.** Pre-calculate exact bounds and pass them directly. Unlike `slippage` (a percent applied to the current market price — so if the price shifts before your tx lands, your effective bounds shift with it), these fields are absolute values that stay exactly as you set them. Useful when the price may move between your decision and your tx landing on-chain. **Buy:** `maxQuoteAmountIn` (max quote spent), `minBaseAmountOut` (min tokens received). **Sell:** `maxBaseAmountIn` (max tokens spent), `minQuoteAmountOut` (min quote received). `slippage` must always be present in the request: if you provide only one of the two fields, the other is derived from `slippage`; if you provide both, `slippage` is not used but still required. We recommend providing both fields. | | `priorityFee` | **Optional. Not required.** Extra fee (in SOL) to speed up your transaction and increase its chance it lands in the current block.

There are two modes of operation:

**1️⃣ Automatic Jito split (≥ 0.00023 SOL):**
If the value is **0.00023 SOL or higher**, PumpAPI automatically splits it:
• **90% → `jitoTip`** (used by ~90% of validators)
• **10% → `priorityFee`** (for non-Jito validators)

**2️⃣ No split (< 0.00023 SOL):**
If the value is **less than 0.00023 SOL**, *no split occurs*. The full amount is treated as `priorityFee`, and the transaction is sent via **SWQOS** (fast non-Jito route). | | `jitoTip` | Optional. Use this if you don’t want automatic priorityFee split.
Example: `'jitoTip': 0.0002`.
Minimum required to join Jito auction: **0.0002 SOL**. Anything below that is ignored, and the transaction is sent without Jito participation. When `jitoTip` is provided, your entire `priorityFee` remains intact (not split). | | `cuLimit` | **Optional. Not required.** Compute units limit for the transaction. By default we set the lowest value that still lets 100% of transactions succeed. A lower value gives your transaction higher priority, but increases the risk it fails with "exceeded CUs limit". | | `guaranteedDelivery` | **Optional experimental feature** `"true"` tells the server to rebroadcast the transaction for up to 10 seconds and respond with `confirmed: true` if it appears on-chain within that time. Otherwise, you receive `confirmed: false`. ⚠️ This affects response time: if you want an immediate reply (without confirmation of success), set this to false! | | `partnerAddress` | Optional. Run your own service and want to receive a fee from your users? Set this field. The fee defined in `partnerFeeRatio` + `partnerFeeFixed` will be sent to this address.
You can also use it if your strategy requires sending funds somewhere after the operation. | | `partnerFeeRatio` | Optional. Percentage of the trade you want to send to `partnerAddress`. Example: `0.005` = 0.5%, `0.01` = 1%. | | `partnerFeeFixed` | Optional. A fixed amount (in SOL) you want to send to `partnerAddress` for the operation. Example: `0.0001`. | | `mintRef` | Optional. When using Jito Bundles or Actions and creating tokens, you don’t yet know the token address assigned to you (unless you provide mintPrivateKey). To handle this, within a single request you can set "mintRef": "any value" (the default is "0") and reuse it across related transactions inside the same Jito Bundle or Actions. When buying the token, specify "mintRef": "the value you set earlier", and the backend will understand which token you’re referring to. Works within a single request; a second request requires providing the mint address. | *** * Python * JavaScript * Rust * Go ```python import requests url = "https://api.pumpapi.io" data = { "privateKey": "base58_private_key", # or pass "apiKey": "your_api_key" instead — see the 🔑 spoiler above "action": "buy", "mint": "token_address", "amount": 0.01, "denominatedInQuote": "true", "slippage": 20, "priorityFee": 0.0001, } response = requests.post(url, json=data) print(response.json()) ``` ```javascript import axios from 'axios'; const data = { privateKey: "base58_private_key", // or pass "apiKey": "your_api_key" instead — see the 🔑 spoiler above action: "buy", mint: "token_address", amount: 0.01, denominatedInQuote: "true", slippage: 20, priorityFee: 0.0001 }; axios.post('https://api.pumpapi.io', data) .then(response => console.log(response.data)) .catch(error => console.error(error)); ``` ```rust use reqwest::Client; use serde_json::json; #[tokio::main] async fn main() -> Result<(), Box> { let client = Client::new(); let res = client.post("https://api.pumpapi.io") .json(&json!({ "privateKey": "base58_private_key", // or pass "apiKey": "your_api_key" instead — see the 🔑 spoiler above "action": "buy", "mint": "token_address", "amount": 0.01, "denominatedInQuote": "true", "slippage": 20, "priorityFee": 0.0001 })) .send() .await? .text() .await?; println!("{}", res); Ok(()) } ``` ```go package main import ( "bytes" "encoding/json" "fmt" "net/http" ) func main() { data := map[string]interface{}{ "privateKey": "base58_private_key", // or pass "apiKey": "your_api_key" instead — see the 🔑 spoiler above "action": "buy", "mint": "token_address", "amount": 0.01, "denominatedInQuote": "true", "slippage": 20, "priorityFee": 0.0001, } jsonData, _ := json.Marshal(data) resp, err := http.Post("https://api.pumpapi.io", "application/json", bytes.NewBuffer(jsonData)) if err != nil { panic(err) } defer resp.Body.Close() var result map[string]interface{} json.NewDecoder(resp.Body).Decode(&result) fmt.Println(result) } ``` *** #### Response Format[​](#response-format "Direct link to Response Format") | Request type | Response | | ------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Single transaction** | `{"signature": "...", "err": "", "timestamp": "timestamp_ms"}, 'trades': [{'poolId': 'pool_id_used', 'mint': 'mint_address_used', 'quoteMint': 'quote_mint_address_used', 'pool': 'name_of_the_amm'}]` | | **[Jito Bundle](/jito-bundles.md)** (up to 5 txs) | `{"signatures": ["...", "..."], "err": "", "timestamp": "timestamp_ms", "bundleUUIDs": ["bundle_uuid]}, 'trades': [{'poolId': 'pool_id_used', 'mint': 'mint_address_used', 'quoteMint': 'quote_mint_address_used', 'pool': 'name_of_the_amm'}]` | `err` is an **empty string `""` on success**, or the error message on failure. Extra fields may appear depending on the action (e.g. `createdMints` when creating tokens). *** #### How Local Transactions Work[​](#how-local-transactions-work "Direct link to How Local Transactions Work") Local transactions keep your private key **100% on your machine**. The flow is: 1. You send us a request with only your `publicKey` (no private key). 2. Our server builds the transaction and returns it to you **unsigned**, as raw bytes. 3. You sign the transaction locally on your machine. 4. You broadcast it to the Solana network yourself (via any RPC). This method is for: 1. **Web app builders** — your users sign transactions themselves via wallet extensions (Phantom, Solflare, Backpack…). Request an unsigned transaction from us with the user's `publicKey`, pass it to the wallet extension for signing, then broadcast it. 2. Users who prioritize **key security** over speed and simplicity — your private key never leaves your machine. If neither applies to you and you want the **fastest and simplest** path — where we sign and broadcast on your behalf — switch to the **⚡ Lightning transactions** tab above (recommended). *** #### Request Body[​](#request-body-1 "Direct link to Request Body") | Field | Description | | ------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `publicKey` | Your public key (the wallet address) | | `action` | `"buy"` or `"sell"` | | `mint` | Mint address of the token | | `quoteMint` | **Optional. Not required.** Use this only when you want to limit pool selection to pools where `mint` is paired with a specific quote token. If you do not provide `quoteMint`, we automatically choose the best available pool for `mint`; the quote token of that selected pool will be spent when buying or received when selling. | | `poolId` | **Optional. Not required.** provide this if you need to trade token from the specific pool. | | `amount` | Amount to trade. Use `'100%'` to sell all and get a 0.002 sol refund from the network | | `denominatedInQuote` | `"true"` if amount is in SOL (or any other quote token), `"false"` for token amount | | `slippage` | Slippage in percent (recommended: 20) | | `maxQuoteAmountIn`
`minBaseAmountOut`
`maxBaseAmountIn`
`minQuoteAmountOut` | **Optional. Not required.** Pre-calculate exact bounds and pass them directly. Unlike `slippage` (a percent applied to the current market price — so if the price shifts before your tx lands, your effective bounds shift with it), these fields are absolute values that stay exactly as you set them. Useful when the price may move between your decision and your tx landing on-chain. **Buy:** `maxQuoteAmountIn` (max quote spent), `minBaseAmountOut` (min tokens received). **Sell:** `maxBaseAmountIn` (max tokens spent), `minQuoteAmountOut` (min quote received). `slippage` must always be present in the request: if you provide only one of the two fields, the other is derived from `slippage`; if you provide both, `slippage` is not used but still required. We recommend providing both fields. | | `priorityFee` | **Optional. Not required.** Priority fee in SOL | | `cuLimit` | **Optional. Not required.** Compute units limit for the transaction. By default we set the lowest value that still lets 100% of transactions succeed. A lower value gives your transaction higher priority, but increases the risk it fails with "exceeded CUs limit". | | `partnerAddress` | Optional. Run your own service and want to receive a fee from your users? Set this field. The fee defined in `partnerFeeRatio` + `partnerFeeFixed` will be sent to this address.
You can also use it if your strategy requires sending funds somewhere after the operation. | | `partnerFeeRatio` | Optional. Percentage of the trade you want to send to `partnerAddress`. Example: `0.005` = 0.5%, `0.01` = 1%. | | `partnerFeeFixed` | Optional. A fixed amount (in SOL) you want to send to `partnerAddress` for the operation. Example: `0.0001`. | | `mintRef` | Optional. When using Jito Bundles or Actions and creating tokens, you don’t yet know the token address assigned to you (unless you provide mintPrivateKey). To handle this, within a single request you can set "mintRef": "any value" (the default is "0") and reuse it across related transactions inside the same Jito Bundle or Actions. When buying the token, specify "mintRef": "the value you set earlier", and the backend will understand which token you’re referring to. Works within a single request; a second request requires providing the mint address. | *** * Python * JavaScript * Rust * Go ```python import requests from solders.transaction import VersionedTransaction from solders.keypair import Keypair from solders.message import to_bytes_versioned from solders.commitment_config import CommitmentLevel from solders.rpc.requests import SendVersionedTransaction from solders.rpc.config import RpcSendTransactionConfig import base64 response = requests.post(url="https://api.pumpapi.io", json={ "publicKey": "your_public_key", "action": "buy", # or sell "mint": "token_address", "amount": 0.01, # When you're selling, you can pass "100%" to sell everything "denominatedInQuote": "true", "slippage": 20, "priorityFee": 0.0001, }) keypairs = [ Keypair.from_base58_string("base58_private_key_1"), # stays on your computer # Keypair.from_base58_string("base58_private_key_2"), # If you are using actions or jito bundles, add all private keys involved in the transaction here. ] try: # jito bundle branch (multiple transactions) b64_txs = response.json() txs = [] all_signatures = [] for base64_encoded_tx in b64_txs: tx = VersionedTransaction.from_bytes(base64.b64decode(base64_encoded_tx)) required_signers = list(tx.message.account_keys)[:tx.message.header.num_required_signatures] signatures = list(tx.signatures) for keypair in keypairs: if keypair.pubkey() not in required_signers: continue signer_index = required_signers.index(keypair.pubkey()) signatures[signer_index] = keypair.sign_message(to_bytes_versioned(tx.message)) tx = VersionedTransaction.populate(tx.message, signatures) all_signatures.append(tx.signatures[0]) txs.append(base64.b64encode(bytes(tx)).decode("ascii")) jito_response = requests.post( "https://mainnet.block-engine.jito.wtf:443/api/v1/bundles?uuid=PLACE_YOUR_UUID_HERE_TO_USE_JITO_BUNDLES", # if you want to send multiple txs via Jito bundles get your UUID here: https://discord.com/invite/jito , without a UUID it won't land headers={"Content-Type": "application/json"}, json={ "jsonrpc": "2.0", "id": 1, "method": "sendBundle", "params": [txs, {"encoding": "base64"}] } ) print(jito_response.content) print(all_signatures) except requests.exceptions.JSONDecodeError: # single tx branch tx = VersionedTransaction.from_bytes(response.content) required_signers = list(tx.message.account_keys)[:tx.message.header.num_required_signatures] signatures = list(tx.signatures) for keypair in keypairs: if keypair.pubkey() not in required_signers: continue signer_index = required_signers.index(keypair.pubkey()) signatures[signer_index] = keypair.sign_message(to_bytes_versioned(tx.message)) tx = VersionedTransaction.populate(tx.message, signatures) commitment = CommitmentLevel.Confirmed config = RpcSendTransactionConfig(preflight_commitment=commitment) txPayload = SendVersionedTransaction(tx, config) response = requests.post( url="https://api.mainnet-beta.solana.com/", # it's better to use Helius RPC endpoint headers={"Content-Type": "application/json"}, data=SendVersionedTransaction(tx, config).to_json() ) txSignature = response.json()['result'] print(f'Transaction: https://solscan.io/tx/{txSignature}') ``` ```javascript import { Connection, Keypair, VersionedTransaction } from "@solana/web3.js"; import bs58 from "bs58"; const response = await fetch("https://api.pumpapi.io", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ publicKey: "your_public_key", action: "buy", // or sell mint: "token_address", amount: 0.01, // When you're selling, you can pass "100%" to sell everything denominatedInQuote: "true", slippage: 20, priorityFee: 0.0001, }), }); const keypairs = [ Keypair.fromSecretKey(bs58.decode("base58_private_key_1")), // stays on your computer // Keypair.fromSecretKey(bs58.decode("base58_private_key_2")), // If you are using actions or jito bundles, add all private keys involved in the transaction here. ]; const responseBuffer = Buffer.from(await response.arrayBuffer()); try { // jito bundle branch (multiple transactions) const b64Txs = JSON.parse(responseBuffer.toString("utf8")); const txs = []; const allSignatures = []; for (const base64EncodedTx of b64Txs) { const tx = VersionedTransaction.deserialize( new Uint8Array(Buffer.from(base64EncodedTx, "base64")) ); const requiredSigners = tx.message.staticAccountKeys.slice( 0, tx.message.header.numRequiredSignatures ); const matchingKeypairs = keypairs.filter((kp) => requiredSigners.some((pk) => pk.equals(kp.publicKey)) ); tx.sign(matchingKeypairs); allSignatures.push(bs58.encode(tx.signatures[0])); txs.push(Buffer.from(tx.serialize()).toString("base64")); } const jitoResponse = await fetch( "https://mainnet.block-engine.jito.wtf:443/api/v1/bundles?uuid=PLACE_YOUR_UUID_HERE_TO_USE_JITO_BUNDLES", // if you want to send multiple txs via Jito bundles get your UUID here: https://discord.com/invite/jito , without a UUID it won't land { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "sendBundle", params: [txs, { encoding: "base64" }], }), } ); console.log(await jitoResponse.text()); console.log(allSignatures); } catch (e) { // single tx branch if (!(e instanceof SyntaxError)) throw e; const tx = VersionedTransaction.deserialize(new Uint8Array(responseBuffer)); const requiredSigners = tx.message.staticAccountKeys.slice( 0, tx.message.header.numRequiredSignatures ); const matchingKeypairs = keypairs.filter((kp) => requiredSigners.some((pk) => pk.equals(kp.publicKey)) ); tx.sign(matchingKeypairs); const commitment = "confirmed"; const web3Connection = new Connection( "https://api.mainnet-beta.solana.com/", // it's better to use Helius RPC endpoint commitment ); const txSignature = await web3Connection.sendTransaction(tx, { preflightCommitment: commitment, }); console.log(`Transaction: https://solscan.io/tx/${txSignature}`); } ``` ```rust use base64::{engine::general_purpose::STANDARD, Engine as _}; use reqwest::Client; use serde_json::json; use solana_sdk::{ signature::{Keypair, Signer}, transaction::VersionedTransaction, }; #[tokio::main] async fn main() -> Result<(), Box> { let client = Client::new(); let response = client .post("https://api.pumpapi.io") .json(&json!({ "publicKey": "your_public_key", "action": "buy", // or sell "mint": "token_address", "amount": 0.01, // When you're selling, you can pass "100%" to sell everything "denominatedInQuote": "true", "slippage": 20, "priorityFee": 0.0001, })) .send() .await?; let response_bytes = response.bytes().await?; let keypairs = vec![ Keypair::from_base58_string("base58_private_key_1"), // stays on your computer // Keypair::from_base58_string("base58_private_key_2"), // If you are using actions or jito bundles, add all private keys involved in the transaction here. ]; if let Ok(b64_txs) = serde_json::from_slice::>(&response_bytes) { // jito bundle branch (multiple transactions) let mut txs: Vec = Vec::new(); let mut all_signatures: Vec = Vec::new(); for base64_encoded_tx in b64_txs { let tx_bytes = STANDARD.decode(&base64_encoded_tx)?; let mut tx: VersionedTransaction = bincode::deserialize(&tx_bytes)?; let required_signers = &tx.message.static_account_keys() [..tx.message.header().num_required_signatures as usize]; let message_bytes = tx.message.serialize(); for keypair in &keypairs { if let Some(signer_index) = required_signers .iter() .position(|pubkey| pubkey == &keypair.pubkey()) { tx.signatures[signer_index] = keypair.sign_message(&message_bytes); } } all_signatures.push(tx.signatures[0].to_string()); txs.push(STANDARD.encode(bincode::serialize(&tx)?)); } let jito_response = client .post("https://mainnet.block-engine.jito.wtf:443/api/v1/bundles?uuid=PLACE_YOUR_UUID_HERE_TO_USE_JITO_BUNDLES") // if you want to send multiple txs via Jito bundles get your UUID here: https://discord.com/invite/jito , without a UUID it won't land .header("Content-Type", "application/json") .json(&json!({ "jsonrpc": "2.0", "id": 1, "method": "sendBundle", "params": [txs, {"encoding": "base64"}] })) .send() .await?; println!("{}", jito_response.text().await?); println!("{:?}", all_signatures); } else { // single tx branch let mut tx: VersionedTransaction = bincode::deserialize(&response_bytes)?; let required_signers = &tx.message.static_account_keys() [..tx.message.header().num_required_signatures as usize]; let message_bytes = tx.message.serialize(); for keypair in &keypairs { if let Some(signer_index) = required_signers .iter() .position(|pubkey| pubkey == &keypair.pubkey()) { tx.signatures[signer_index] = keypair.sign_message(&message_bytes); } } let commitment = "confirmed"; let rpc_payload = json!({ "jsonrpc": "2.0", "id": 1, "method": "sendTransaction", "params": [ STANDARD.encode(bincode::serialize(&tx)?), { "encoding": "base64", "preflightCommitment": commitment } ] }); let response = client .post("https://api.mainnet-beta.solana.com/") // it's better to use Helius RPC endpoint .header("Content-Type", "application/json") .json(&rpc_payload) .send() .await?; let tx_signature: serde_json::Value = response.json().await?; println!( "Transaction: https://solscan.io/tx/{}", tx_signature["result"].as_str().unwrap_or("") ); } Ok(()) } ``` ```go package main import ( "bytes" "encoding/base64" "encoding/json" "fmt" "io" "log" "net/http" "github.com/gagliardetto/solana-go" ) func main() { payload := map[string]any{ "publicKey": "your_public_key", "action": "buy", // or sell "mint": "token_address", "amount": 0.01, // When you're selling, you can pass "100%" to sell everything "denominatedInQuote": "true", "slippage": 20, "priorityFee": 0.0001, } body, err := json.Marshal(payload) if err != nil { log.Fatal(err) } response, err := http.Post("https://api.pumpapi.io", "application/json", bytes.NewBuffer(body)) if err != nil { log.Fatal(err) } defer response.Body.Close() rawResponse, err := io.ReadAll(response.Body) if err != nil { log.Fatal(err) } keypairs := []solana.PrivateKey{ solana.MustPrivateKeyFromBase58("base58_private_key_1"), // stays on your computer // solana.MustPrivateKeyFromBase58("base58_private_key_2"), // If you are using actions or jito bundles, add all private keys involved in the transaction here. } signer := func(key solana.PublicKey) *solana.PrivateKey { for i := range keypairs { if keypairs[i].PublicKey().Equals(key) { return &keypairs[i] } } return nil } var b64Txs []string if err := json.Unmarshal(rawResponse, &b64Txs); err == nil { // jito bundle branch (multiple transactions) txs := []string{} allSignatures := []string{} for _, base64EncodedTx := range b64Txs { txBytes, err := base64.StdEncoding.DecodeString(base64EncodedTx) if err != nil { log.Fatal(err) } tx := new(solana.VersionedTransaction) if err := tx.UnmarshalBinary(txBytes); err != nil { log.Fatal(err) } if _, err := tx.Sign(signer); err != nil { log.Fatal(err) } signedBytes, err := tx.MarshalBinary() if err != nil { log.Fatal(err) } allSignatures = append(allSignatures, tx.Signatures[0].String()) txs = append(txs, base64.StdEncoding.EncodeToString(signedBytes)) } jitoPayload := map[string]any{ "jsonrpc": "2.0", "id": 1, "method": "sendBundle", "params": []any{ txs, map[string]any{"encoding": "base64"}, }, } jitoBody, err := json.Marshal(jitoPayload) if err != nil { log.Fatal(err) } jitoResponse, err := http.Post( "https://mainnet.block-engine.jito.wtf:443/api/v1/bundles?uuid=PLACE_YOUR_UUID_HERE_TO_USE_JITO_BUNDLES", // if you want to send multiple txs via Jito bundles get your UUID here: https://discord.com/invite/jito , without a UUID it won't land "application/json", bytes.NewBuffer(jitoBody), ) if err != nil { log.Fatal(err) } defer jitoResponse.Body.Close() jitoRespBody, err := io.ReadAll(jitoResponse.Body) if err != nil { log.Fatal(err) } fmt.Println(string(jitoRespBody)) fmt.Println(allSignatures) } else { // single tx branch tx := new(solana.VersionedTransaction) if err := tx.UnmarshalBinary(rawResponse); err != nil { log.Fatal(err) } if _, err := tx.Sign(signer); err != nil { log.Fatal(err) } txBytes, err := tx.MarshalBinary() if err != nil { log.Fatal(err) } commitment := "confirmed" rpcPayload := map[string]any{ "jsonrpc": "2.0", "id": 1, "method": "sendTransaction", "params": []any{ base64.StdEncoding.EncodeToString(txBytes), map[string]any{ "encoding": "base64", "preflightCommitment": commitment, }, }, } rpcBody, err := json.Marshal(rpcPayload) if err != nil { log.Fatal(err) } rpcResponse, err := http.Post( "https://api.mainnet-beta.solana.com/", // it's better to use Helius RPC endpoint "application/json", bytes.NewBuffer(rpcBody), ) if err != nil { log.Fatal(err) } defer rpcResponse.Body.Close() var result struct { Result string `json:"result"` } if err := json.NewDecoder(rpcResponse.Body).Decode(&result); err != nil { log.Fatal(err) } fmt.Printf("Transaction: https://solscan.io/tx/%s\n", result.Result) } } ``` *** #### Response Format[​](#response-format-1 "Direct link to Response Format") Local transactions return the **raw, unsigned transaction bytes** — not JSON. You deserialize them, sign locally, and broadcast yourself. | Request type | Response | | ------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------- | | **Single transaction** (regular `buy` / `sell` / `create` / Actions) | One raw `VersionedTransaction` in the response body | | **[Jito Bundle](/jito-bundles.md)** (multiple transactions inside `"transactions": [...]`) | An array of raw base64 `VersionedTransaction` txs — one per transaction in the bundle (up to 5) | tip Want cleaner code and faster execution? Use our ⚡ Lightning transactions *** Need help? Join our [Telegram group](https://t.me/pumpapi_devs). --- ## Transfer ### Transfer Use this to **send native SOL or SPL tokens** to another wallet. * If `mint` is **not provided**, the API sends **native SOL**. * If `mint: "token_address"` or `"mintRef": "value"` is provided, the API sends the specified **token** instead. * You can also pass `memo` as an optional field. It lets you attach a message that will be visible in Solana explorers. `amount` can be either a numeric value (for example `0.000001`) or a percentage string such as `"100%"` (transfer the full balance). The example below shows a **native SOL transfer**.
Uncomment the `"mint": "token_address"` line if you want to transfer tokens instead. > **Local transactions are supported**
For a local-transaction example, visit the **[Trade API](/trade-api.md)** page and reuse the same local-transaction code snippets — the flow works the same way here.
The code snippets below show **lightning transactions**. #### Endpoint[​](#endpoint "Direct link to Endpoint") `POST https://api.pumpapi.io` #### Request Body[​](#request-body "Direct link to Request Body") | Field | Description | | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `privateKey` | Base58 private key of the wallet that will sign the transfer transaction. **Not required if you pass `apiKey` instead.** | | `apiKey` | **Optional. Not required.** Pass it instead of `privateKey` if you prefer not to send the private key. Generate one on the **[Trade API](/trade-api.md)** page (🔑 spoiler). | | `action` | Must be **"transfer"** | | `to` | Recipient wallet address. Example: `pump22QQQnff5qmAxW7yg6VEKU3C7Mj8C4TDaXJZt9Q` | | `amount` | Amount to send. You can pass a numeric value such as `0.000001` or a percentage string such as `"100%"` to transfer the full balance | | `mint` | Optional. Token mint address. If omitted, native SOL is sent | | `mintRef` | Optional. Temporary token reference for [token creations](/create-token-pump-fun.md) | | `memo` | Optional. A memo string that will be visible in Solana explorers | #### 📦 Code Examples[​](#-code-examples "Direct link to 📦 Code Examples") * Python * JavaScript * Rust * Go ```python import requests url = "https://api.pumpapi.io" data = { "privateKey": "base58_private_key", # or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "transfer", "to": "recipient_public_key", "amount": 0.000001, # You can also use a percentage, for example "100%" to transfer everything # "mint": "token_address", # Add this if you want to transfer tokens # "memo": "Hello from PumpAPI", # Optional memo visible in Solana explorers } response = requests.post(url, json=data) print(response.json()) ``` ```javascript import axios from "axios"; const url = "https://api.pumpapi.io"; const data = { privateKey: "base58_private_key", # or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) action: "transfer", to: "recipient_public_key", amount: 0.000001, // You can also use a percentage, for example "100%" to transfer everything // mint: "token_address", // Add this if you want to transfer tokens // memo: "Hello from PumpAPI", // Optional memo visible in Solana explorers }; axios .post(url, data) .then((res) => console.log(res.data)) .catch((err) => console.error(err)); ``` ```rust use reqwest::Client; use serde_json::json; #[tokio::main] async fn main() -> Result<(), Box> { let client = Client::new(); let res = client .post("https://api.pumpapi.io") .json(&json!({ "privateKey": "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "transfer", "to": "recipient_public_key", "amount": 0.000001 // "mint": "token_address", // Add this if you want to transfer tokens // "memo": "Hello from PumpAPI" // Optional memo visible in Solana explorers })) .send() .await? .text() .await?; println!("{}", res); Ok(()) } ``` ```go package main import ( "bytes" "encoding/json" "fmt" "net/http" ) func main() { url := "https://api.pumpapi.io" data := map[string]any{ "privateKey": "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "transfer", "to": "recipient_public_key", "amount": 0.000001, // You can also use a percentage, for example "100%" to transfer everything // "mint": "token_address", // Add this if you want to transfer tokens // "memo": "Hello from PumpAPI", // Optional memo visible in Solana explorers } jsonData, _ := json.Marshal(data) resp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonData)) if err != nil { panic(err) } defer resp.Body.Close() var result any _ = json.NewDecoder(resp.Body).Decode(&result) fmt.Printf("%v\n", result) } ``` *** Need help? Join our [Telegram group](https://t.me/pumpapi_devs). --- ## Tutorials ### Detecting Scam Pools In this guide, we'll teach you how to identify scam liquidity pools and protect yourself from rug pulls. Important Note Even if a token passes all security checks from our [token scam detection guide](/tutorials/detect_scam_tokens.md), you can still lose money if you're trading in the wrong pool. Always verify the pool before trading! #### Anyone Can Create a Pool[​](#anyone-can-create-a-pool "Direct link to Anyone Can Create a Pool") Here's something many traders don't realize: **anyone can create a liquidity pool for any token**. Even if a token was originally launched on pump.fun, nothing prevents someone from: 1. Buying that token 2. Creating their own pool on PumpSwap, Raydium, Meteora, or any other DEX 3. Waiting for unsuspecting traders to buy from their malicious pool This means you might accidentally analyze and trade a legitimate token, but in a scam pool created by a bad actor. Always Check the Pool Before trading, always verify which pool you're interacting with. The token might be fine, but the pool could be a trap. #### Pool Verification[​](#pool-verification "Direct link to Pool Verification") ##### Checking Pool Origin[​](#checking-pool-origin "Direct link to Checking Pool Origin") Let's focus on the most common case: you only want to trade tokens related to pump.fun, raydium launchpad, meteora launchpad ecosystem. Here's how to verify the pool using our API response: | Pool Type | What to Check | Safe Condition | | --------------------------------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `pump` | Nothing extra needed | ✅ Safe if `mayhemMode` == `False`. (If `True`, the token supply is 2 billion, and 1 billion tokens are allocated to pump.fun’s AI agent. The agent may sell before you. It hasn’t bought these tokens, which creates an imbalance. Selling all tokens when liquidity is nearly empty may cause a 6024 overflow error. In this case, sell as much as possible and call `"action": "burn"` with `100%` to recover the rent fee.) | | `pump-amm` | Check `poolCreatedBy` | ✅ Safe if `poolCreatedBy` = `"pump"` and `mayhemMode` == `False` | | `raydium-cpmm` | Check `poolCreatedBy` | ✅ Safe if `poolCreatedBy` = `"raydium-launchpad"` | | `meteora-damm-v1/meteora-damm-v2` | Check `poolCreatedBy` | ✅ Safe if `poolCreatedBy` = `"meteora-launchpad"` and `"burnedLiquidity"` = 100% (meteora launchpad allows to choose creator’s liquidity share, so they can remove liquidity if it's less than 100%) | | Any pool | Check `poolCreatedBy` | ⚠️ Be careful if `poolCreatedBy` = `"custom"` | Quick Rule If you want a simple rule: avoid any pool where `poolCreatedBy` equals `"custom"` unless you know exactly what you're doing. ##### Example: Safe Pool[​](#example-safe-pool "Direct link to Example: Safe Pool") ```json { "pool": "pump-amm", "poolCreatedBy": "pump", // ✅ Created by pump.fun migration - SAFE "burnedLiquidity": "100%", "mayhemMode": False, } ``` ##### Example: Suspicious Pool[​](#example-suspicious-pool "Direct link to Example: Suspicious Pool") ```json { "pool": "pump-amm", "poolCreatedBy": "custom", // ⚠️ Created manually by someone - BE CAREFUL "burnedLiquidity": "0%" } ``` #### Understanding Liquidity and Rug Pulls[​](#understanding-liquidity-and-rug-pulls "Direct link to Understanding Liquidity and Rug Pulls") ##### What is Liquidity?[​](#what-is-liquidity "Direct link to What is Liquidity?") A liquidity pool is essentially a smart contract holding two assets (e.g., SOL and a token). When you buy a token, you add SOL to the pool and remove tokens. When you sell, you do the opposite. **Liquidity providers** are people who deposit both assets into the pool. In return, they receive LP (Liquidity Provider) tokens representing their share of the pool. They earn trading fees but can also withdraw their liquidity at any time. ##### How Rug Pulls Work[​](#how-rug-pulls-work "Direct link to How Rug Pulls Work") Here's a step-by-step example of a classic liquidity rug pull: **Step 1: Scammer creates a pool** ```text Pool initial state: ├── SOL: 200 ├── Tokens: 20,000,000 └── Scammer owns: 100% of LP tokens ``` **Step 2: Victim buys tokens** ```text Victim sends: 70 SOL Victim receives: 10,000,000 tokens Pool after purchase: ├── SOL: 270 ├── Tokens: 10,000,000 └── Scammer still owns: 100% of LP tokens ``` **Step 3: Scammer withdraws all liquidity** ```text Scammer withdraws 100% of LP tokens and receives: ├── SOL: 270 (including victim's 70 SOL!) └── Tokens: 10,000,000 Pool after rug pull: ├── SOL: 0 └── Tokens: 0 ``` **Result:** The victim is left with 10,000,000 tokens that cannot be sold because there's no liquidity in the pool. The scammer walks away with 270 SOL (200 initial + 70 from victim). #### The burnedLiquidity Parameter[​](#the-burnedliquidity-parameter "Direct link to The burnedLiquidity Parameter") ##### What Does It Mean?[​](#what-does-it-mean "Direct link to What Does It Mean?") `burnedLiquidity` shows what percentage of LP tokens have been permanently destroyed (burned). Burned LP tokens can never be used to withdraw liquidity. | burnedLiquidity | Meaning | | --------------- | ----------------------------------------------------------------------- | | `"100%"` | All liquidity is permanently locked. Nobody can rug pull. | | `"50%"` | Half of liquidity is locked. Even if all providers withdraw, 50% stays. | | `"0%"` | No liquidity is locked. Pool can be completely drained. | Rule of Thumb Higher `burnedLiquidity` = Safer pool. When 100% is burned, the pool will always have liquidity for trading, no matter what. ##### Why Do People Provide Liquidity?[​](#why-do-people-provide-liquidity "Direct link to Why Do People Provide Liquidity?") Liquidity providers earn a percentage of every trade that happens in the pool. This can be a legitimate way to earn passive income. However, scammers abuse this system by creating pools with the intention of withdrawing all liquidity after others have bought in. When pump.fun migrates a token to pump-amm, it burns the LP tokens, which is why `poolCreatedBy: "pump"` pools are safe. #### When 0% burnedLiquidity is Acceptable[​](#when-0-burnedliquidity-is-acceptable "Direct link to When 0% burnedLiquidity is Acceptable") Not every pool with `"0%"` burned liquidity is a scam. Here are legitimate scenarios: ##### 1. Old, Established Pools[​](#1-old-established-pools "Direct link to 1. Old, Established Pools") Some older pools with well-known tokens have multiple liquidity providers. The ownership is diluted across many participants, so no single entity controls enough to drain the pool. ##### 2. Stablecoin and Major Token Pools[​](#2-stablecoin-and-major-token-pools "Direct link to 2. Stablecoin and Major Token Pools") If you're buying USDC, USDT, or other major tokens, the `burnedLiquidity` parameter matters less. Why? Because even if something happens to one pool, you can always sell these tokens in hundreds of other pools. ##### 3. You Don't Plan to Sell in This Pool[​](#3-you-dont-plan-to-sell-in-this-pool "Direct link to 3. You Don't Plan to Sell in This Pool") If you're using a pool purely for buying and plan to sell elsewhere (for example, arbitrage), pool safety matters less. Just be aware of the risks. #### Check poolFeeRate Carefully[​](#check-poolfeerate-carefully "Direct link to Check poolFeeRate Carefully") When working with Meteora Launchpad, Meteora DAMM V1, and Meteora DAMM V2, always verify the `poolFeeRate` parameter. Meteora allows pool creators to set fees up to 99%. All trading fees go to LP providers — which often means the pool creator. This makes fee verification critical. * `poolFeeRate = 0.0025` → 0.25% fee (normal and reasonable) * `poolFeeRate = 0.5` → 50% fee (extremely dangerous) Also check `poolFeeRateAfterMigration` for Meteora Launchpad pools. A token might look fine at launch but migrate to a pool with a 10% fee. You don’t want to discover that only when trying to sell. #### Best Practices for Pool Verification[​](#best-practices-for-pool-verification "Direct link to Best Practices for Pool Verification") When checking pools through our API, follow this checklist: 1. ✅ Check `pool` type 2. ✅ If `pool` is `pump-amm`, verify `poolCreatedBy` is `"pump"` 3. ✅ If `pool` is `raydium-cpmm`, verify `poolCreatedBy` is `"raydium-launchpad"` 4. ✅ If `pool` is `meteora-damm-v1` or `meteora-damm-v2`, verify `poolCreatedBy` is `"meteora-launchpad"` and `burnedLiquidity` is `100%` and `"poolFeeRate"` is less than `0.001` 5. ✅ Avoid pools where `poolCreatedBy` is `"custom"` unless you have good reasons 6. ✅ Check `burnedLiquidity` — prefer pools with high percentages 7. ✅ If `burnedLiquidity` is `"0%"`, only proceed if you understand the risks 8. ✅ Avoid `pump` and `pump-amm` pools where `mayhemMode` == `False` Simplest Check If you don't want to deal with complex verification logic, just use this simple rule: ```python if trade_event.get('poolCreatedBy') in ('pump', 'raydium-launchpad') and not trade_event.get('mayhemMode'): # Safe to trade ``` This single check filters out all manually created pools, leaving only pools created by trusted launchpads (pump.fun, raydium-launchpad). #### Summary[​](#summary "Direct link to Summary") | Check | Safe✅ | Risky🚨 | | --------------- | ------------------------------------------------ | --------------------------------- | | Pool type | `pump`, `raydium-launchpad`, `meteora-launchpad` | — | | poolCreatedBy | `"pump"`, `"raydium-launchpad"` | `"custom"`, `"meteora-launchpad"` | | burnedLiquidity | 50%+ | 0% | | mayhemMode | False | True | Good luck! --- ### Detecting Scam Tokens In this guide, we'll teach you how to use our API to identify scam tokens that have been added to Pump AMM and Raydium CPMM pools. Important Note This guide is specifically for tokens in Pump AMM and Raydium CPMM pools. For pump.fun and Bonk pools, this verification is not necessary because these launchpads are designed to ensure trust - you can be confident that no one will block your tokens or steal your money. The only risk on such launchpads is price volatility (you may lose money, but this is not a technical scam). #### What is Technical Scam?[​](#what-is-technical-scam "Direct link to What is Technical Scam?") We're talking about **technical scam** - when you lose money not because of price fluctuations, but because of the technical capabilities built into Solana tokens. This is fundamentally different from market risk. #### Understanding Token Programs[​](#understanding-token-programs "Direct link to Understanding Token Programs") There are two token programs from Solana: * **spl-token** - the older but still popular version * **spl-token-2022** - the newer version with extended capabilities Every token you see on the Solana network belongs to one of these programs, and you can check this on Solscan. Older pump.fun tokens were issued on `spl-token`, and now there's a transition period to `spl-token-2022`. Key Concept Every memecoin belongs to one of these token programs. There can be no other option. (Technically, you can create your own program for token creation, but no one will recognize it - all pools only support SPL programs, and you cannot insert a token with custom code into a pool, meaning it cannot be traded). #### Example Trade Event[​](#example-trade-event "Direct link to Example Trade Event") Here's what a trading event from our Datastream looks like: ```json { "signature": "3ajv8Z8M4FS4gN9oxJ7mijuBXFqh5PhU9iQKSfHRg6tANq1bf7ctvjsvxtz88JEZfuErGcvAYpxmzY1ji9PWxkQT", "action": "sell", "poolId": "8bKC4SYPALUqVpkmTw9JXJ8HcaFFjPbCwoavwCKZyHH4", "mint": "iNFMULTEJVCmhn2iT1xpqZXGm589oe7MjdwmfRHyCPq", "quoteMint": "So11111111111111111111111111111111111111112", "txSigner": "5zE1jAZPNACZUjJ1dEYGeo3TUG2KBHZpDpjXQth9qsgF", "tokenAmount": 426.0, "quoteAmount": 1.054e-6, "tokensInPool": 831751212.1486242, "quoteInPool": 2.261396821, "price": 2.7188501633348083e-9, "marketCapQuote": 2.310601896771811, "name": "Everyone Infected", "symbol": "Virus", "uri": "https://ipfs.io/ipfs/QmU36FKWDH9AZriggkeSP8uARccsQGEgw8nUPmYLh6ByW8", "supply": 849845250, "poolFeeRate": 0.01, "pool": "meteora-damm-v2", "poolCreatedBy": "custom", "burnedLiquidity": "100%", "minPrice": 5.421214630269582e-20, "maxPrice": 1.844605071373595e19, "mintAuthority": None, "freezeAuthority": None, "tokenProgram": "spl-token-2022", "tokenExtensions": { "transferFeeConfig": {} <----- transferFeeConfig is VERY DANGEROUS, and probably the most common scam in the spl-token-2022 }, "tradersInvolved": { "5zE1jAZPNACZUjJ1dEYGeo3TUG2KBHZpDpjXQth9qsgF": {} }, "postBalances": { "5zE1jAZPNACZUjJ1dEYGeo3TUG2KBHZpDpjXQth9qsgF": { "sol": 0.275737402, "iNFMULTEJVCmhn2iT1xpqZXGm589oe7MjdwmfRHyCPq": 2419.16839794, "So11111111111111111111111111111111111111112": 0.0 } }, "priorityFee": 0.000145, "block": 421882961, "timestamp": 1779638272696 } ``` #### SPL-Token Security Checks[​](#spl-token-security-checks "Direct link to SPL-Token Security Checks") For `spl-token`, there are only 2 types of potential technical scams: ##### 1. mintAuthority[​](#1-mintauthority "Direct link to 1. mintAuthority") A legitimate token, after minting tokens (for example, 1 billion new tokens), should disable `mintAuthority` by setting it to `None` (this is what launchpads do, and you can trust them). **⚠️ Warning:** If the `mintAuthority` field contains an address instead of `None`, it means that more tokens can be minted at any time, diluting your holdings. ##### 2. freezeAuthority[​](#2-freezeauthority "Direct link to 2. freezeAuthority") A legitimate token should NOT have `freezeAuthority` (value should be `None`). If there's an address in this field, the token is most likely a **SCAM** and can freeze your tokens at any moment. Exception for Stablecoins This is normal only for stablecoins like USDC, USDT, and others, because regulators require them to have the ability to block funds in accounts. Therefore, theoretically, any of your USDC can be frozen at any moment. For example, here's a [frozen account transaction attempt](https://solscan.io/tx/2NFRdteSJzWEyQqhLEuC1HT3TZqELBDc3h9QwENVJC48vXYw1cgRKkbDq17jAHghuHMHHEpZSeuaQ1rzznZ6A1eq) we found from the USDC freeze authority. Open Program Logs and search the page for "account is frozen" and you'll see that the transaction fails not because of insufficient funds, but because the funds are blocked. This is where the possibilities for abuse on `spl-token` end. #### SPL-Token-2022 and Token Extensions[​](#spl-token-2022-and-token-extensions "Direct link to SPL-Token-2022 and Token Extensions") `spl-token-2022` offers all the same features as `spl-token`, but adds **token extensions** on top. These extensions can bring both benefits and harm. Below is a table ranking token extensions from safe and harmless to dangerous. If a token is not from a well-known company and has a dangerous extension, the probability of it being a scam is almost 100%. #### Token Extensions Safety Reference[​](#token-extensions-safety-reference "Direct link to Token Extensions Safety Reference") ##### ✅ Safe Extensions[​](#-safe-extensions "Direct link to ✅ Safe Extensions") These extensions are cosmetic or security-enhancing and do not affect your ability to trade: | Extension | Description | Safety Level | | ------------------------- | ----------------------------------------------------------------------------------------- | ------------ | | **metadataPointer** | Points to token metadata | ✅ Safe | | **tokenMetadata** | Contains token metadata information | ✅ Safe | | **groupPointer** | Points to token group | ✅ Safe | | **groupMemberPointer** | Points to group member | ✅ Safe | | **tokenGroup** | Groups related tokens | ✅ Safe | | **tokenGroupMember** | Member of a token group | ✅ Safe | | **scaledUiAmount** | Changes UI display only | ✅ Safe | | **interestBearingConfig** | Cosmetic interest rate display | ✅ Safe | | **mintCloseAuthority** | Authority to close mint account (they can't close it if anybody still have token balance) | ✅ Safe | ##### 🚨 Dangerous Extensions[​](#-dangerous-extensions "Direct link to 🚨 Dangerous Extensions") These extensions can prevent you from selling or result in loss of funds: | Extension | Description | Danger Level | | --------------------------------- | --------------------------------------------------- | ------------ | | **memoTransfer** | Requires memo for transfers | 🚨 High Risk | | **transferFeeConfig** | Charges fees on transfers | 🚨 High Risk | | **transferHook** | Custom code runs on transfers | 🚨 High Risk | | **permanentDelegate** | Permanent control over tokens | 🚨 High Risk | | **defaultAccountState** | Can set accounts to frozen by default | 🚨 High Risk | | **nonTransferable** | Tokens cannot be transferred | 🚨 High Risk | | **confidentialTransferMint** | Confidential transfers (incompatible with pools) | 🚨 High Risk | | **confidentialMintBurn** | Confidential minting (incompatible with pools) | 🚨 High Risk | | **confidentialTransferFeeConfig** | Confidential transfer fee (incompatible with pools) | 🚨 High Risk | | **pausableConfig** | Can pause all transfers | 🚨 High Risk | | **cpiGuard** | Your program will stop working | 🚨 High Risk | #### Best Practices[​](#best-practices "Direct link to Best Practices") When checking tokens through our API, always verify: 1. ✅ `mintAuthority` is `None` 2. ✅ `freezeAuthority` is `None` (unless it's a known stablecoin) 3. ✅ If `spl-token-2022`, check `tokenExtensions` array 4. ✅ Avoid tokens with dangerous extensions unless from trusted sources Stay safe and always verify token before trading! --- ## Wrap Sol ### Wrap SOL The wrapSol action converts native SOL into Wrapped SOL (wSOL) — an SPL token version of SOL. If you need to convert it back, just buy or sell any token on pump-amm. This will automatically close the wSOL token account and return everything back to SOL. *** #### Endpoint[​](#endpoint "Direct link to Endpoint") `POST https://api.pumpapi.io` #### Request Fields[​](#request-fields "Direct link to Request Fields") | Field | Description | | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `privateKey` | Your wallet private key (base58). **Not required if you pass `apiKey` instead.** | | `apiKey` | **Optional. Not required.** Pass it instead of `privateKey` if you prefer not to send your private key. Generate one on the **[Trade API](/trade-api.md)** page (🔑 spoiler). | | `action` | Must be `"wrapSol"` | | `amount` | Amount of SOL to wrap (e.g. `"0.5"`) | | `priorityFee` | Priority fee in SOL (e.g. `"0.00002"`) | *** #### Code Examples[​](#code-examples "Direct link to Code Examples") * Python * JavaScript * Go * Rust ```python import aiohttp import asyncio async def wrap_sol(): url = "https://api.pumpapi.io" data = { "privateKey": "base58_private_key", # or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "wrapSol", "amount": "0.5", "priorityFee": "0.00002", } async with aiohttp.ClientSession() as session: async with session.post(url, json=data) as response: result = await response.json() print(result) asyncio.run(wrap_sol()) ``` ```javascript const response = await fetch("https://api.pumpapi.io", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ privateKey: "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) action: "wrapSol", amount: "0.5", priorityFee: "0.00002", }), }); const result = await response.json(); console.log(result); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "net/http" ) func main() { payload := map[string]string{ "privateKey": "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "wrapSol", "amount": "0.5", "priorityFee": "0.00002", } body, _ := json.Marshal(payload) resp, err := http.Post("https://api.pumpapi.io", "application/json", bytes.NewBuffer(body)) if err != nil { panic(err) } defer resp.Body.Close() var result map[string]interface{} json.NewDecoder(resp.Body).Decode(&result) fmt.Println(result) } ``` ```rust use reqwest::Client; use serde_json::json; #[tokio::main] async fn main() -> Result<(), Box> { let client = Client::new(); let payload = json!({ "privateKey": "base58_private_key", // or use "apiKey": "your_api_key" instead — generate one at pumpapi.io/trade-api (🔑 spoiler) "action": "wrapSol", "amount": "0.5", "priorityFee": "0.00002" }); let res = client .post("https://api.pumpapi.io") .json(&payload) .send() .await?; println!("{}", res.text().await?); Ok(()) } ``` *** Need help? Join our [Telegram group](https://t.me/pumpapi_devs). ---