Skip to main content
For authentication, error codes, and request conventions, see API Overview.

GET /v1/orchestration/routes

List all supported trading pairs. No authentication required.
Response:
Each entry is a valid (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.
Query parameters (all optional, each narrows the returned list): 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):
Field notes:
  • orderNotionalUsd is 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.
  • exactIn and exactOut each report supported, a requestAmount range for the amount you would send in that mode (source leg for exact-in, destination leg for exact-out), and the IDs of the constraints entries that apply to that mode.
  • fiatUsd reports the amountFiatUsd band (1.00to1.00 to 50,000.00) and the surfaces that accept it (onramp, pay_link). It is non-null only on lightning:BTC source routes.
  • dynamicProviderLimits flags routes where provider-backed legs (components) impose additional quote-time limits. A live /estimate or /quote can still return amount_too_small, amount_too_large, amount_exceeds_liquidity, or route_unavailable on these routes even when the static bounds pass.
  • constraints is a typed list of every limit on the route. source values: 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.
Query parameters: Authentication is optional. When an Authorization header is provided, affiliateId and affiliateIds are resolved against partner-scoped affiliate profiles. Response:
Three field groups are conditional:
  • roundingFeeAmount appears only when nonzero.
  • deliveryMode appears only when fixed delivery applies (see Fixed delivery).
  • appFeeAmount, appFeePlatformCutAmount, and appFees appear only when appFees, affiliateId, or affiliateIds was provided:
  • feeAsset is USDC for most routes, USDB for BTC -> USDB, and BTC for direct Lightning passthrough routes such as lightning:BTC -> spark:BTC.
  • totalFeeAmount equals feeAmount + roundingFeeAmount + appFeeAmount. Estimate totals never include sweep fees; those appear only on /quote.
  • estimatedOut reflects the final amount after all fees (platform + app) are deducted.
  • roundingFeeAmount is stablecoin surplus retained when output is capped to a whole-cent or exact-out target. It appears only when nonzero.
  • For partner invoice billing, feeAmount can be "0" because the platform fee is billed after settlement instead of deducted from the transaction. Fees owed are visible through GET /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, feeAsset BTC) return 400 unsupported_fee_plan.
  • The same validation rules apply as /quote: appFees and affiliateId/affiliateIds are 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.
Request fields

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 returns 400 unsupported_delivery_mode.
  • Only routes with fixedEligible: true on /routes support it, and availability additionally depends on per-partner operator configuration. Cross-chain routes never support it.
  • When fixed delivery does not apply, /quote and /estimate reject with fixed_delivery_unavailable (the error message states the reason), while /onramp silently 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):
Exact-out Lightning example (any buy-side source -> lightning:BTC):
Exact-in affiliate-fee example (spark:BTC -> solana:USDC):
Exact-in affiliate-registry example (spark:BTC -> solana:USDC):
Exact-in with multiple affiliates (spark:BTC -> solana:USDC):
Exact-in with per-quote feeBps override (spark:BTC -> solana:USDC):
Entries in 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):
Notes:
  • amountMode defaults to exact_in.
  • amountMode=exact_out is supported on routes with exactOutEligible: true on /routes.
  • Stablecoin exact-out amounts must be whole-cent values. A non-cent value returns 400 invalid_request.
  • refundAddress is required when amountMode=exact_out.
  • If Authorization is included, send X-Idempotency-Key.
  • appFees, affiliateId, and affiliateIds are 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 as lightning:BTC -> bitcoin:BTC, reject fee plans with 400 unsupported_fee_plan (“appFees require a route with supported fee settlement”).
  • appFees max length is 16.
  • Each appFees[i].fee is fee bps (1..10000).
  • Sum of all app fee bps must be <= 10000.
  • affiliateId and affiliateIds must match ^[a-z0-9][a-z0-9_-]{0,63}$ after trimming and lowercasing.
  • Use either appFees or affiliateId/affiliateIds, not both; sending both returns 400 invalid_request. affiliateId and affiliateIds can both be provided; they are merged (with affiliateId treated as a single-element list).
  • affiliateIds accepts 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.
  • affiliateId and affiliateIds require authenticated quote requests.
  • slippageBps defaults to 50 when omitted (200 for NEAR-ingress sources).
  • ZeroConf offers are not quote response fields. For eligible Bitcoin L1 exact-in orders, a zeroconfOffer may appear on the order after the Bitcoin transaction is detected.
  • For destinationChain = lightning, recipientAddress must be a BOLT11 invoice. In exact_in mode, the invoice must be amountless (0-amount). In exact_out mode, the invoice can be amountless or encode an amount matching the requested amount in sats.
Affiliate fee models:
  • Inline recipients:
    • appFees: [{ recipient: string, fee: number }]
    • fee is 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 feeBps override 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:USDC when either side is Solana, an EVM/relay chain, or a provider-bridged destination such as TON.
    • Settles on spark:USDB when either side is spark:USDB and no chain from the solana:USDC rule is involved.
    • Pure BTC-to-BTC routes (e.g. lightning:BTC -> bitcoin:BTC) have no resolvable settlement and reject fee plans with 400 unsupported_fee_plan.
  • Execution point:
    • If the source chain matches the settlement chain (e.g. solana source on solana:USDC settlement), 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.
  • For source-native routes like SOL -> BTC and ETH -> 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
  • 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), and recipientAmount (80% paid to the fee recipient).
  • appFees recipients are validated against the settlement-chain address format.
  • For affiliateId and affiliateIds, the affiliate profile must have a payoutAddress configured (set via PUT /v1/affiliates/:affiliateId). The payout chain/asset can be any destination supported by the live route table, not just base or solana.
