Firm Quotes
Every quote Vulcx serves carries aquoteId — a short-lived commitment to the exact route and
price you were shown. Hand it back when you build the swap and the engine replays that route
instead of silently re-quoting, with your minimum-out anchored to the quoted price. Within a short
window you can go further and redeem the quote firm: slippage collapses to a few basis points
around the quoted price, and if the market moved past that, the API refuses before you pay a
transaction fee.
Firm redemption is price-or-fail, not a fill guarantee. If the pool genuinely moved, your
request fails cleanly with a
409 and you re-quote — you never execute at a worse price than you
committed to.The three ways to build a swap
Where quoteIds come from
GET /api/v1/quote responses and every WebSocket quote push include:
string
The commitment ID, e.g.
q_b15372a8d82a93d1e328ae24e5d3669a. Omitted when the quote can’t be
pinned (e.g. split routes).integer
How long the
quoteId stays redeemable (default 3000).integer
How long it stays redeemable with
firm: true (default 400).quoteId minted over REST is bound to your API key — only requests authenticated with the same
key can redeem it. Pair, amount, and swapMode must match the original quote exactly.
Route pinning (pass quoteId)
minAmountOut is computed from the quoted amountOut, not from a
fresh re-quote — what the user approved is what the chain enforces. Your slippageBps still
applies on top, so a route-pinned swap behaves exactly like today’s flow when the price hasn’t
moved, and refuses to quietly degrade when it has.
Firm redemption ("firm": true)
Within firmForMs of the quote, add "firm": true to the same request. The engine re-evaluates
the pinned route against live pool state:
- Price held (or improved) → the swap builds with slippage collapsed to the server’s firm
margin (default 10 bps) around the quoted price. Your
slippageBpsis ignored. - Price drifted past the margin →
409 Conflict, no transaction is built, and you can re-quote and retry in one round-trip. Favorable drift always passes.
POST /api/v1/swap and POST /api/v1/instructions accept
quoteId and firm identically.
Error contract
The SDK surfaces these as
QuoteExpiredError (410) and QuoteStaleError (409) — both
non-retryable as-is; catch them, re-quote, and retry with the new quoteId.
Signed quotes
Every quote that carries aquoteId also carries an Ed25519 signature over its price (when the
deployment has signing enabled — production does):
string
Base58 Ed25519 signature over the canonical quote message.
integer
The absolute expiry (unix milliseconds) embedded in the signed message.
exactIn as 0/1, and expiry in unix milliseconds.
The verification key is public and unauthenticated: