> ## 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.

# Stablecoin to BTC

This flow starts with a funded source asset on any supported chain and ends with BTC delivered to Spark, Bitcoin L1, or Lightning, or USDB delivered to Spark.

If you want a reusable deposit address that runs this flow automatically on each deposit, use [reusable addresses](/products/orchestration/reusable-addresses#what-are-accumulation-addresses).

Common uses:

* Wallet buy flow: users pay USDC and receive BTC to a Spark address, Bitcoin address, or Lightning invoice.
* Payout rails: convert USDC into BTC without running Bitcoin infrastructure.

Live pairs, per-asset contract addresses, decimals, and chain ids come from `GET /v1/orchestration/routes`. Per-route amount bounds come from `GET /v1/orchestration/limits`. Never hardcode contract addresses; read them from the route entry's source and destination detail objects.

## Flow

1. Create a quote: `POST /v1/orchestration/quote`.
2. Send the source asset to `depositAddress` for `amountIn`.
3. Submit the deposit transaction: `POST /v1/orchestration/submit`.
4. Track status via webhooks or `GET /v1/orchestration/status?id=...`.

Quotes expire 2 minutes after creation. Late deposits are always repriced at live market rates at detection time and execute against the quote's `slippageBps`.

## Affiliate fees

App fees are supported on these routes when `amountMode=exact_in`. Fees are computed in USDC and settled on Solana. Flashnet retains a 20% platform cut of all app fees; the remaining 80% goes to the fee recipient. Affiliate fees use a holdback model where the recipient's 80% share accumulates and is claimed by the affiliate. For `SOL`/`ETH` routes, the engine converts to USDC first, then applies fees. See [Quotes and Orders](/products/orchestration/api/quotes-and-orders#post-v1orchestrationquote) for the full affiliate fee model.

## Example: USDC (Base) to BTC (Spark)

```ts theme={null}
const BASE_URL = 'https://orchestration.flashnet.xyz';

const quote = await fetch(`${BASE_URL}/v1/orchestration/quote`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Authorization: `Bearer ${process.env.FLASHNET_API_KEY}`,
    // Required for authenticated quotes.
    'X-Idempotency-Key': `quote:${Date.now()}`,
  },
  body: JSON.stringify({
    sourceChain: 'base',
    sourceAsset: 'USDC',
    destinationChain: 'spark',
    destinationAsset: 'BTC',
    amount: '100000000',
    recipientAddress: 'spark1...',
    slippageBps: 50,
  }),
}).then((r) => r.json());

// Send USDC to quote.depositAddress for quote.amountIn.
// Capture the deposit transaction hash.
const txHash = await sendUsdcOnBase({
  to: quote.depositAddress,
  amountUsdcSmallest: quote.amountIn,
});

const submit = await fetch(`${BASE_URL}/v1/orchestration/submit`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Authorization: `Bearer ${process.env.FLASHNET_API_KEY}`,
    'X-Idempotency-Key': `submit:${quote.quoteId}:${txHash}`,
  },
  body: JSON.stringify({
    quoteId: quote.quoteId,
    txHash,
    // Optional but recommended. When present, the deposit verifier checks the sender address.
    sourceAddress: '0xYourSenderAddress',
  }),
}).then((r) => r.json());

const status = await fetch(
  `${BASE_URL}/v1/orchestration/status?id=${encodeURIComponent(submit.orderId)}`,
).then((r) => r.json());

console.log(status.order.status);
```

## Example: SOL (Solana) to BTC (Spark)

```json theme={null}
{
  "sourceChain": "solana",
  "sourceAsset": "SOL",
  "destinationChain": "spark",
  "destinationAsset": "BTC",
  "amount": "25000000",
  "recipientAddress": "spark1...",
  "slippageBps": 50
}
```

`amount` is lamports (`1 SOL = 1_000_000_000 lamports`).

## Example: SOL (Solana) to BTC (Spark) with affiliate fee

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

## Example: SOL (Solana) to BTC (Spark) with affiliate registry

```json theme={null}
{
  "sourceChain": "solana",
  "sourceAsset": "SOL",
  "destinationChain": "spark",
  "destinationAsset": "BTC",
  "amount": "100000000",
  "recipientAddress": "spark1...",
  "affiliateId": "flashpartner",
  "slippageBps": 50
}
```

## Example: USDC to BTC (Bitcoin L1)

Set `destinationChain = bitcoin` and provide a Bitcoin address in `recipientAddress`.

```json theme={null}
{
  "sourceChain": "base",
  "sourceAsset": "USDC",
  "destinationChain": "bitcoin",
  "destinationAsset": "BTC",
  "amount": "100000000",
  "recipientAddress": "bc1...",
  "slippageBps": 50
}
```

The submit step is the same as any USDC source quote.

## Example: USDC to BTC (Lightning)

Lightning-destination routes use custom pricing. USDB routes get the lowest rates.

For Lightning payouts, `recipientAddress` must be a BOLT11 invoice. Use an amountless (0-amount) invoice for exact-in mode, or an invoice with an amount matching the target sats for exact-out mode. Amountless invoices are accepted in both modes.

```json theme={null}
{
  "sourceChain": "solana",
  "sourceAsset": "USDC",
  "destinationChain": "lightning",
  "destinationAsset": "BTC",
  "amount": "25000000",
  "recipientAddress": "lnbc1...",
  "slippageBps": 50
}
```

The submit step is the same as any USDC source quote.

## Example: USDC to BTC (Lightning, exact out)

Use exact-out when the recipient must receive a precise number of sats on Lightning. The system determines the required USDC input and includes a routing fee buffer.

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

`amount` is the target BTC delivery in sats. The `recipientAddress` can be an amountless invoice or an invoice encoding the same amount (100,000 sats in this case).

The quote response includes the same exact-out fields as BTC-to-USDC exact-out:

* `targetAmountOut`: the requested sats (matches `amount`)
* `requiredAmountIn`: USDC to deposit
* `maxAcceptedAmountIn`: upper bound on accepted deposit
* `inputBufferBps`: buffer applied to the required input

Affiliate fees (`appFees` / `affiliateId` / `affiliateIds`) are not supported with `amountMode=exact_out`.

## Example: USDT (Ethereum) to BTC (Spark)

For chain sources other than Solana, the quote returns a deposit address on the source chain. The deposit is detected automatically.

```json theme={null}
{
  "sourceChain": "ethereum",
  "sourceAsset": "USDT",
  "destinationChain": "spark",
  "destinationAsset": "BTC",
  "amount": "10000000",
  "recipientAddress": "spark1...",
  "slippageBps": 50
}
```

`amount` is in USDT smallest units (6 decimals). The `depositAddress` in the response is an Ethereum address. Send USDT there and the order is created automatically.

## Deposit verification

The engine verifies that the deposit transaction sent the correct asset to the quoted `depositAddress`. When `sourceAddress` is provided on submit, the verifier also confirms the sender matches.

Deposits do not need to match the quoted `amountIn` exactly. See [Deposit Amount Flexibility](/products/orchestration/order-lifecycle#what-happens-if-the-deposit-amount-differs-from-the-quote) for details on how over/underpayments are handled.

## Next steps

* [API Reference](/products/orchestration/api/overview)
* [BTC to Stablecoin](/products/orchestration/btc-to-stablecoin)
* [Webhooks](/products/orchestration/webhooks)