Response (exact-out sample):
Response (exact-in with appFees sample):
Response (exact-in source-side appFees sample):
Field notes:
  • depositAddress depends on sourceChain:
    • EVM and Solana sources: chain address that receives the source asset
    • spark: Spark address that receives BTC or USDB
    • bitcoin: Bitcoin L1 address
    • lightning: BOLT11 invoice to pay
  • totalFeeAmount equals feeAmount + roundingFeeAmount + appFeeAmount + sweepFeeAmount. roundingFeeAmount and sweepFeeAmount appear in the response only when nonzero.
  • sweepFeeAmount is returned on some USDC-source routes when a sweep fee is configured.
  • roundingFeeAmount is returned when stablecoin surplus is retained instead of delivered.
  • appFeeAmount and appFees are returned when appFees or affiliateId was requested.
  • appFeePlatformCutAmount is the sum of Flashnet’s 20% cut across all app fees.
  • appFees[*].amount is the gross fee in settlement-chain USDC smallest units (what the user pays).
  • appFees[*].platformCutAmount is Flashnet’s 20% cut of that fee.
  • appFees[*].recipientAmount is the 80% paid to the fee recipient.
  • appFees[*].affiliateId is present when the quote used affiliateId.
  • lightningReceiveRequestId is only present for sourceChain = lightning quotes.
  • feeAsset is USDB for BTC -> USDB quotes, BTC for direct Lightning passthrough quotes, and USDC otherwise.
  • targetAmountOut, requiredAmountIn, maxAcceptedAmountIn, and inputBufferBps are present for exact-out quotes.
  • inputBufferBps is currently 2 when slippageBps=0, otherwise 0.

POST /v1/orchestration/submit

Create an order from a quote after you have initiated the source deposit.
Request fields The request body shape depends on sourceChain. Each source chain uses a different subset of these fields. See the examples below. Headers:
Request body shape depends on the quote 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
Response:
If an order already exists for the same (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 always lightning:BTC. Supported destinations are the lightning:BTC source pairs on GET /v1/orchestration/routes. The amount field is BTC in sats.
Headers:
Request fields Request body:
Notes:
  • amountMode=exact_out is supported where the lightning:BTC pair has exactOutEligible: true on /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.
Response:
The 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:
  • feeBps reflects the platform fee rate for the specific route.
  • feeAsset is BTC for the direct BTC passthrough routes, USDB for lightning:BTC -> spark:USDB, and the destination-side stable asset for most other routes.
  • route is 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.
For the full integration guide with code examples, see Fiat Onramp.

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.
Headers:
Query parameters: Response when no order exists yet:
Response when an order has been created:
The 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:
  1. Create a quote via POST /v1/orchestration/quote.
  2. Direct the user to deposit to depositAddress.
  3. Poll GET /v1/orchestration/order?quoteId=q_... until order is non-null.
  4. Once order appears, continue polling or switch to webhooks to track execution.
When 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.
Provide exactly one query parameter: 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:
  • processing
  • confirming
  • bridging
  • swapping
  • awaiting_approval
  • refunding
  • delivering
  • completed
  • failed
  • expired
  • unfulfilled
  • refunded
Internal paused orders are returned as processing on partner-visible status responses. Response (authenticated):
With 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:
  • flashnetRequestId when a Flashnet swap has executed
  • sparkTxHash when a Spark transfer, withdrawal, or Lightning action is created
  • swap metadata when a Flashnet swap leg has been recorded
  • paymentIntent metadata for exact-out orders
  • zeroconfOffer when a ZeroConf offer has been generated for a Bitcoin L1 deposit (see ZeroConf offer fields)
  • feePlan when quote-level appFees or affiliateId was requested
  • feePayouts as affiliate and recipient payout legs are executed
  • feePayouts.entries[*].role is app_fee, recipient_payout, platform_fee, or fee_custody
  • feePayouts.entries[*].affiliateId is present for app-fee entries derived from affiliateId
  • feePayouts.entries[*].leg is full for a completed recipient or fee-custody transfer, holdback for an affiliate fee retained for a later claim, or legacy instant on historical multi-leg records. It is unrelated to ZeroConf.
  • supersededByOperationId on an order left unfulfilled whose Bitcoin deposit was replaced (e.g. RBF’d) and recovered by a later order — the id of that successor order. See Recovered (superseded) orders.
  • recoveredFromOperationId on a successor order that recovered a replaced deposit — the id of the original unfulfilled order it took over.

GET /v1/orchestration/history

List your orders filtered by recipientAddress.
Headers:
Query parameters: Response:
History entries use the same order shape as GET /v1/orchestration/status, including optional swap, paymentIntent, and zeroconfOffer metadata when present.