Migrate from Jupiter to Carbium
Move a Jupiter-centered Solana swap integration to Carbium by mapping quote parameters, signing boundaries, execution ownership, and rollback checks.
Migrate from Jupiter to Carbium
If your current Solana trading flow is built around Jupiter Swap API, the migration is not "swap one hostname and keep the same request body."
Start by identifying which Jupiter surface your code depends on:
- legacy Metis-style quote and swap flows
- Ultra order and execute flows
- newer Swap API flows with managed execution or custom transaction paths
- token, price, trigger, recurring, or lending APIs that are not simple swaps
Carbium's published flow is narrower and more direct. The current public Swap API path centers on a quote request that can already return the executable transaction when you include user_account.
That difference is the whole migration. This page shows what maps cleanly, what needs a rewrite, and which Jupiter-specific product surfaces should stay separate until they have their own migration plan.
Part of the Carbium Solana infrastructure stack.
What changes in the migration
The main difference is execution ownership.
Jupiter's current developer docs present API families where Jupiter can handle more of the swap lifecycle, including order creation, execution, landing infrastructure, token services, and adjacent DeFi APIs. Jupiter also now points older Metis and Ultra flows toward newer Swap API migration paths.
Carbium's public docs focus the swap path around GET https://api.carbium.io/api/v2/quote, which can return a base64 txn when user_account is provided.
That makes the migration straightforward for quote-to-transaction builders, but not a 1:1 replacement for every Jupiter product surface.
| Jupiter surface | Carbium surface | Migration confidence |
|---|---|---|
| API-key authenticated quote request | API-key authenticated quote request | High |
| Quote request with input mint, output mint, amount, and slippage | Quote request with source mint, destination mint, amount, and slippage | High |
| Base64 transaction returned for client or backend signing | Base64 txn returned when user_account is provided | High |
| Sign and submit transaction with Solana SDK tooling | Sign and submit transaction through Carbium RPC | High |
| Jupiter-managed execute or landing flow | App-owned signing, submission, and confirmation | Medium |
| Jupiter token, price, trigger, recurring, lending, or limit-order APIs | No documented Carbium drop-in replacement in current public docs | Low |
For standard swap flows, the clean migration is to preserve the business logic around quote -> sign -> submit while replacing the request shape and removing provider-specific objects from the flow.
What does not map 1:1
Do not port these blindly:
| Jupiter capability | Current Carbium docs status | What to do |
|---|---|---|
Legacy Metis quoteResponse passed into a separate transaction-build request | Carbium's current docs emphasize GET /api/v2/quote with user_account returning txn directly | Rewrite the execution step instead of trying to preserve the same request choreography |
| Ultra-style order and execute flows | No Carbium-managed execute equivalent is documented in the current public swap guides | Treat this as an ownership change and prove app-owned submission before cutover |
| Jupiter options like custom payer, fee, destination-account, dynamic slippage, route filters, or transaction-size controls | No direct one-to-one mapping is published in Carbium's current Q1 guide | Validate each behavior individually before removing Jupiter from production |
| Token, price, trigger, recurring, lending, or limit-order APIs | Outside the current Carbium Swap API migration path | Keep them on Jupiter or assign a separate replacement owner |
The mistake to avoid is carrying over a Jupiter-centric internal abstraction and assuming Carbium will accept the same quote object and execution settings. It will not.
Migrate the plain swap path first. Keep non-swap Jupiter APIs on a separate workstream until you have a tested Carbium replacement or decide to keep them hybrid.
Endpoint and parameter mapping
Quote request
Jupiter's current Swap docs publish a quote request like:
GET https://api.jup.ag/swap/v1/quote- header:
x-api-key - query params such as
inputMint,outputMint,amount, andslippageBps
Carbium's live execution guide publishes:
GET https://api.carbium.io/api/v2/quote- header:
X-API-KEY - query params
src_mint,dst_mint,amount_in,slippage_bps user_accountwhen you want the response to include an executable transaction
| Intent | Jupiter param | Carbium param |
|---|---|---|
| Input token | inputMint | src_mint |
| Output token | outputMint | dst_mint |
| Raw amount | amount | amount_in |
| Slippage in basis points | slippageBps | slippage_bps |
| Wallet public key for executable transaction | passed later as userPublicKey to /swap | passed now as user_account to /quote |
Execution step
Many legacy Jupiter integrations build the executable transaction in a second request:
POST /swap
{
"userPublicKey": "...",
"quoteResponse": { "...": "..." }
}Carbium's current guide collapses that into the quote call. When user_account is included, the quote response contains txn, a base64-encoded VersionedTransaction ready for signing.
That means the migration usually looks like this:
- stop passing a Jupiter
quoteResponseinto a second swap-builder request - request the Carbium quote with
user_account - deserialize
txn - sign it
- submit it through Carbium RPC
Minimal rewrite example
Before: legacy Jupiter-style flow
const quoteUrl = new URL("https://api.jup.ag/swap/v1/quote");
quoteUrl.searchParams.set("inputMint", inputMint);
quoteUrl.searchParams.set("outputMint", outputMint);
quoteUrl.searchParams.set("amount", amountIn);
quoteUrl.searchParams.set("slippageBps", "50");
const quoteResponse = await fetch(quoteUrl, {
headers: { "x-api-key": process.env.JUP_API_KEY! },
}).then((r) => r.json());
const swapResponse = await fetch("https://api.jup.ag/swap/v1/swap", {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": process.env.JUP_API_KEY!,
},
body: JSON.stringify({
userPublicKey: wallet.publicKey.toBase58(),
quoteResponse,
}),
}).then((r) => r.json());After: Carbium-style flow
const quoteUrl = new URL("https://api.carbium.io/api/v2/quote");
quoteUrl.searchParams.set("src_mint", inputMint);
quoteUrl.searchParams.set("dst_mint", outputMint);
quoteUrl.searchParams.set("amount_in", amountIn);
quoteUrl.searchParams.set("slippage_bps", "50");
quoteUrl.searchParams.set("user_account", wallet.publicKey.toBase58());
const quote = await fetch(quoteUrl, {
headers: { "X-API-KEY": process.env.CARBIUM_API_KEY! },
}).then((r) => r.json());
if (!quote.txn) {
throw new Error("Missing executable transaction in Carbium quote response");
}
const transaction = VersionedTransaction.deserialize(
Buffer.from(quote.txn, "base64")
);
transaction.sign([wallet]);
const connection = new Connection(
`https://rpc.carbium.io/?apiKey=${process.env.CARBIUM_RPC_KEY}`,
"confirmed"
);
const signature = await connection.sendTransaction(transaction, {
skipPreflight: true,
maxRetries: 3,
});Safe cutover sequence
Use this order for production migrations:
- Inventory whether your Jupiter integration only uses quote and swap, or whether it also depends on managed execution, custom payer, fee collection, token metadata, price feeds, recurring orders, or limit-order controls.
- Create separate
CARBIUM_API_KEYandCARBIUM_RPC_KEYsecrets. - Rewrite the quote request shape first.
- Replace provider-specific transaction-build or execute steps with Carbium quote deserialization and RPC submission.
- Re-test confirmation, retry logic, and slippage handling under live market conditions.
- Validate any Jupiter-only advanced execution settings individually before removing the old path.
This keeps the migration narrow. Core swap execution can move first, while fee-routing or account-management edge cases stay isolated until verified.
Migration checklist
-
CARBIUM_API_KEYexists in your secret store -
CARBIUM_RPC_KEYexists for transaction submission - Jupiter quote parameters are translated to Carbium's
src_mint,dst_mint,amount_in, andslippage_bps - The execution path no longer assumes a Jupiter-specific
quoteResponse, order, or execute object -
user_accountis included on Carbium quote requests that need an executable transaction - Signed transactions are submitted through Carbium RPC and confirmed before replay
- Any Jupiter-specific payer, fee, destination-account, token, price, or order features have been re-tested explicitly or left hybrid
When Carbium is a good fit
Carbium is the cleanest next step when your current Jupiter integration is mainly:
- quote -> transaction -> sign -> submit
- backend-safe API-key usage
- wallet, bot, or app flows that can work with an executable transaction returned from the quote layer
It is not a one-line migration if your current integration depends heavily on Jupiter-specific execution controls that Carbium's public docs do not currently mirror on the same surface.
Treat this as a flow migration, not a field rename. The biggest change is architectural: Carbium's published guide returns
txnfrom the quote step when you passuser_account.
Ready to move your swap flow off Jupiter? Start with Q1 for the request shape, then use the Quote to Swap Integration Guide once the returned
txnis stable.
Updated 29 days ago
