justi.fun
§06 · API

Trade API

Quote, build, sign, submit and track swaps on the curve and on DAMM v2.

The flow

  1. Quote (optional): GET /v1/quote?mint&side&amount. Buys take lamports in, sells take raw token units (6 decimals).
  2. Build: POST /v1/swap. The server quotes fresh, builds, simulates, then sets the compute limit to the simulated use x 1.2 + 5000 and the priority fee ("auto" by default).
  3. Sign the base64 v0 transaction in the wallet. Wallets may add their own instructions; the swap instruction must stay as built.
  4. Submit: POST /v1/submit. It is rebroadcast every 2 s (and sent to Jito when built with a tip) until it confirms, fails or expires. Or send it with your own RPC: the trade is indexed either way.
  5. Track: GET /v1/swaps/{id} or GET /v1/tx/{signature}.
const r = await justi.buy({ mint, sol: 0.25, signer: wallet, slippageBps: 800 });
if (r.status === "failed" && r.error?.code === "slippage") {
  // retry with r.error.suggestSlippageBps
}

Routes

routeWhen
curveBefore graduation: a direct Meteora DBC swap.
dammAfter graduation: a direct swap on the coin's Meteora DAMM v2 pool.
jupiterOnly as a fallback (fallback: true) when a direct build fails for a reason that is not the trader's, or between curve full and migrated if Jupiter has a route. Otherwise that short window answers graduating (409).

Measured on mainnet by simulation: a curve buy is about 660 bytes and 50,000 compute units; a DAMM v2 swap about 680 to 730 bytes and 36,000 to 42,000 units.

Fee parts

Every quote has fee.total and fee.parts, which sum to the total: creator, holders, platformBurnJusti, platformWallet, sniperBurnCoin, sniperBurnJusti, sniperPlatform, meteora, liquidityProviders, referral. In the sniper window, fee.windowSecondsLeft and fee.windowExtra show the opening fee. On DAMM v2 the fee goes to the locked LP positions and Meteora, and a both-token pool takes the buy fee in the coin (fee.token = "TOKEN").

When a trade fails

A trade that fails on chain is a 200 from submit with status: "failed" and error.code. For slippage, error.suggestSlippageBps is the slippage that would have passed. An expired blockhash gives expired: build again.

Submit answer
{ "swapId": "...", "status": "failed", "signature": "...", "mint": "...", "side": "buy", "route": "curve",
  "error": { "code": "slippage", "message": "The price moved past your slippage. Try again with a little more room.", "suggestSlippageBps": 1500 } }

Reference

#Quote a buy or sell (exact in) on the curve or the DAMM v2 pool

GET/v1/quote
Key optionalRate class quotegetQuote

Parameters

NameTypeAbout
mintrequiredqueryaddress
siderequiredquery"buy" | "sell"buy: SOL in, coin out. sell: coin in, SOL out.
amountrequiredqueryu64 stringLamports to spend on a buy, raw tokens to sell.
slippageBpsqueryintegerBasis points, 10 to 5000. Default 1000 (10%).
Response Quote
FieldTypeAbout
mintrequiredaddress
siderequired"buy" | "sell"buy: SOL in, coin out. sell: coin in, SOL out.
routerequired"curve" | "damm" | "jupiter"curve: DBC swap. damm: direct DAMM v2 swap. jupiter: fallback only.
fallbackrequiredbooleantrue when Jupiter stands in for a failed direct route.
amountInrequiredu64 stringLamports for a buy, raw tokens for a sell. Fee included.
expectedOutrequiredu64 stringUnsigned integer as a decimal string (may exceed 2^53).
minOutrequiredu64 stringexpectedOut less slippage; the swap fails below it.
slippageBpsrequiredinteger
priceImpactPctrequirednumber
priceSolrequirednumberSpot before the trade, SOL per whole token.
priceAfterSolrequirednumber
marketCapSolrequirednumber
curveProgressPctrequirednumber | null
feerequiredobject
tokenrequired"SOL" | "TOKEN"The side the fee is taken in. DAMM v2 pools in both-token mode take the buy fee in the coin.
totalrequiredu64 stringRaw units of fee.token.
totalLamportsrequiredu64 stringThe fee as lamports (token fees valued at spot).
pctrequirednumberFee as percent of the trade on the fee side.
windowSecondsLeftrequiredintegerSeconds left in the opening sniper window.
windowExtrarequiredu64 stringPart of total above the normal tier fee (sniper window).
partsrequiredobjectWhere the fee goes. Sums to total.
nowrequiredintegerUnix time in seconds.
Errors400 bad_request, invalid_params401 unauthorized404 not_found409 graduating429 rate_limited500 internal502 upstream_error503 unavailable
curl "https://api.justi.fun/v1/quote?mint=<mint>&side=buy&amount=100000000"

#Build an unsigned v0 swap transaction for a wallet

POST/v1/swap
Key optionalRate class buildBody 8kbbuildSwap

Quotes fresh, builds, simulates and sets the compute limit. Sign the returned transaction with the wallet and send it to POST /v1/submit (or send it yourself). The wallet may add instructions, but the swap instruction must stay as built.

Body

