Pump.fun Curve Quotes (fft)
Use fft=1 on Q1 to price SOL pairs with pump.fun tokens on their live bonding curve and get back a transaction that trades on pump.fun directly.
Use fft=1 when your integration trades pump.fun tokens that are still on their bonding curve. New launches are quotable within milliseconds of creation.
fft is an optional query parameter on the Q1 GET /api/v2/quote request. It keeps the Q1 parameters, the X-API-KEY header, and the Q1 response schema. When one side of the pair is SOL and the other is a pump.fun token on its bonding curve:
- the quote is priced on the curve's live state with pump.fun's own fee math, including pump.fun's protocol and creator fees
- with
user_account,txnis an unsigned transaction that trades on pump.fun directly:buy_exact_sol_into buy,sellto sell - curves quoted in another token (USDC, PUMP and others) are served too, in SOL or in their own quote token; see Curves quoted in another token
Any other pair, and any token that has graduated to PumpSwap, is answered by normal Q1 routing. On a SOL pair whose token is not a pump.fun coin, fft=1 first adds an RPC read and up to 60 ms, so send it on quotes for tokens that may be pump.fun coins.
Part of the Carbium Solana infrastructure stack.
What this page owns
This page owns the fft=1 behavior of Q1:
| Surface | What it does |
|---|---|
GET https://api.carbium.io/api/v2/quote with fft=1 |
Prices SOL and pump.fun bonding-curve pairs on the live curve and can return a transaction that trades on pump.fun directly |
Use other pages when the question changes:
- use Q1 for the base request shape and the other response fields
- use Executing Swaps for sign -> submit -> confirm
- use Swap API Errors Reference for auth, request-shape, and route failures
- use Supported DEXs and Routing Sources for the sources normal routing uses
When fft=1 applies
| Request | Answered by |
|---|---|
src_mint is SOL, dst_mint is a pump.fun token on its bonding curve |
The curve: a buy through pump.fun buy_exact_sol_in |
src_mint is a pump.fun token on its bonding curve, dst_mint is SOL |
The curve: a sell through pump.fun sell |
| The token has graduated to PumpSwap | Normal Q1 routing |
src_mint is SOL, dst_mint is a pump.fun token on a curve quoted in another token |
Two legs in one transaction when that quote token is served: SOL to the quote token on a DEX pool, then pump.fun buy_exact_quote_in_v2 |
src_mint is such a token, dst_mint is SOL |
Two legs: pump.fun sell_v2, then the quote token to SOL |
| The curve's own quote token and its pump.fun token, either way (for example USDC to the token) | The curve, priced and paid in the quote token |
| A curve quoted in a token that is not served, or whose leg pool is unavailable right now | Normal Q1 routing, usually 422 no_route |
| Any other pair, including token-to-token pairs | Normal Q1 routing |
fft missing, or any value other than 1 |
Normal Q1 routing |
SOL means the mint So11111111111111111111111111111111111111112. Only the exact value 1 turns the curve path on; fft=true does not.
To see which path answered, check the swapInfo.label of each routePlan leg: a pump-curve leg is the curve path, alone or with one DEX leg on a curve quoted in another token. Any other route is normal routing.
Request shape
Method: GET
URL:
https://api.carbium.io/api/v2/quote
Header:
X-API-KEY: YOUR_API_KEY
| Parameter | Required | Meaning |
|---|---|---|
src_mint |
Yes | SOL to buy, or the pump.fun token mint to sell |
dst_mint |
Yes | The pump.fun token mint to buy, or SOL to sell |
amount_in |
Yes | Raw input amount: lamports on a buy, raw token units on a sell |
slippage_bps |
Yes | Slippage tolerance in basis points |
user_account |
No | Wallet address; required for an executable txn |
fft |
No | 1 prices SOL and pump.fun bonding-curve pairs on the live curve |
treasury and fee_bps keep working with fft=1. The fees table below shows how they are charged on a curve answer.
Response differences
A curve answer has the same schema as any Q1 answer. Its curve leg is the routePlan entry labeled pump-curve (the only leg on a SOL-quoted curve). These fields carry curve-specific values:
| Field | On a curve answer |
|---|---|
routePlan[].swapInfo.label |
pump-curve |
routePlan[].swapInfo.ammKey |
The token's bonding-curve address |
routePlan[].swapInfo.feeAmount |
pump.fun's fee in lamports: its protocol fee plus the creator fee |
routePlan[].swapInfo.outAmount |
On a sell, the SOL pump.fun pays out after its own fee and before the platform fee |
feeBps |
Carbium-side fees in basis points: the 5 bps platform fee, plus your fee_bps when you set treasury |
feeMint |
The SOL mint, on buys and sells: every fee on this path is paid in SOL |
srcAmountIn |
Buy: amount_in minus the platform fee (and your fee), which is the SOL that goes into pump.fun. Sell: amount_in |
destAmountOut |
Buy: tokens out. Sell: SOL out after pump.fun's fee and the platform fee (and your fee) |
txn |
Base64 unsigned v0 transaction, present only with user_account |
What the transaction does
txn is unsigned. user_account is the fee payer and the only signer, and the message carries a recent blockhash.
| Side | Instructions, in order |
|---|---|
| Buy | compute-unit limit and price; SOL fee transfers; create the wallet's token account if it is missing; pump.fun buy_exact_sol_in |
| Sell | compute-unit limit and price; pump.fun sell; SOL fee transfers |
The platform fee is a plain SOL transfer inside this transaction, and so is your fee when you set treasury: one transaction, one signature.
Fees on a curve answer
| Fee | Charged on | Paid to |
|---|---|---|
| Platform fee, 5 bps | Buy: amount_in. Sell: the SOL pump.fun pays out |
Carbium, by SOL transfer in txn |
Your fee (treasury + fee_bps) |
The same base as the platform fee | The treasury wallet, by SOL transfer in txn |
| pump.fun protocol and creator fees | The SOL that trades on the curve | pump.fun, inside its own instruction; reported as feeAmount |
Each SOL transfer is floor(base * bps / 10000) lamports. On this path your fee is paid in SOL even when the output is a token, no treasury token account is created, and the transaction has no carbium fee: log line: check the treasury wallet's SOL balance instead.
Curves quoted in another token
About one pump.fun launch in ten is quoted in a token other than SOL: its curve takes and pays out that token, for example USDC or PUMP. fft=1 serves these curves in two ways.
On the curve's own pair (the quote token and the pump.fun token, either way), the answer is one leg, pump-curve, priced and paid in the quote token. feeMint is the quote token's mint, and every fee is charged in it.
On a SOL pair, the answer is two legs in one transaction, when the curve's quote token is served (table below):
| Side | routePlan, in trade order |
What txn does |
|---|---|---|
| Buy | the DEX leg (SOL to the quote token), then pump-curve |
wraps SOL, swaps it to the quote token on the leg pool, unwraps what is left, buys on the curve with buy_exact_quote_in_v2 |
| Sell | pump-curve, then the DEX leg (the quote token to SOL) |
sells on the curve with sell_v2, swaps the quote token to SOL on the leg pool, unwraps |
The DEX leg's swapInfo.label is o-whirlpool, r-clmm or pump-amm, and its ammKey is the leg pool. feeMint is the SOL mint, srcAmountIn and destAmountOut are in SOL and token units as on a SOL-quoted curve, and each leg's swapInfo.feeMint names the token its feeAmount is in. Every leg carries its own minimum output, so the transaction trades in full or not at all.
Served quote tokens
| Quote token mint | Leg pool |
|---|---|
pumpCmXqMfrsAkQ5r49WcJnRayYRqmXz6ae8H7H9Dfn (PUMP) |
Orca Whirlpool |
EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v (USDC) |
Orca Whirlpool |
3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh |
Orca Whirlpool |
XsoCS1TfEyfFhfvj8EtZ528L3CaKBDBRqRapnBbDF2W |
Raydium CLMM |
Xsc9qvGR1efVDFGLrVsmkzv3qi45LTBjeUKSPmx9qEh |
Raydium CLMM |
XsDoVfqeBukxuZHWhdvWHBhgEHjGNst4MLodqsJHzoB |
Raydium CLMM |
TTWofwAge91oFhZs7kpQdyrVRkmevgM88xijGvQFbKo |
Raydium CLMM |
SPCXxcqXj6e5dJDVNovHN8744zkbhM2bYudU45BimGb |
Raydium CLMM |
shib5gSoVKPjwkXrxRk7SbQFzb2R9rQB3TgQWYX4RwW |
Raydium CLMM, while its pool holds at least 10 SOL |
DJTu7vi8norVzdVAffgvb39VP7wjKeTsgaMBJrzfxvoF |
Raydium CLMM |
HiMSSzzwkZkrXJ4PGVJRdtfLaANeAztjjcgk5Dxe7Lwx |
Raydium CLMM |
8J69rbLTzWWgUJziFY8jeu5tDwEPBwUz4pKBMr5rpump |
Pump AMM |
Ai66LHZG9MCzg1WKdawwqduVAXpNDUuV8M3uyq5ppump |
Pump AMM |
9cRCn9rGT8V2imeM2BaKs13yhMEais3ruM3rPvTGpump |
Pump AMM |
The list changes as pools change. A SOL buy is served only when, at that moment, the leg pool can also price selling that quote token back to SOL. A SOL pair on a curve whose quote token is not served, or whose leg pool cannot be priced right now, answers like any pair without a route: 422 no_route. The curve's own pair still works.
What stays in your wallet
- Buy: the DEX leg must return at least its minimum, up to 0.5% under its quote. The curve spends exactly that minimum, so anything the leg returns above it stays in your wallet as the quote token.
- Sell: the curve's output goes back to SOL less a 0.5% margin, and that margin stays in your wallet as the quote token. If the curve pays out less than that, because the price moved more than about 0.5% between the quote and landing, the whole transaction fails and nothing trades: requote and send again. In a 15-minute live test, 3 of 43 such sells failed this way and each went through on the next quote.
- Quote-token account: the first trade creates your wallet's account for the quote token (rent about 0.0015 SOL). It keeps the leftovers above; close it when you no longer need it.
The platform fee and your fee are SOL transfers, as on a SOL-quoted curve: on a buy they are charged on amount_in, on a sell on the SOL the DEX leg pays out. pump.fun's fees are charged in the quote token, and the leg pool's fee is inside its output.
Errors
Curve-path errors use a structured body. Branch on error.code; message is written for people and can change.
{
"error": {
"code": "fft_sell_exceeds_real_sol",
"message": "gross 196786684 lamports above real_sol_reserves 98716048",
"details": { "max_amount_in": "3519164087103" }
}
}
| HTTP status | code |
Meaning | First fix |
|---|---|---|---|
422 |
fft_amount_too_small |
amount_in buys or sells nothing after fees |
Raise amount_in |
422 |
fft_sell_exceeds_real_sol |
The sell needs more SOL than the curve holds | Sell details.max_amount_in or less: the largest amount the curve can pay for right now |
422 |
fft_buy_exceeds_real_tokens |
The buy asks for more tokens than the curve has left | Lower amount_in |
400 |
fft_bad_user_account |
user_account is not a valid Solana address |
Send the wallet's base58 address |
500 |
fft_rpc_error |
The curve state could not be read | Retry the quote |
500 |
fft_txn_error |
The quote priced, but the transaction could not be built | Retry the quote |
details appears only on fft_sell_exceeds_real_sol. A pair that neither the curve path nor normal routing can serve answers 422 with code no_route. Auth, request-shape, and normal-routing failures keep their usual bodies; see Swap API Errors Reference.
Guidance
- Widen slippage for launch buys. Launches move fast. For buys in the first seconds after a launch, set
slippage_bpsbetween1000and3000as an explicit policy for that flow, not as a retry knob. On a buy,destAmountOutMinis themin_tokens_outthat pump.fun enforces. - Reuse your connection. Keep your HTTPS connection to the API open between quotes: a new TLS connection per request costs about 14 ms more than a reused one. Most HTTP clients reuse connections when you keep the client (in Node,
fetchdoes; in Python, use arequests.Session). - Sign and send promptly.
txnis unsigned and carries a recent blockhash. Sign and submit it right after the quote. If the blockhash expires, request a new quote instead of re-signing the old bytes; see Blockhash Expiry Recovery Playbook. - Simulate before you send. The curve path builds
txnwithout checking the wallet's balance, so a quote can return a transaction the wallet cannot pay for. Keep preflight on, or simulate first. - Keep SOL for network costs. The wallet pays the network fee, and the rent for any account the buy opens such as its token account, on top of
amount_in.signatureFeeLamports,prioritizationFeeLamports, andrentFeeLamportsread"0"and do not cover these. A wallet's first pump.fun buy ever also opens pump.fun's per-user volume account, about 0.00135 SOL, once per wallet. - Sell the full balance. Pass the wallet's raw token balance (the
amountstring fromgetTokenAccountBalance) asamount_in, with the mints swapped:src_mintis the token anddst_mintis SOL. Onfft_sell_exceeds_real_sol, selldetails.max_amount_infirst, then requote the rest. The sell leaves the emptied token account open; close it in your own transaction to recover its rent. - Requote a brand-new mint. If a quote for a token launched moments ago comes back without the
pump-curvelabel, or as a route error, its curve was not visible yet. Request the quote again. - Requote after a buy fails on chain. A buy can land and fail when the curve changed after the quote.
Custom 2006, a seeds constraint oncreator_vault, means the token's creator moved it to pump.fun fee sharing, which often happens in the first slots after a launch.Custom 6042means the price moved pastslippage_bps. Request a new quote and send itstxn; do not resend the old bytes.
Worked example
Buy 0.1 SOL of a token that just launched, with slippage_bps=2000:
curl --request GET \
--url 'https://api.carbium.io/api/v2/quote?src_mint=So11111111111111111111111111111111111111112&dst_mint=TOKEN_MINT&amount_in=100000000&slippage_bps=2000&user_account=YOUR_WALLET&fft=1' \
--header 'X-API-KEY: YOUR_API_KEY'
Response, trimmed to the fields this page covers:
{
"srcAmountIn": "99950000",
"destAmountOut": "3519164015687",
"destAmountOutMin": "2815331212549",
"swapMode": "BaseIn",
"slippage": "2000",
"routePlan": [
{
"swapInfo": {
"ammKey": "BONDING_CURVE_ADDRESS",
"label": "pump-curve",
"inputMint": "So11111111111111111111111111111111111111112",
"outputMint": "TOKEN_MINT",
"inAmount": "99950000",
"outAmount": "3519164015687",
"feeAmount": "1233952",
"feeMint": "So11111111111111111111111111111111111111112"
},
"percent": "100",
"bps": "10000"
}
],
"feeMint": "So11111111111111111111111111111111111111112",
"feeBps": "5",
"inputMint": "So11111111111111111111111111111111111111112",
"outputMint": "TOKEN_MINT",
"txn": "AQAAAAAAAAAAAAAAAAAAAAAA..."
}
How the numbers fit together:
amount_inis 100000000 lamports. The 5 bps platform fee is 50000 lamports, paid by a SOL transfer insidetxn, sosrcAmountInis 99950000.- Of
srcAmountIn, 1233952 lamports is pump.fun's protocol and creator fee (feeAmount), and the other 98716048 lamports buy on the curve. destAmountOutis 3519164015687 raw units: 3,519,164.015687 tokens at pump.fun's 6 decimals.destAmountOutMinisdestAmountOutless 20%, themin_tokens_outthe pump.fun instruction enforces.
Selling that balance back is the same request with the mints swapped and the token amount as amount_in:
curl --request GET \
--url 'https://api.carbium.io/api/v2/quote?src_mint=TOKEN_MINT&dst_mint=So11111111111111111111111111111111111111112&amount_in=3519164015687&slippage_bps=1000&user_account=YOUR_WALLET&fft=1' \
--header 'X-API-KEY: YOUR_API_KEY'
With no other trades on the curve in between, that sell answers routePlan[].swapInfo.outAmount 97482095, the SOL pump.fun pays out after its fee, and destAmountOut 97433354. The 48741 lamport difference is the 5 bps platform fee.
🔶 Start with Q1 for the base quote flow, add
fft=1for pump.fun tokens on their bonding curve, then move into Executing Swaps to sign and submit. For platform setup, start at carbium.io.