> ## Documentation Index
> Fetch the complete documentation index at: https://docs.flashnet.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Quotes and Orders

> Create quotes, submit deposits, track order status, and query history using the Orchestra orchestration API endpoints.

<Info>
  For authentication, error codes, and request conventions, see [API Overview](/products/orchestration/api/overview).
</Info>

## GET /v1/orchestration/routes

List all supported trading pairs. No authentication required.

Response:

```json theme={null}
{
  "routes": [
    {
      "sourceChain": "base",
      "sourceAsset": "USDC",
      "destinationChain": "spark",
      "destinationAsset": "BTC",
      "source": {
        "chain": "base",
        "asset": "USDC",
        "contractAddress": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
        "decimals": 6,
        "chainId": "8453"
      },
      "destination": {
        "chain": "spark",
        "asset": "BTC",
        "contractAddress": null,
        "decimals": 8,
        "chainId": null
      }
    },
    {
      "sourceChain": "spark",
      "sourceAsset": "BTC",
      "destinationChain": "base",
      "destinationAsset": "USDC",
      "source": {
        "chain": "spark",
        "asset": "BTC",
        "contractAddress": null,
        "decimals": 8,
        "chainId": null
      },
      "destination": {
        "chain": "base",
        "asset": "USDC",
        "contractAddress": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
        "decimals": 6,
        "chainId": "8453"
      }
    }
  ]
}
```

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.

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. With `amountMode=exact_out`, this is the destination amount. Stablecoin exact-out amounts must be whole-cent values.                                                                                             |
| `amountMode`       | No       | `"exact_in"` (default) or `"exact_out"`                                                                                                                                                                                          |
| `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. |

Authentication is optional. When an `Authorization` header is provided, `affiliateId` and `affiliateIds` are resolved against partner-scoped affiliate profiles.

Response:

```json theme={null}
{
  "estimatedOut": "string",
  "feeAmount": "string",
  "feeBps": 5,
  "totalFeeAmount": "string",
  "roundingFeeAmount": "string",
  "feeAsset": "USDC",
  "route": ["USDC", "USDB", "BTC"]
}
```

When `appFees`, `affiliateId`, or `affiliateIds` is provided, the response includes additional fields:

```json theme={null}
{
  "estimatedOut": "string",
  "feeAmount": "string",
  "feeBps": 5,
  "totalFeeAmount": "string",
  "appFeeAmount": "string",
  "appFeePlatformCutAmount": "string",
  "appFees": [
    {
      "recipient": "So1AffiliateOne...",
      "feeBps": 100,
      "amount": "string",
      "platformCutAmount": "string",
      "recipientAmount": "string"
    }
  ],
  "feeAsset": "USDC",
  "route": ["USDC", "USDB", "BTC"]
}
```

* `feeAsset` is `USDC` for most routes, `USDB` for `BTC -> USDB`, and `BTC` for direct Lightning passthrough routes such as `lightning:BTC -> spark:BTC` and `lightning:BTC -> bitcoin:BTC`.
* `totalFeeAmount` equals `feeAmount + appFeeAmount` (when present).
* `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 is `"0"` when no surplus is retained.
* 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).
* App fees are not supported when `feeAsset` is `USDB` or `BTC` (routes with no stablecoin settlement chain).
* 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.

**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. With `amountMode=exact_out`, this is the destination amount. Stablecoin exact-out amounts must be whole-cent values, for example multiples of `10000` for 6-decimal USDC/USDB. |
| `recipientAddress` | `string`         | Yes         | Address on the destination chain. BOLT11 invoice when `destinationChain=lightning`.                                                                                                                              |
| `amountMode`       | `string`         | No          | `"exact_in"` (default) or `"exact_out"`. `exact_out` is supported for stablecoin `lightning:BTC` sell routes, `bitcoin:BTC -> (base\|solana):USDC`, and supported source routes to `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`.                                  |

Exact-in example (default mode):

```json theme={null}
{
  "sourceChain": "base",
  "sourceAsset": "USDC",
  "destinationChain": "spark",
  "destinationAsset": "BTC",
  "amount": "100000000",
  "recipientAddress": "spark1...",
  "slippageBps": 50,
  "zeroconfEnabled": true
}
```

