POST /v1/orchestration/onramp returns the order, invoice, fees, and expiry. Pay the BOLT11 invoice in depositAddress with Cash App or Strike. paymentLinks.cashApp opens Cash App with the invoice; the payer app controls its USD display.
Prerequisites
- An Orchestra account. Create one in the dashboard. Flashnet reviews new accounts before enabling API access.
- A server key (
fn_...) from API keys in the dashboard. Keep it on your backend. For browsers and apps, use a scoped client key (fnp_...); see Authentication.
Flow
1
Preview the price (optional)
GET /v1/orchestration/estimate with sourceChain=lightning&sourceAsset=BTC returns an indicative estimatedOut without creating anything.2
Create the onramp order
Request $50.00 over Lightning into USDB on Spark:Example response for exact-in pricing (values vary by quote):Optional
Replace
SERVER_KEY with your fn_... key. Use a new X-Idempotency-Key for each operation and reuse it when retrying that same request. Amounts are integer strings in the asset’s smallest unit: "100000" is 0.001 BTC; "50000000" is 50 USDC on Base. Read each asset’s decimals from /routes.shortUrl serves a mobile handoff page or desktop QR page for this order. Use pay links for repeat checkout.Optional tag is your own reference for the order. It returns on every order.* webhook as data.tag. See Tags.3
Hand off to the user's wallet
For Cash App, navigate to
paymentLinks.cashApp on mobile or encode that URL as a desktop QR code. Never fetch() it. Use the invoice for a compatible wallet’s Lightning payment flow.4
Track the order
Subscribe to SSE or register a webhook; see Status and Frontend rules below.The order emits a webhook when it is created, usually
order.processing. If the invoice times out unpaid, no further webhook follows. A payment sent before expiry can still settle up to six hours after the timeout and then emits order.completed, so a webhook-only integration should not treat expiresAt as final.Amount modes
Send exactly one ofamount or amountFiatUsd.
amount: integer string in sats foramountMode: "exact_in"(default), or destination smallest units for"exact_out".amountFiatUsd: USD string from"1.00"to"50000.00", converted to sats at spot. The order and webhooks recordspotUsdPerBtc.
amountMode: "exact_in" to require that mode. Read the returned amountMode, amounts, and fees; partner-invoiced platform fees are billed separately.
exact_outis not supported tospark:BTCorbitcoin:BTC.slippageBpsis pinned to 1000. Lower values are clamped up;effectiveSlippageBpsreports what was applied.- Use returned
expiresAt. Exact-in normally lasts 24 hours; exact-out and fixed-delivery requests use 5 minutes. Fixed delivery can fall back when unavailable. Reopening does not extend expiry. refundAddressis a Lightning address (user@domain) or an amountless BOLT11 invoice, used if the order fails before the swap. Other values are dropped and named inignoredFields.
Destinations
Destinations are thelightning:BTC entry’s route.to set on GET /v2/orchestration/routes. Common targets:
- USDB on Spark: swap into USDB; fees in USDB.
- BTC on Spark or Bitcoin L1: settle the fee, then deliver BTC; fees in sats.
- USDC on Solana or Base: swap, bridge, and deliver; fees in USDC.
Restrictions
Not available to residents of New York City. Lightning payer apps impose their own per-payment limits; validate client-side against thelimits.fiatUsd band from GET /v1/orchestration/limits. See Routes and limits.
Frontend rules
- Keep the API key on your backend. Proxy
/v1/sse/paths through your server withContent-Type: text/event-stream. - Separate invoice UI expiry from order tracking. Close SSE on
completed,failed, orrefunded; continue trackingunfulfilledfor late settlement during the six-hour recovery window from timeout. If SSE fails, pollGET /v1/orchestration/status?id=ORDER_IDevery 3 seconds.