Skip to main content

Firm Quotes

Every quote Vulcx serves carries a quoteId — 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

ModeRequestWhat’s enforcedWindow
Re-quote (default)no quoteIdA fresh quote at build time; min-out = fresh quote − slippageBps
Route-pinnedquoteIdThe exact quoted route; min-out = quoted price − slippageBpsvalidForMs (~3 s)
FirmquoteId + "firm": trueThe exact quoted route; min-out = quoted price − firm margin (~10 bps). Drift past the margin fails with 409 before buildingfirmForMs (~400 ms)

Where quoteIds come from

GET /api/v1/quote responses and every WebSocket quote push include:
quoteId
string
The commitment ID, e.g. q_b15372a8d82a93d1e328ae24e5d3669a. Omitted when the quote can’t be pinned (e.g. split routes).
validForMs
integer
How long the quoteId stays redeemable (default 3000).
firmForMs
integer
How long it stays redeemable with firm: true (default 400).
A 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)

The returned transaction’s 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 slippageBps is ignored.
  • Price drifted past the margin409 Conflict, no transaction is built, and you can re-quote and retry in one round-trip. Favorable drift always passes.
The firm window is sub-second (~400 ms ≈ ten Fogo blocks). It’s designed for machine flows — session-key signing, bots, protocol integrations — where quote → sign → submit completes in tens of milliseconds. A human confirming a wallet popup can’t beat it; use route pinning (seconds-long) for popup flows.
Both POST /api/v1/swap and POST /api/v1/instructions accept quoteId and firm identically.

Error contract

StatusMeaningWhat to do
410 GonequoteId expired (past validForMs, or past firmForMs for firm), evicted, or unknownRe-quote, retry with the fresh quoteId
409 ConflictPinned route no longer exists — or, with firm, price drifted past the marginRe-quote, retry; for firm, retry immediately
403 ForbiddenquoteId was minted under a different API keyRe-quote with your own key
400 Bad RequestPair, amount, or swapMode don’t match the quote — or firm without a quoteIdSend the exact quoted request
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. The widget does this automatically.

Live invalidation on the stream

If you subscribe to the WebSocket stream, the server pushes
when the last quote it broadcast for a pair drifts past the firm margin — so your UI can stop offering the firm price the instant it dies instead of discovering it at redemption. It’s best-effort sugar: the redemption-time check is the real gate.

Why this works on Fogo

Fogo’s ~40 ms blocks mean a 400 ms firm window spans ~10 blocks of runway, and quote → commit round-trips fit inside it with session-key signing. The quoted price is enforced on-chain by the aggregator program’s balance-delta check — if the pool moved past your min-out between build and execution, the transaction fails rather than filling worse. Worst case is a failed transaction, never a worse price.
Last modified on July 15, 2026