Exact-out payment-intent example (`bitcoin:BTC -> base|solana:USDC`):

```json theme={null}
{
  "sourceChain": "bitcoin",
  "sourceAsset": "BTC",
  "destinationChain": "base",
  "destinationAsset": "USDC",
  "amount": "100000000",
  "amountMode": "exact_out",
  "recipientAddress": "0xYourBaseUsdcAddress",
  "refundAddress": "bc1qyourrefundaddress...",
  "slippageBps": 0
}
```

Exact-out Lightning example (any buy-side source `-> lightning:BTC`):

```json theme={null}
{
  "sourceChain": "base",
  "sourceAsset": "USDC",
  "destinationChain": "lightning",
  "destinationAsset": "BTC",
  "amount": "100000",
  "amountMode": "exact_out",
  "recipientAddress": "lnbc1u1...",
  "refundAddress": "0xYourBaseUsdcRefundAddress",
  "slippageBps": 0
}
```

Exact-in affiliate-fee example (`spark:BTC -> solana:USDC`):

```json theme={null}
{
  "sourceChain": "spark",
  "sourceAsset": "BTC",
  "destinationChain": "solana",
  "destinationAsset": "USDC",
  "amount": "100000",
  "recipientAddress": "So1RecipientAddress...",
  "appFees": [
    {
      "recipient": "So1AffiliateOne...",
      "fee": 100
    },
    {
      "recipient": "So1AffiliateTwo...",
      "fee": 50
    }
  ]
}
```

Exact-in affiliate-registry example (`spark:BTC -> solana:USDC`):

```json theme={null}
{
  "sourceChain": "spark",
  "sourceAsset": "BTC",
  "destinationChain": "solana",
  "destinationAsset": "USDC",
  "amount": "100000",
  "recipientAddress": "So1RecipientAddress...",
  "affiliateId": "flashpartner"
}
```

Exact-in with multiple affiliates (`spark:BTC -> solana:USDC`):

```json theme={null}
{
  "sourceChain": "spark",
  "sourceAsset": "BTC",
  "destinationChain": "solana",
  "destinationAsset": "USDC",
  "amount": "100000",
  "recipientAddress": "So1RecipientAddress...",
  "affiliateIds": ["referrer-alice", "platform-fee"]
}
```

Exact-in with per-quote feeBps override (`spark:BTC -> solana:USDC`):

```json theme={null}
{
  "sourceChain": "spark",
  "sourceAsset": "BTC",
  "destinationChain": "solana",
  "destinationAsset": "USDC",
  "amount": "100000",
  "recipientAddress": "So1RecipientAddress...",
  "affiliateIds": [
    "referrer-alice",
    { "affiliateId": "platform-fee", "feeBps": 25 }
  ]
}
```

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`):

```json theme={null}
{
  "sourceChain": "solana",
  "sourceAsset": "SOL",
  "destinationChain": "spark",
  "destinationAsset": "BTC",
  "amount": "100000000",
  "recipientAddress": "spark1...",
  "appFees": [
    {
      "recipient": "Dtkxt55zEUDj6NTXGRtH8uQsACsTjoSVkXfYBEF8xkkT",
      "fee": 100
    }
  ]
}
```

Notes:

* `amountMode` defaults to `exact_in`.
* `amountMode=exact_out` is supported for stablecoin `lightning:BTC` sell routes, `bitcoin:BTC -> (base|solana):USDC`, and supported source routes to `lightning:BTC`.
* 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 currently supported only for `amountMode=exact_in` and when `sourceChain` or `destinationChain` is `base|solana`.
* Fee settlement chain is `sourceChain` when source is `base|solana`, otherwise `destinationChain`.
* `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. `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.
* `zeroconfEnabled` is only used when `sourceChain = bitcoin` and `amountMode = exact_in`.
  * If omitted, it defaults to `true`.
  * If the deployment does not have ZeroConf configured, the engine falls back to on-chain confirmations.
* 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` whenever solana or any supported chain (base, ethereum, arbitrum, optimism, polygon, bsc, plasma, tempo, tron, monad, …) is in either side of the route.
  * Settles on `spark:USDB` when `spark:USDB` is 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 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):

