Build Transaction
POST /api/v1/swap builds a complete unsigned transaction for a token swap. Sign it with the user’s wallet and submit to the network.
Request
User’s wallet address (base58). This wallet signs and pays for the transaction.
Input token mint address.
Output token mint address.
Amount in smallest token units.
Slippage tolerance in basis points. Default: 50 (0.5%).
Skip transaction simulation. Faster but no pre-flight validation. Only set true if you handle validation yourself.
Example
curl -X POST "https://api.vulcx.xyz/api/v1/swap" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $VULCX_KEY " \
-d '{
"userWallet": "9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM",
"inputMint": "So11111111111111111111111111111111111111112",
"outputMint": "uSd2czE61Evaf76RNbq4KPpXnkiL3irdzgLFUMe3NoG",
"amount": "1000000000",
"swapMode": "ExactIn",
"slippageBps": 50
}'
const response = await fetch ( "https://api.vulcx.xyz/api/v1/swap" , {
method: "POST" ,
headers: {
"Content-Type" : "application/json" ,
Authorization: `Bearer ${ process . env . VULCX_KEY }` ,
},
body: JSON . stringify ({
userWallet: wallet.publicKey. toBase58 (),
inputMint: "So11111111111111111111111111111111111111112" ,
outputMint: "uSd2czE61Evaf76RNbq4KPpXnkiL3irdzgLFUMe3NoG" ,
amount: "1000000000" ,
swapMode: "ExactIn" ,
slippageBps: 50 ,
}),
});
const { success , data , error } = await response. json ();
if ( ! success) throw new Error (error);
console. log ( `Transaction built. Expires at block ${ data . lastValidBlockHeight }` );
import os, requests
resp = requests.post(
"https://api.vulcx.xyz/api/v1/swap" ,
json = {
"userWallet" : "9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM" ,
"inputMint" : "So11111111111111111111111111111111111111112" ,
"outputMint" : "uSd2czE61Evaf76RNbq4KPpXnkiL3irdzgLFUMe3NoG" ,
"amount" : "1000000000" ,
"swapMode" : "ExactIn" ,
"slippageBps" : 50 ,
},
headers = { "Authorization" : f "Bearer { os.environ[ 'VULCX_KEY' ] } " },
)
result = resp.json()
if not result[ "success" ]:
raise Exception (result[ "error" ])
data = result[ "data" ]
print ( f "Transaction built. Expires at block { data[ 'lastValidBlockHeight' ] } " )
Response
{
"success" : true ,
"data" : {
"transaction" : "AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAHEAo..." ,
"lastValidBlockHeight" : 245832190 ,
"amountIn" : "1000000000" ,
"amountOut" : "145320000" ,
"minAmountOut" : "144593400" ,
"feeAmount" : "0" ,
"simulation" : {
"success" : true ,
"logs" : [],
"computeUnitsConsumed" : 85000 ,
"insufficientFunds" : false ,
"slippageExceeded" : false
},
"computeUnitsEstimate" : 85000 ,
"route" : [
"So11111111111111111111111111111111111111112" ,
"uSd2czE61Evaf76RNbq4KPpXnkiL3irdzgLFUMe3NoG"
],
"hopCount" : 1 ,
"pools" : [ "HJPjoWUrhoZzkNfRpHuieeFk9WcZWjwy6PBjZ81ngndJ" ],
"isSplitRoute" : false
}
}
Response fields
Base64-encoded unsigned transaction. Deserialize, sign, and submit.
Transaction expires after this block height (~60 seconds from creation).
Input amount in smallest units.
Estimated output amount in smallest units.
Minimum output after slippage (ExactIn only). Transaction reverts if actual output is less.
Maximum input after slippage (ExactOut only). Transaction reverts if actual input exceeds this.
Aggregator fee in output token units.
Simulation result (omitted if skipSimulation: true). Show SimulationResult fields
Whether the simulation passed.
CU used during simulation.
Error message if simulation failed.
Wallet doesn’t have enough balance.
Price moved beyond tolerance.
Estimated compute units for execution.
Token path from input to output.
Pool addresses used, in execution order.
Whether liquidity is split across multiple pools.
Percentage split per pool (only if isSplitRoute is true).
Simulation
By default, the API simulates the transaction before returning it. This catches common issues early:
simulation fieldMeaning What to do insufficientFunds: trueWallet doesn’t have enough tokens or FOGO for fees Show balance error to user slippageExceeded: truePrice changed between quote and transaction build Retry with a fresh quote success: false + errorOther simulation failure Check logs for details
Set skipSimulation: true only if you need lower latency and handle validation yourself.
What’s next
After receiving the transaction, sign and submit it .