For authentication, error codes, and request conventions, see API Overview.
GET /v1/orchestration/routes
List all supported trading pairs. No authentication required.(sourceChain, sourceAsset) -> (destinationChain, destinationAsset) pair that can be used with /estimate, /quote, and /submit. The list is derived from the pipeline route resolver and stays in sync automatically as new pairs are added. It covers both the canonical BTC/USDB routes and the cross-chain (non-BTC) planner routes, sorted BTC-zone first; cross-chain pairs are exact-in only and never fixed-eligible.
Each route carries two eligibility booleans: exactOutEligible (the pair accepts amountMode=exact_out) and fixedEligible (the pair can support deliveryMode=fixed, subject to per-partner configuration; see Fixed delivery).
Each route includes source and destination detail objects:
GET /v1/orchestration/limits
Amount limits per route. Call this before quoting to pre-validate amounts instead of hardcoding bounds in your integration. No authentication required; rate limited to 60 requests per minute per IP./limits covers the canonical routes. Cross-chain planner routes appear on /routes but not on /limits today.
The response is
{ generatedAt, routes: [...] }. Each entry extends the /routes pair shape with direction ("buy" or "sell") and a limits object.
Response (filtered to bitcoin:BTC -> solana:USDC):
orderNotionalUsdis the operator-tuned USD notional bound for the route’s direction (source: "runtime_order_bounds"). Treat this endpoint as authoritative; the values change without notice.exactInandexactOuteach reportsupported, arequestAmountrange for the amount you would send in that mode (source leg for exact-in, destination leg for exact-out), and the IDs of theconstraintsentries that apply to that mode.fiatUsdreports theamountFiatUsdband (50,000.00) and thesurfacesthat accept it (onramp,pay_link). It is non-null only onlightning:BTCsource routes.dynamicProviderLimitsflags routes where provider-backed legs (components) impose additional quote-time limits. A live/estimateor/quotecan still returnamount_too_small,amount_too_large,amount_exceeds_liquidity, orroute_unavailableon these routes even when the static bounds pass.constraintsis a typed list of every limit on the route.sourcevalues:runtime_order_bounds,flashnet_static_limit,bitcoin_l1_delivery,provider_quote,fiat_amount. The sample above shows one static limit; read the live values from this endpoint instead of hardcoding them.
GET /v1/orchestration/estimate
Lightweight price preview. This does not create a quote and does not create a durable order. Use/estimate for price display and browsing: it is public, stateless, allocates no deposit address, and is safe to call on every input change within its 120 requests per minute per IP limit. Use /quote only when the user has committed to the swap: it is authenticated and idempotent, persists the quote, allocates a deposit address, and starts a 2 minute expiry.
/estimate requires no API key. Client keys (fnp_) cannot pass the fee fields (appFees, affiliateId, affiliateIds) on this endpoint.
Authentication is optional. When an
Authorization header is provided, affiliateId and affiliateIds are resolved against partner-scoped affiliate profiles.
Response:
roundingFeeAmountappears only when nonzero.deliveryModeappears only when fixed delivery applies (see Fixed delivery).appFeeAmount,appFeePlatformCutAmount, andappFeesappear only whenappFees,affiliateId, oraffiliateIdswas provided:
feeAssetisUSDCfor most routes,USDBforBTC -> USDB, andBTCfor direct Lightning passthrough routes such aslightning:BTC -> spark:BTC.totalFeeAmountequalsfeeAmount + roundingFeeAmount + appFeeAmount. Estimate totals never include sweep fees; those appear only on/quote.estimatedOutreflects the final amount after all fees (platform + app) are deducted.roundingFeeAmountis stablecoin surplus retained when output is capped to a whole-cent or exact-out target. It appears only when nonzero.- For partner invoice billing,
feeAmountcan be"0"because the platform fee is billed after settlement instead of deducted from the transaction. Fees owed are visible throughGET /v1/partner/dashboard/fee-invoices. - App fees follow the same deduction order as
/quote: platform fee first, then app fees, before the swap (buy direction) or after the swap (sell direction). - Fee plans follow the same route scope as
/quote: any route with a supported fee settlement. Routes with no resolvable settlement (pure BTC-to-BTC,feeAssetBTC) return400 unsupported_fee_plan. - The same validation rules apply as
/quote:appFeesandaffiliateId/affiliateIdsare mutually exclusive, max 16 entries, sum of bps must be<= 10000.
POST /v1/orchestration/quote
Request a durable quote with deposit instructions. Quotes expire 2 minutes after creation./quote is the execution step, not the browsing step. Price with /estimate while the user is deciding; call /quote once, when they commit. Every /quote call persists a quote and allocates a deposit address.Fixed delivery (deliveryMode)
deliveryMode accepts "variable" (default) or "fixed". Fixed delivery makes the quoted estimatedOut a delivery commitment rather than an estimate: the order delivers the quoted amount.
- Requires
amountMode=exact_in. Any other mode returns400 unsupported_delivery_mode. - Only routes with
fixedEligible: trueon/routessupport it, and availability additionally depends on per-partner operator configuration. Cross-chain routes never support it. - When fixed delivery does not apply,
/quoteand/estimatereject withfixed_delivery_unavailable(the error message states the reason), while/onrampsilently proceeds as a normal variable onramp. - The response echoes
deliveryMode: "fixed"only when fixed delivery applies. Treat its absence as a variable quote.
/estimate and /onramp accept the same field with the same semantics.
Exact-out payment-intent example (bitcoin:BTC -> base:USDC):
-> lightning:BTC):
spark:BTC -> solana:USDC):
spark:BTC -> solana:USDC):
spark:BTC -> solana:USDC):
spark:BTC -> solana:USDC):
affiliateIds can be either plain strings or { affiliateId, feeBps } objects. String entries resolve fee bps from the affiliate’s registered profile. Object entries override the profile’s fee bps for that quote only, without mutating the stored profile. Both forms can be mixed in the same request.
Exact-in source-side affiliate-fee example (solana:SOL -> spark:BTC):
amountModedefaults toexact_in.amountMode=exact_outis supported on routes withexactOutEligible: trueon/routes.- Stablecoin exact-out amounts must be whole-cent values. A non-cent value returns
400 invalid_request. refundAddressis required whenamountMode=exact_out.- If
Authorizationis included, sendX-Idempotency-Key. appFees,affiliateId, andaffiliateIdsare accepted in both amount modes on any route with a supported fee settlement (see the settlement resolution rules under “Affiliate fee models” below). Routes with no resolvable settlement, meaning pure BTC-to-BTC routes such aslightning:BTC -> bitcoin:BTC, reject fee plans with400 unsupported_fee_plan(“appFees require a route with supported fee settlement”).appFeesmax length is16.- Each
appFees[i].feeis fee bps (1..10000). - Sum of all app fee bps must be
<= 10000. affiliateIdandaffiliateIdsmust match^[a-z0-9][a-z0-9_-]{0,63}$after trimming and lowercasing.- Use either
appFeesoraffiliateId/affiliateIds, not both; sending both returns400 invalid_request.affiliateIdandaffiliateIdscan both be provided; they are merged (withaffiliateIdtreated as a single-element list). affiliateIdsaccepts up to 16 entries per quote. Each entry is either a plain affiliate ID (fee bps comes from the registered profile) or an object{ affiliateId, feeBps }that overrides the profile’s fee bps for that quote only. The sum of all effective affiliate fee BPS must be<= 10000.affiliateIdandaffiliateIdsrequire authenticated quote requests.slippageBpsdefaults to50when omitted (200for NEAR-ingress sources).- ZeroConf offers are not quote response fields. For eligible Bitcoin L1 exact-in orders, a
zeroconfOffermay appear on the order after the Bitcoin transaction is detected. - For
destinationChain = lightning,recipientAddressmust be a BOLT11 invoice. Inexact_inmode, the invoice must be amountless (0-amount). Inexact_outmode, the invoice can be amountless or encode an amount matching the requestedamountin sats.
- Inline recipients:
appFees: [{ recipient: string, fee: number }]feeis fee bps per recipient (1..10000).
- Registry by id (single):
affiliateId: string- profile is managed through
PUT /v1/affiliates/:affiliateId - quote resolves recipient + fee bps from your partner-scoped profile
- Registry by ids (multiple):
affiliateIds: Array<string | { affiliateId: string, feeBps: number }>- string entries resolve recipient and fee bps from the registered profile
- object entries resolve recipient from the registered profile but use the per-quote
feeBpsoverride instead of the profile’s bps; the stored profile is not mutated - fees from all affiliates are applied to the order; each affiliate accumulates their share independently and claims separately
- Settlement chain and asset are determined by the route via
resolveFeeSettlement:- Settles on
solana:USDCwhen either side is Solana, an EVM/relay chain, or a provider-bridged destination such as TON. - Settles on
spark:USDBwhen either side isspark:USDBand no chain from thesolana:USDCrule is involved. - Pure BTC-to-BTC routes (e.g.
lightning:BTC -> bitcoin:BTC) have no resolvable settlement and reject fee plans with 400unsupported_fee_plan.
- Settles on
- Execution point:
- If the source chain matches the settlement chain (e.g. solana source on
solana:USDCsettlement), fees are deducted on the source-side stablecoin leg before bridge/swap continuation. - If the source chain does not match the settlement chain, fees are deducted on whichever stablecoin leg the route exposes: typically the destination-side USDC payout leg for sells, or the bridge leg for supported chain payouts.
- If the source chain matches the settlement chain (e.g. solana source on
- For source-native routes like
SOL -> BTCandETH -> BTC, fees are deducted on the stablecoin leg after ingress conversion (SOL|ETH -> USDC). - Quote math order:
- platform fee (
feeAmount) - optional sweep fee (
sweepFeeAmount, USDC-source routes only) - app fee allocation (
appFeeAmount,appFees) - 20% platform cut retained from each app fee (
appFeePlatformCutAmount); remaining 80% goes to the fee recipient - net amount proceeds to route execution
- platform fee (
- Flashnet retains 20% of each app/affiliate fee. The quote response shows the split per recipient:
amount(gross fee charged to the user),platformCutAmount(20% retained by Flashnet), andrecipientAmount(80% paid to the fee recipient). appFeesrecipients are validated against the settlement-chain address format.- For
affiliateIdandaffiliateIds, the affiliate profile must have apayoutAddressconfigured (set viaPUT /v1/affiliates/:affiliateId). The payout chain/asset can be any destination supported by the live route table, not just base or solana.
depositAddressdepends onsourceChain:- EVM and Solana sources: chain address that receives the source asset
spark: Spark address that receives BTC or USDBbitcoin: Bitcoin L1 addresslightning: BOLT11 invoice to pay
totalFeeAmountequalsfeeAmount + roundingFeeAmount + appFeeAmount + sweepFeeAmount.roundingFeeAmountandsweepFeeAmountappear in the response only when nonzero.sweepFeeAmountis returned on some USDC-source routes when a sweep fee is configured.roundingFeeAmountis returned when stablecoin surplus is retained instead of delivered.appFeeAmountandappFeesare returned whenappFeesoraffiliateIdwas requested.appFeePlatformCutAmountis the sum of Flashnet’s 20% cut across all app fees.appFees[*].amountis the gross fee in settlement-chain USDC smallest units (what the user pays).appFees[*].platformCutAmountis Flashnet’s 20% cut of that fee.appFees[*].recipientAmountis the 80% paid to the fee recipient.appFees[*].affiliateIdis present when the quote usedaffiliateId.lightningReceiveRequestIdis only present forsourceChain = lightningquotes.feeAssetisUSDBforBTC -> USDBquotes,BTCfor direct Lightning passthrough quotes, andUSDCotherwise.targetAmountOut,requiredAmountIn,maxAcceptedAmountIn, andinputBufferBpsare present for exact-out quotes.inputBufferBpsis currently2whenslippageBps=0, otherwise0.
POST /v1/orchestration/submit
Create an order from a quote after you have initiated the source deposit.
The request body shape depends on
sourceChain. Each source chain uses a different subset of these fields. See the examples below.
Headers:
sourceChain.
Base/Solana sources (sourceChain = base|solana):
sourceAddress is optional but recommended. It is required when depositing to a shared address. When present, deposit verification requires the sender to match.
Spark sources (sourceChain = spark):
sourceSparkAddress is optional but recommended. It is required when depositing to a shared Spark address. When present, deposit verification requires the sender to match.
Bitcoin L1 sources (sourceChain = bitcoin):
bitcoinVout is optional. When omitted, the engine resolves it by scanning the transaction outputs for the one that pays the quote’s deposit address. You can still provide it explicitly if needed.
Lightning sources (sourceChain = lightning):
lightningReceiveRequestId can be omitted. When omitted, the API uses the value embedded in the quote.
The txHash field is validated per source chain:
- EVM chains:
0x-prefixed 64-character hex string - Solana: Base58-encoded signature (64-90 characters)
- Bitcoin: 64-character hex transaction ID
- Spark: UUID format, 32-character hex, or 64-character token transaction hash
- Lightning: Automatically populated from the quote’s receive request ID
(sourceChain, sourceTxHash[, sourceTxVout]), submit returns the existing { orderId, status }.
POST /v1/orchestration/onramp
Combined quote and submit for Lightning sell flows. Creates a Lightning invoice and order in a single call. Designed for fiat onramp integrations where the user pays via a Lightning-compatible app. The source is alwayslightning:BTC. Supported destinations are the lightning:BTC source pairs on GET /v1/orchestration/routes. The amount field is BTC in sats.
Request body:
amountMode=exact_outis supported where thelightning:BTCpair hasexactOutEligible: trueon/routes. The direct BTC passthrough destinations do not support it.- Stablecoin exact-out amounts must be whole-cent values. For 6-decimal stables, send multiples of
10000, for example"50000000"for $50.00. - Affiliate fees require a stablecoin settlement path and are not supported on the direct BTC passthrough routes.
paymentLinks.cashApp URL is a deeplink that opens a Lightning-compatible payment app to pay the invoice. On mobile, redirect the user to this URL. On desktop, display it as a QR code.
paymentLinks.shortUrl is a short redirect URL that 302s to the payment deeplink. Use this when sharing payment links in text messages, emails, or other contexts where the full URL is too long. The short URL is always present when PUBLIC_BASE_URL is configured on the server.
The Lightning invoice expires at expiresAt: 24 hours from creation for exact-in, 5 minutes for exact-out and for fixed-delivery exact-in. If the user doesn’t pay in time, create a new onramp order.
Field notes:
feeBpsreflects the platform fee rate for the specific route.feeAssetisBTCfor the direct BTC passthrough routes,USDBforlightning:BTC -> spark:USDB, and the destination-side stable asset for most other routes.routeis the asset path, not the pipeline step list.- For
lightning:BTC -> bitcoin:BTC, the final on-chain withdrawal also pays the network withdrawal fee quoted at delivery time. That fee is separate from Flashnet’s platform fee.
GET /v1/orchestration/order
Look up a quote and its associated order by quote ID. Designed for submissionless flows where partners poll after creating a quote and directing a user to deposit. Returns the quote state alongside the order. When no order exists yet (deposit not detected),order is null and the quote’s expired field indicates whether the deposit window is still open.
Response when no order exists yet:
order object uses the same shape as GET /v1/orchestration/status, including optional swap, paymentIntent, zeroconfOffer, feePlan, and feePayouts metadata when present.
Polling pattern for submissionless flows:
- Create a quote via
POST /v1/orchestration/quote. - Direct the user to deposit to
depositAddress. - Poll
GET /v1/orchestration/order?quoteId=q_...untilorderis non-null. - Once
orderappears, continue polling or switch to webhooks to track execution.
quote.expired is true and order is still null, no deposit has been detected yet. Expired quotes that receive a late deposit are always repriced at the live market rate at detection time and create an order; execution is still bounded by the quote’s slippageBps.
GET /v1/orchestration/status
Check an order’s current state. Authentication is optional:- Without
Authorization: returns a redacted order record. - With
Authorization: returns the full order record for your partner only.
txHash lookup returns the most recently created order with that sourceTxHash. For Bitcoin L1 deposits where multiple orders can share the same txid, prefer id from webhooks for exact attribution.
Possible order.status values:
processingconfirmingbridgingswappingawaiting_approvalrefundingdeliveringcompletedfailedexpiredunfulfilledrefunded
paused orders are returned as processing on partner-visible status responses.
Response (authenticated):
Authorization, the order object is the full public operation record. Without it, some fields are omitted.
amountIn and feeAmount reflect the actual processed deposit. When the on-chain deposit differs from the original quote, the engine updates these fields before execution. Any positive deposit amount is accepted. The stages array will include amount_reconciled when this adjustment occurred.
Depending on route and progress, the order can include:
flashnetRequestIdwhen a Flashnet swap has executedsparkTxHashwhen a Spark transfer, withdrawal, or Lightning action is createdswapmetadata when a Flashnet swap leg has been recordedpaymentIntentmetadata for exact-out orderszeroconfOfferwhen a ZeroConf offer has been generated for a Bitcoin L1 deposit (see ZeroConf offer fields)feePlanwhen quote-levelappFeesoraffiliateIdwas requestedfeePayoutsas affiliate and recipient payout legs are executedfeePayouts.entries[*].roleisapp_fee,recipient_payout,platform_fee, orfee_custodyfeePayouts.entries[*].affiliateIdis present for app-fee entries derived fromaffiliateIdfeePayouts.entries[*].legisfullfor a completed recipient or fee-custody transfer,holdbackfor an affiliate fee retained for a later claim, or legacyinstanton historical multi-leg records. It is unrelated to ZeroConf.supersededByOperationIdon an order leftunfulfilledwhose Bitcoin deposit was replaced (e.g. RBF’d) and recovered by a later order — the id of that successor order. See Recovered (superseded) orders.recoveredFromOperationIdon a successor order that recovered a replaced deposit — the id of the originalunfulfilledorder it took over.
GET /v1/orchestration/history
List your orders filtered byrecipientAddress.
Response:
GET /v1/orchestration/status, including optional swap, paymentIntent, and zeroconfOffer metadata when present.