```json theme={null}
{
  "quoteId": "q_...",
  "depositAddress": "bc1q...",
  "amountIn": "250000",
  "estimatedOut": "100000000",
  "feeAmount": "100000",
  "totalFeeAmount": "100000",
  "feeAsset": "USDC",
  "feeBps": 5,
  "route": ["BTC", "USDB", "USDC"],
  "expiresAt": "2026-02-04T02:00:00.000Z",
  "zeroconfEnabled": false,
  "amountMode": "exact_out",
  "targetAmountOut": "100000000",
  "requiredAmountIn": "250000",
  "maxAcceptedAmountIn": "250050",
  "inputBufferBps": 2
}
```

Response (exact-in with appFees sample):

```json theme={null}
{
  "quoteId": "q_...",
  "depositAddress": "spark1...",
  "amountIn": "100000",
  "estimatedOut": "24825000",
  "feeAmount": "25000",
  "totalFeeAmount": "62125",
  "appFeeAmount": "37125",
  "appFeePlatformCutAmount": "7425",
  "appFees": [
    {
      "affiliateId": "flashpartner",
      "recipient": "So1AffiliateOne...",
      "feeBps": 50,
      "amount": "24750",
      "platformCutAmount": "4950",
      "recipientAmount": "19800"
    },
    {
      "recipient": "So1AffiliateTwo...",
      "feeBps": 50,
      "amount": "12375",
      "platformCutAmount": "2475",
      "recipientAmount": "9900"
    }
  ],
  "feeAsset": "USDC",
  "feeBps": 5,
  "route": ["BTC", "USDB", "USDC"],
  "expiresAt": "2026-02-04T02:00:00.000Z"
}
```

Response (exact-in source-side appFees sample):

```json theme={null}
{
  "quoteId": "q_...",
  "depositAddress": "So1DepositAddress...",
  "amountIn": "100000000",
  "estimatedOut": "11643",
  "feeAmount": "7893",
  "totalFeeAmount": "86749",
  "appFeeAmount": "78856",
  "appFeePlatformCutAmount": "15771",
  "appFees": [
    {
      "recipient": "Dtkxt55zEUDj6NTXGRtH8uQsACsTjoSVkXfYBEF8xkkT",
      "feeBps": 50,
      "amount": "78856",
      "platformCutAmount": "15771",
      "recipientAmount": "63085"
    }
  ],
  "feeAsset": "USDC",
  "feeBps": 5,
  "route": ["SOL", "USDC", "USDB", "BTC"],
  "expiresAt": "2026-02-11T23:55:36.296Z"
}
```

Field notes:

* `depositAddress` depends on `sourceChain`:
  * `base|solana`: 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 + appFeeAmount + sweepFeeAmount` (when present).
* `sweepFeeAmount` is returned on some USDC-source routes when a sweep fee is configured, and is included in `totalFeeAmount`.
* `roundingFeeAmount` is returned when stablecoin surplus is retained instead of delivered. It is included in `totalFeeAmount` when present.
* `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`.
* `zeroconfEnabled` is only present for `sourceChain = bitcoin`.
* `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**

| 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`, `monad`). 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.                                                                                                                            |

The request body shape depends on `sourceChain`. Each source chain uses a different subset of these fields. See the examples below.

Headers:

```bash theme={null}
Authorization: Bearer fn_...
X-Idempotency-Key: <unique key>
```

Request body shape depends on the quote `sourceChain`.

Base/Solana sources (`sourceChain = base|solana`):

```json theme={null}
{
  "quoteId": "q_...",
  "txHash": "0x...",
  "sourceAddress": "0x..."
}
```

`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`):

```json theme={null}
{
  "quoteId": "q_...",
  "sparkTxHash": "spark_transfer_id_or_token_tx_hash",
  "sourceSparkAddress": "spark1..."
}
```

`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`):

```json theme={null}
{
  "quoteId": "q_...",
  "bitcoinTxid": "txid"
}
```

`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`):

```json theme={null}
{
  "quoteId": "q_...",
  "lightningReceiveRequestId": "string"
}
```

`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

