Skip to main content

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

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

If you also want to trade at migration time, add "initialTradeAction": "buy" or "sell" to your request. All other fields (amount, slippage, etc.) work exactly like the Trade API.


Combine with Actions

You can use Actions to buy just enough tokens to push tokensInPool to 0, then trigger the migration as the second action — all in one transaction. In this case, you can't use initialTradeAction - see why below.


CPI Limit — Important

warning

Solana has a CPI limit of 49. Migration with a trade is a complex transaction, so you need to optimize your request carefully.

You cannot use regular SOL for the trade — it takes too many CPI calls. You must use Wrapped SOL (wSOL) instead.

Step 1 — Wrap your SOL (separate transaction)

Call wrapSol in advance to convert SOL into wSOL:

data = {
"privateKey": "base58_private_key",
"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"

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.


Endpoint

POST https://api.pumpapi.io

Request Fields (migrate + trade)

{
"privateKey": "base58_private_key",
"action": "migrate",
"initialTradeAction": "buy",
"disableSolWrapper": "true",
"mint": "token_address",
"amount": "0.01",
"denominatedInQuote": "true",
"slippage": "90",
"priorityFee": "0.00019"
}

Local Transactions

Local transactions are supported too, but will be slower. Use the same logic as on the Trade API page.


Code Example

The example below wraps 0.5 SOL, then listens to the stream and triggers migration + buy the moment tokensInPool == 0.

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",
"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"],
"amount": "0.2",
"denominatedInQuote": "true",
"slippage": "20",
"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())

Need help? Join our Telegram group.