FieldTypeAbout
mintrequiredaddress
walletrequiredaddressFee payer and signer.
siderequired"buy" | "sell"buy: SOL in, coin out. sell: coin in, SOL out.
amountrequiredu64 stringLamports to spend on a buy, raw tokens to sell.
slippageBpsintegerBasis points, 10 to 5000. Default 1000 (10%).
priorityFee"auto" | integer"auto" (Helius estimate or recent fees on the pool) or micro-lamports per compute unit. default "auto"
computeUnitLimit"auto" | integer"auto": simulated use x 1.2 + 5000. default "auto"
jitoTipLamportsu64 stringAdds a tip transfer to a Jito tip account; submit then also sends through Jito. 0 or 1000 to 100000000.
Response SwapBuilt
FieldTypeAbout
swapIdrequiredstringUUID.
routerequired"curve" | "damm" | "jupiter"
fallbackrequiredboolean
quoterequiredQuote
mintrequiredaddress
siderequired"buy" | "sell"buy: SOL in, coin out. sell: coin in, SOL out.
routerequired"curve" | "damm" | "jupiter"curve: DBC swap. damm: direct DAMM v2 swap. jupiter: fallback only.
fallbackrequiredbooleantrue when Jupiter stands in for a failed direct route.
amountInrequiredu64 stringLamports for a buy, raw tokens for a sell. Fee included.
expectedOutrequiredu64 stringUnsigned integer as a decimal string (may exceed 2^53).
minOutrequiredu64 stringexpectedOut less slippage; the swap fails below it.
slippageBpsrequiredinteger
priceImpactPctrequirednumber
priceSolrequirednumberSpot before the trade, SOL per whole token.
priceAfterSolrequirednumber
marketCapSolrequirednumber
curveProgressPctrequirednumber | null
feerequiredobject
nowrequiredintegerUnix time in seconds.
transactionrequiredstringBase64 unsigned v0 transaction.
bytesrequiredinteger
computeUnitsConsumedrequiredinteger | nullFrom the simulation.
computeUnitLimitrequiredinteger
priorityMicroLamportsrequiredinteger
jitoTipLamportsrequiredu64 stringUnsigned integer as a decimal string (may exceed 2^53).
lastValidBlockHeightrequiredinteger
Errors400 bad_request, slippage, insufficient_funds, chain_rejected, invalid_params, invalid_json401 unauthorized404 not_found409 graduating413 payload_too_large429 rate_limited500 internal502 upstream_error503 unavailable
curl -X POST "https://api.justi.fun/v1/swap" \
  -H "Content-Type: application/json" \
  -d '{"mint":"<mint>","wallet":"<wallet>","side":"buy","amount":"100000000","slippageBps":1000}'

#Relay a signed swap built by POST /v1/swap

POST/v1/submit
Key optionalRate class submitBody 16kbsubmitSwap

Checks it is paid and signed by the building wallet and carries the exact swap instruction built, then sends it (RPC rebroadcast every 2s, plus Jito when built with a tip) until confirmed, failed or expired. Answers when it settles or after waitMs (default 20000, max 25000) with status submitted; poll GET /v1/tx/{signature}. A trade that fails on chain is a 200 with status failed and an error.

Body

FieldTypeAbout
swapIdrequiredstringUUID.
transactionrequiredstringBase64 signed transaction. max 4000 chars
waitMsinteger0 to 25000
Response SwapStatus
FieldTypeAbout
swapIdrequiredstringUUID.
statusrequired"built" | "submitted" | "confirmed" | "failed" | "expired"
signaturerequiredstring | null
mintrequiredaddress
siderequired"buy" | "sell"buy: SOL in, coin out. sell: coin in, SOL out.
routerequiredstring
errorrequiredobject | null
coderequiredstring
messagerequiredstring
suggestSlippageBpsinteger
Errors400 tx_mismatch, signature_invalid, bad_request, invalid_params, invalid_json401 unauthorized404 not_found409 already_submitted413 payload_too_large429 rate_limited500 internal
curl -X POST "https://api.justi.fun/v1/submit" \
  -H "Content-Type: application/json" \
  -d '{"swapId":"<swapId>","transaction":"<signed base64 transaction>"}'

#Status of a swap built through the API

GET/v1/swaps/{id}
Key optionalRate class readgetSwap

Parameters

NameTypeAbout
idrequiredpathstringUUID.
Response SwapStatus
FieldTypeAbout
swapIdrequiredstringUUID.
statusrequired"built" | "submitted" | "confirmed" | "failed" | "expired"
signaturerequiredstring | null
mintrequiredaddress
siderequired"buy" | "sell"buy: SOL in, coin out. sell: coin in, SOL out.
routerequiredstring
errorrequiredobject | null
coderequiredstring
messagerequiredstring
suggestSlippageBpsinteger
Errors400 invalid_params401 unauthorized404 not_found429 rate_limited500 internal
curl "https://api.justi.fun/v1/swaps/<id>"

#Status of any transaction signature (and the swap or launch it belongs to)

GET/v1/tx/{signature}
Key optionalRate class readgetTransactionStatus

Parameters

NameTypeAbout
signaturerequiredpathsignatureBase58 transaction signature.
Response TxStatus
FieldTypeAbout
signaturerequiredsignatureBase58 transaction signature.
statusrequired"pending" | "confirmed" | "finalized" | "failed" | "unknown"unknown: the RPC has not seen it (not sent, dropped, or too old).
slotrequiredinteger | null
errorrequiredobject | nullThe on-chain error when failed.
kindrequired"swap" | "launch" | null
refIdrequiredstring | nullswapId or launchId when it was built here.
Errors400 invalid_params401 unauthorized429 rate_limited500 internal502 upstream_error
curl "https://api.justi.fun/v1/tx/<signature>"