Response:

```json theme={null}
{
  "orderId": "ord_...",
  "status": "processing"
}
```

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.

Supported destinations include:

* `lightning:BTC -> spark:USDB`
* `lightning:BTC -> spark:BTC`
* `lightning:BTC -> bitcoin:BTC`
* supported stablecoin and native-asset destinations on other chains

The source is always `lightning:BTC`. The `amount` field is BTC in sats.

Headers:

```bash theme={null}
Authorization: Bearer fn_...
X-Idempotency-Key: <unique key>
```

**Request fields**

| 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      | Integer string. With `exact_in`, BTC in sats. With `exact_out`, the destination amount in smallest units. Stablecoin exact-out amounts must be whole-cent values. |
| `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.                                                                                 |

Request body:

```json theme={null}
{
  "destinationChain": "solana",
  "destinationAsset": "USDC",
  "recipientAddress": "So1...",
  "amount": "100000",
  "slippageBps": 50
}
```

Notes:

* `amountMode=exact_out` is supported for stablecoin and other bridged destinations, but not for `lightning:BTC -> spark:BTC` or `lightning:BTC -> bitcoin:BTC`.
* 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:

```json theme={null}
{
  "orderId": "ord_...",
  "quoteId": "q_...",
  "depositAddress": "lnbc1000n1pj...",
  "paymentLinks": {
    "cashApp": "https://cash.app/launch/lightning/lnbc1000n1pj...",
    "shortUrl": "https://orchestration.flashnet.xyz/pay/a3xKm2Rq"
  },
  "amountIn": "100000",
  "estimatedOut": "96543210",
  "feeAmount": "38536",
  "feeBps": 40,
  "totalFeeAmount": "38536",
  "feeAsset": "USDC",
  "route": ["BTC", "USDB", "USDC"],
  "expiresAt": "2026-01-15T12:04:00.000Z"
}
```

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` (2 minutes from creation). 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](/products/orchestration/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:

```bash theme={null}
Authorization: Bearer fn_...
```

Query parameters:

| Param     | Required | Notes              |
| --------- | -------- | ------------------ |
| `quoteId` | Yes      | Quote id (`q_...`) |

Response when no order exists yet:

```json theme={null}
{
  "quote": {
    "id": "q_...",
    "kind": "sell",
    "sourceChain": "spark",
    "sourceAsset": "BTC",
    "destinationChain": "solana",
    "destinationAsset": "USDC",
    "amountIn": "100000",
    "estimatedOut": "96500000",
    "feeBps": 5,
    "feeAmount": "4830",
    "depositAddress": "spark1...",
    "recipientAddress": "So1...",
    "slippageBps": 50,
    "expiresAt": "2026-02-04T02:00:00.000Z",
    "expired": false,
    "createdAt": "2026-02-04T01:58:00.000Z"
  },
  "order": null,
  "stages": []
}
```

Response when an order has been created:

```json theme={null}
{
  "quote": {
    "id": "q_...",
    "kind": "sell",
    "sourceChain": "spark",
    "sourceAsset": "BTC",
    "destinationChain": "solana",
    "destinationAsset": "USDC",
    "amountIn": "100000",
    "estimatedOut": "96500000",
    "feeBps": 5,
    "feeAmount": "4830",
    "depositAddress": "spark1...",
    "recipientAddress": "So1...",
    "slippageBps": 50,
    "expiresAt": "2026-02-04T02:00:00.000Z",
    "expired": true,
    "createdAt": "2026-02-04T01:58:00.000Z"
  },
  "order": {
    "id": "ord_...",
    "type": "order",
    "status": "swapping",
    "quoteId": "q_...",
    "sourceChain": "spark",
    "sourceAsset": "BTC",
    "destinationChain": "solana",
    "destinationAsset": "USDC",
    "recipientAddress": "So1...",
    "amountIn": "100000",
    "amountOut": null,
    "feeBps": 5,
    "feeAmount": "4830",
    "createdAt": "2026-02-04T02:01:00.000Z"
  },
  "stages": [
    {
      "name": "deposit_confirmed",
      "status": "completed",
      "completedAt": "2026-02-04T02:01:05.000Z"
    }
  ]
}
```

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:

| 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:

* `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):

```json theme={null}
{
  "order": {
    "id": "ord_...",
    "type": "order",
    "status": "refunding",
    "quoteId": "q_...",
    "sourceChain": "bitcoin",
    "sourceAsset": "BTC",
    "sourceAddress": null,
    "sourceTxHash": "<txid>",
    "sourceTxVout": 0,
    "depositAddress": "bc1q...",
    "destinationChain": "base",
    "destinationAsset": "USDC",
    "recipientAddress": "0x...",
    "amountIn": "250000",
    "amountOut": null,
    "feeBps": 5,
    "feeAmount": "100000",
    "slippageBps": 50,
    "errorCode": "slippage_exceeded",
    "errorMessage": "Pool moved past slippage tolerance between deposit and execution",
    "createdAt": "2026-02-04T01:30:00.000Z",
    "updatedAt": "2026-02-04T01:30:10.000Z",
    "completedAt": null,
    "paymentIntent": {
      "version": 1,
      "amountMode": "exact_out",
      "targetAmountOut": "100000000",
      "requiredAmountIn": "250000",
      "maxAcceptedAmountIn": "250050",
      "inputBufferBps": 2,
      "actualAmountIn": "249900",
      "refundAddress": "bc1q...",
      "exactOutExecution": "strict"
    },
    "feePlan": {
      "version": 1,
      "settlementChain": "solana",
      "settlementAsset": "USDC",
      "appFees": [
        {
          "affiliateId": "flashpartner",
          "recipient": "So1AffiliateOne...",
          "feeBps": 50
        },
        {
          "recipient": "So1AffiliateTwo...",
          "feeBps": 50
        }
      ]
    },
    "feePayouts": {
      "version": 1,
      "entries": [
        {
          "idempotencyKey": "order:ord_...:full:appfee:0",
          "leg": "full",
          "chain": "solana",
          "role": "app_fee",
          "affiliateId": "flashpartner",
          "recipient": "So1AffiliateOne...",
          "feeBps": 50,
          "amount": "24750",
          "platformCutAmount": "4950",
          "recipientAmount": "19800",
          "txHash": "5kW...",
          "recordedAt": "2026-02-04T01:35:00.000Z"
        },
        {
          "idempotencyKey": "order:ord_...:full:payout",
          "leg": "full",
          "chain": "solana",
          "role": "recipient_payout",
          "recipient": "So1RecipientAddress...",
          "feeBps": null,
          "amount": "2475000",
          "platformCutAmount": null,
          "recipientAmount": null,
          "txHash": "3hN...",
          "recordedAt": "2026-02-04T01:35:02.000Z"
        }
      ]
    }
  },
  "stages": [
    {
      "name": "deposit_confirmed",
      "status": "completed",
      "completedAt": "2026-02-04T01:30:05.000Z"
    },
    {
      "name": "refund_requested",
      "status": "completed",
      "completedAt": "2026-02-04T01:30:10.000Z"
    }
  ]
}
```

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](/products/orchestration/api/approval-flows#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` or `recipient_payout`
* `feePayouts.entries[*].affiliateId` is present for app-fee entries derived from `affiliateId`
* `feePayouts.entries[*].leg` is `full`, `instant`, or `holdback` for routes that execute in multiple legs

## GET /v1/orchestration/history

List your orders filtered by `recipientAddress`.

Headers:

```bash theme={null}
Authorization: Bearer fn_...
```

Query parameters:

| 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`                                                                                                          |

Response:

```json theme={null}
{
  "orders": [{ "id": "ord_...", "status": "completed" }]
}
```

History entries use the same order shape as `GET /v1/orchestration/status`, including optional `swap`, `paymentIntent`, and `zeroconfOffer` metadata when present.
