For authentication, error codes, and request conventions, see API Overview.
GET /v1/orchestration/routes
List all supported trading pairs. No authentication required. Response:(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.
Each route includes source and destination detail objects:
| Field | Type | Notes |
|---|---|---|
chain | string | Chain identifier |
asset | string | Asset symbol |
contractAddress | string | null | Token contract address (EVM, checksummed), mint address (Solana), or token ID (Spark USDB). null for native assets (BTC, ETH, SOL, etc.). |
decimals | number | Smallest-unit decimals (6 for USDC/USDC.e/USDT/USDB/PathUSD, 8 for BTC/WBTC/cbBTC, 18 for ETH, 9 for SOL) |
chainId | string | null | Chain ID as a string. Numeric for EVM chains (e.g. "8453"), CAIP-2 for Solana ("solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"). null for spark, bitcoin, and lightning. |
GET /v1/orchestration/estimate
Lightweight price preview. This does not create a quote and does not write to the database. Query parameters:| Param | Required | Notes |
|---|---|---|
sourceChain | Yes | One of the supported chains |
sourceAsset | Yes | One of the supported assets |
destinationChain | Yes | One of the supported chains |
destinationAsset | Yes | One of the supported assets |
amount | Yes | Integer string |
appFees | No | JSON-encoded array of {recipient, fee}. Same shape as the /quote body field. |
affiliateId | No | Registered affiliate ID (single). Requires Authorization header. |
affiliateIds | No | Registered affiliate IDs. Accepts either a comma-separated list (a,b,c) for the plain-string form, or a JSON-encoded array ([...]) when you need the {affiliateId, feeBps} override form. Requires Authorization header. |
Authorization header is provided, affiliateId and affiliateIds are resolved against partner-scoped affiliate profiles.
Response:
appFees, affiliateId, or affiliateIds is provided, the response includes additional fields:
feeAssetisUSDCfor most routes,USDBforBTC -> USDB, andBTCfor direct Lightning passthrough routes such aslightning:BTC -> spark:BTCandlightning:BTC -> bitcoin:BTC.totalFeeAmountequalsfeeAmount + appFeeAmount(when present).estimatedOutreflects the final amount after all fees (platform + app) are deducted.- 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). - App fees are not supported when
feeAssetisUSDBorBTC(routes with no stablecoin settlement chain). - 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. Request fields| Field | Type | Required | Notes |
|---|---|---|---|
sourceChain | Chain | Yes | Source chain identifier |
sourceAsset | Asset | Yes | Source asset symbol |
destinationChain | Chain | Yes | Destination chain identifier |
destinationAsset | Asset | Yes | Destination asset symbol |
amount | string | Yes | Integer string in smallest units |
recipientAddress | string | Yes | Address on the destination chain. BOLT11 invoice when destinationChain=lightning. |
amountMode | string | No | "exact_in" (default) or "exact_out". exact_out supported for bitcoin:BTC -> (base|solana):USDC and any source -> lightning:BTC. |
refundAddress | string | Conditional | Required when amountMode=exact_out or destinationChain=lightning. |
refundChain | Chain | No | Refund chain. When provided without refundAddress, the request is rejected. |
slippageBps | number | No | Default 50. |
appFees | AppFee[] | No | Inline fee recipients. Each entry: { recipient: string, fee: number }. Max 16 entries. Mutually exclusive with affiliateId/affiliateIds. |
affiliateId | string | No | Single registered affiliate ID. Requires Authorization. Mutually exclusive with appFees. |
affiliateIds | AffiliateRef[] | No | Multiple affiliate IDs. Each entry is a plain string or { affiliateId: string, feeBps: number }. Max 16 entries. Requires Authorization. Mutually exclusive with appFees. |
bitcoin:BTC -> base|solana: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 forbitcoin:BTC -> (base|solana):USDCand any buy-side source-> lightning:BTC.refundAddressis required whenamountMode=exact_out.- If
Authorizationis included, sendX-Idempotency-Key. appFees,affiliateId, andaffiliateIdsare currently supported only foramountMode=exact_inand whensourceChainordestinationChainisbase|solana.- Fee settlement chain is
sourceChainwhen source isbase|solana, otherwisedestinationChain. 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.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.zeroconfEnabledis only used whensourceChain = bitcoinandamountMode = exact_in.- If omitted, it defaults to
true. - If the deployment does not have ZeroConf configured, the engine falls back to on-chain confirmations.
- If omitted, it defaults to
- 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:USDCwhenever solana or any supported chain (base, ethereum, arbitrum, optimism, polygon, bsc, plasma, tempo, tron, …) is in either side of the route. - Settles on
spark:USDBwhenspark:USDBis in either side and no solana/supported chain is involved. - Pure-BTC routes (e.g.
spark:BTC ↔ bitcoin:BTC) have no stablecoin leg and do not support fee plans. The API returns 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:base|solana: chain address that receives the source assetspark: Spark address that receives BTC or USDBbitcoin: Bitcoin L1 addresslightning: BOLT11 invoice to pay
totalFeeAmountequalsfeeAmount + appFeeAmount + sweepFeeAmount(when present).sweepFeeAmountis returned on some USDC-source routes when a sweep fee is configured, and is included intotalFeeAmount.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.zeroconfEnabledis only present forsourceChain = bitcoin.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.priceLockModeandlockedMinAmountOutare present for routes where a Flashnet min-out lock is enforced.
POST /v1/orchestration/submit
Create an order from a quote after you have initiated the source deposit. Request fields| Field | Type | Required | Notes |
|---|---|---|---|
quoteId | string | Yes | Quote ID (q_...) |
txHash | string | Conditional | Required for EVM and Solana sources (base, ethereum, arbitrum, optimism, solana, tron). Format varies by chain (EVM: 0x-prefixed 64-char hex; Solana: base58 signature). |
sourceAddress | string | No | Sender address for base/solana sources. Required when depositing to a shared address. |
sparkTxHash | string | Conditional | Required for sourceChain=spark. UUID, 32-char hex, or 64-char token tx hash. |
sourceSparkAddress | string | No | Sender Spark address. Required when depositing to a shared Spark address. |
bitcoinTxid | string | Conditional | Required for sourceChain=bitcoin. 64-character hex transaction ID. |
bitcoinVout | number | No | Output index. Auto-resolved from transaction outputs when omitted. |
lightningReceiveRequestId | string | No | For sourceChain=lightning. Auto-populated from quote when omitted. |
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:
- Base:
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. Supported destinations include:lightning:BTC -> spark:USDBlightning:BTC -> spark:BTClightning:BTC -> bitcoin:BTC- supported stablecoin and native-asset destinations on other chains
lightning:BTC. The amount field is BTC in sats.
Headers:
| Field | Type | Required | Notes |
|---|---|---|---|
destinationChain | Chain | Yes | Target chain |
destinationAsset | Asset | Yes | Target asset |
recipientAddress | string | Yes | Address on the destination chain |
amount | string | Yes | BTC in sats (integer string) |
amountMode | string | No | "exact_in" (default) or "exact_out". exact_out not supported for -> spark:BTC or -> bitcoin:BTC. |
slippageBps | number | No | Minimum and default 1000 (10%). Values below 1000 are clamped. |
appFees | AppFee[] | No | Inline fee recipients. Not supported on direct BTC passthrough routes. |
affiliateId | string | No | Registered affiliate ID (single). Requires stablecoin settlement path. |
affiliateIds | AffiliateRef[] | No | Registered affiliate IDs (multiple, max 16). Requires stablecoin settlement path. |
amountMode=exact_outis supported for stablecoin and other bridged destinations, but not forlightning:BTC -> spark:BTCorlightning:BTC -> bitcoin:BTC.- 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 (2 minutes from creation). 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.
Headers:
| Param | Required | Notes |
|---|---|---|
quoteId | Yes | Quote id (q_...) |
order object uses the same shape as GET /v1/orchestration/status, including optional swap, priceLock, reprice, 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, the deposit window has closed. Expired quotes that receive a late deposit are repriced at live market rates and still create an order.
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.
| Param | Notes |
|---|---|
id | Order id (ord_...) |
quoteId | Quote id (q_...) |
txHash | Source transaction identifier (see order.sourceTxHash) |
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_approvalrefundingdeliveringcompletedfailedrefunded
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 recordedpriceLock,reprice, andpaymentIntentmetadata for locked/approval-required flowszeroconfOfferwhen 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_feeorrecipient_payoutfeePayouts.entries[*].affiliateIdis present for app-fee entries derived fromaffiliateIdfeePayouts.entries[*].legisfull,instant, orholdbackfor routes that execute in multiple legs
GET /v1/orchestration/history
List your orders filtered byrecipientAddress.
Headers:
| Param | Required | Notes |
|---|---|---|
address | Yes | Recipient address (Spark address, Bitcoin address, Lightning invoice, or Base/Solana address depending on the route) |
status | No | Exact match on the order status |
limit | No | Default 50, max 200 |
offset | No | Default 0 |
GET /v1/orchestration/status, including optional swap, priceLock, reprice, paymentIntent, and zeroconfOffer metadata when present.