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

# Reusable addresses

> Create persistent accumulation and liquidation deposit addresses in Orchestra with frozen fee plans and automatic order creation.

Accumulation and liquidation addresses are the same primitive with the input asset swapped. Both are persistent deposit addresses. Both run every inbound deposit through a fee plan that is resolved and frozen at creation time. The two address types differ only in direction. Accumulation takes inbound stablecoin, ETH, SOL, BNB, or other supported assets and delivers BTC or USDB on Spark. Liquidation takes inbound BTC on Bitcoin L1 and delivers the output on any supported destination chain.

## What are accumulation addresses?

An accumulation address is a persistent deposit address on Solana or any supported EVM chain (base, ethereum, arbitrum, optimism, polygon, bsc, tempo, tron, plasma, monad). Each inbound deposit automatically creates an order that converts to USDC if needed, bridges to Spark, and then either delivers `USDB` to a fixed Spark address or swaps into `BTC` and delivers the BTC to a fixed Spark address.

Hand out one address per user and skip calling `/quote` and `/submit` per deposit.

<Accordion title="Supported routes">
  * `USDC (solana|base|ethereum|arbitrum|optimism|polygon|tempo|monad) -> USDB (spark)`
  * `USDC (solana|base|ethereum|arbitrum|optimism|polygon|tempo|monad) -> BTC (spark)`
  * `USDC.e (polygon) -> USDB (spark)`
  * `USDC.e (polygon) -> BTC (spark)`
  * `USDT (ethereum|arbitrum|optimism|tron|plasma|bsc) -> USDB (spark)`
  * `USDT (ethereum|arbitrum|optimism|tron|plasma|bsc) -> BTC (spark)`
  * `ETH (ethereum|base|arbitrum|optimism) -> USDB (spark)`
  * `ETH (ethereum|base|arbitrum|optimism) -> BTC (spark)`
  * `SOL (solana) -> USDB (spark)`
  * `SOL (solana) -> BTC (spark)`
  * `BNB (bsc) -> USDB (spark)`
  * `BNB (bsc) -> BTC (spark)`
  * `DAI (ethereum) -> USDB (spark)`
  * `DAI (ethereum) -> BTC (spark)`
  * `WBTC (ethereum) -> USDB (spark)`
  * `WBTC (ethereum) -> BTC (spark)`
  * `cbBTC (base|solana|monad) -> USDB (spark)`
  * `cbBTC (base|solana|monad) -> BTC (spark)`

  Tempo `PathUSD` is not supported as an accumulation source asset.

  Deposits on chains other than Solana are detected automatically. Solana-sourced addresses use direct webhook detection.
</Accordion>

### Create an accumulation address

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

const res = await fetch(`${BASE_URL}/v1/accumulation-addresses`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Authorization: `Bearer ${process.env.FLASHNET_API_KEY}`,
    'X-Idempotency-Key': `acu:create:${Date.now()}`,
  },
  body: JSON.stringify({
    label: 'User 123',
    sourceChain: 'solana',
    sourceAsset: 'USDC',
    destinationAsset: 'BTC',
    recipientSparkAddress: 'spark1UserRecipient...',
    feeBps: 5,
    slippageBps: 50,
    appFees: [
      { recipient: 'So1FeeRecipient...', fee: 50 },
    ],
  }),
}).then((r) => r.json());

console.log(res.depositAddress);
```

Response fields:

* `depositAddress`: the address to receive deposits (a Solana address for Solana sources, an on-chain deposit address for other chain sources).
* `appFees`: array of configured fee recipients, present when a fee plan was configured at creation.
* `subscriptions`: status of server-side deposit detection subscriptions (Solana-sourced only).

Response example:

```json theme={null}
{
  "accumulationAddressId": "acu_...",
  "sourceChain": "solana",
  "sourceAsset": "USDC",
  "destinationAsset": "BTC",
  "recipientSparkAddress": "spark1...",
  "feeBps": 5,
  "slippageBps": 50,
  "enabled": true,
  "depositAddress": "So1...",
  "createdAt": "2026-02-04T01:00:00.000Z",
  "appFees": [
    { "recipient": "So1FeeRecipient...", "feeBps": 50 }
  ],
  "subscriptions": []
}
```

### What are the deposit requirements?

On non-Solana chains, deposits must be plain token transfers to the deposit address. The deposit transaction should contain no calldata beyond a standard ERC-20 `transfer()`.

Deposits sent through smart-contract interactions (multisig executions, payment routers, other contract-mediated transfers) are not detected automatically. The funds arrive on-chain, but order creation does not trigger.

<Warning>
  If a contract-mediated deposit lands by mistake, call the reindex endpoint for that accumulation address. The endpoint asks Relay to rescan the stored deposit address and configured token. If Relay finds a balance, it queues the sweep and the normal fill-detection path creates the order.
</Warning>

```bash theme={null}
curl --request POST "$BASE_URL/v1/accumulation-addresses/<DEPOSIT_ADDRESS_OR_ACU_ID>/reindex" \
  --header "Authorization: Bearer $FLASHNET_API_KEY" \
  --header "X-Idempotency-Key: acu:reindex:<unique-key>"
```

Use the reusable `depositAddress` from the create response when you have it. The `acu_...` id works too. This endpoint is only for Relay-backed accumulation addresses, not Bitcoin liquidation addresses.

Solana-sourced deposits do not have this limitation.

### How does a deposit move through the system?

1. Your user sends a supported deposit asset to the returned deposit address.
2. Flashnet detects the deposit and creates an order.
3. The engine processes the order asynchronously.
4. You observe progress via partner webhooks.

### Manage accumulation addresses

* `GET /v1/accumulation-addresses` lists accumulation addresses.
* `GET /v1/accumulation-addresses/:id` fetches a single address.
* `DELETE /v1/accumulation-addresses/:id` disables an address (requires `X-Idempotency-Key`).
* `POST /v1/accumulation-addresses/:idOrAddress/reindex` asks Relay to rescan one Relay-backed deposit address. `:idOrAddress` can be the reusable deposit address or the `acu_...` id. Requires `X-Idempotency-Key`.
* `POST /v1/accumulation-addresses/sync` re-registers all enabled Solana-sourced addresses with the configured deposit detection webhooks. Chain-sourced addresses do not use webhook subscriptions. Intended for operational recovery and self-hosted deployments.

## What are liquidation addresses?

A liquidation address is a persistent Bitcoin L1 deposit address. Each inbound BTC deposit automatically creates an order that swaps BTC and delivers the output asset to a fixed destination on any supported chain, including BSC (`USDT`, `BNB`), Tempo (`USDC`, `PathUSD`), and all other supported chain/asset pairs.

Hand out a static `bc1...` address and skip calling `/quote` and `/submit` per deposit.

Orders created from liquidation deposits have:

* `sourceChain = bitcoin`
* `sourceAsset = BTC`
* `destinationChain` and `destinationAsset` taken from the liquidation address configuration
* `quoteId = null`

### Create a liquidation address

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

const res = await fetch(`${BASE_URL}/v1/liquidation-addresses`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Authorization: `Bearer ${process.env.FLASHNET_API_KEY}`,
    'X-Idempotency-Key': `liq:create:${Date.now()}`,
  },
  body: JSON.stringify({
    label: 'Merchant settlement',
    destinationChain: 'ethereum',
    destinationAsset: 'USDC',
    destinationAddress: '0xYourEthereumAddress',
    feeBps: 5,
    slippageBps: 50,
    appFees: [
      // Inline appFees recipients must live on the fee settlement chain,
      // not the destination chain. For bitcoin:BTC -> ethereum:USDC,
      // settlement is Solana USDC, so this must be a Solana address.
      { recipient: 'So1FeeRecipient...', fee: 50 },
    ],
  }),
}).then((r) => r.json());

// res.l1DepositAddress is the reusable Bitcoin address.
console.log(res.l1DepositAddress);
```

Response fields:

* `liquidationAddressId`: stable id.
* `l1DepositAddress`: Bitcoin deposit address (`bc1...`).
* `sparkAddress`: Spark address used internally for deposit claiming and sweeps.
* `destination.chain`, `destination.asset`, `destination.address`: fixed payout destination.
* `appFees`: array of configured fee recipients, present when a fee plan was configured at creation.

Response example:

```json theme={null}
{
  "liquidationAddressId": "liq_...",
  "sparkAddress": "spark1...",
  "l1DepositAddress": "bc1...",
  "destination": { "chain": "ethereum", "asset": "USDC", "address": "0x..." },
  "feeBps": 5,
  "slippageBps": 50,
  "enabled": true,
  "createdAt": "2026-02-04T01:00:00.000Z",
  "appFees": [
    { "recipient": "So1FeeRecipient...", "feeBps": 50 }
  ]
}
```

### How are deposits attributed?

Each Bitcoin deposit is identified by `(txid, vout)`, where `vout` is the output index that paid the liquidation address. A single Bitcoin transaction can contain multiple outputs to different liquidation addresses, or multiple outputs to the same address. For reliable attribution, use webhooks and store `order.id` from the payload.

### ZeroConf

All Bitcoin L1 deposits to liquidation addresses are ZeroConf-eligible. See [ZeroConf](/products/orchestration/zeroconf) for the full offer flow, confirmation behavior, and accept or decline endpoints.

### Manage liquidation addresses

* `GET /v1/liquidation-addresses` lists enabled liquidation addresses.
* `GET /v1/liquidation-addresses/:id` fetches a single address, enabled or disabled.
* `DELETE /v1/liquidation-addresses/:id` disables an address (requires `X-Idempotency-Key`).

## How do app fees and affiliates work?

Both primitives accept `appFees` or `affiliateIds` at creation. Flashnet resolves and validates the plan at that moment: affiliate profiles are looked up, recipient addresses are validated against the fee settlement chain, and the settlement chain itself is locked in. The resolved plan is then frozen onto the address. Every subsequent deposit replays the frozen plan without re-evaluating profiles. Editing an affiliate profile later does not affect addresses that were created before the edit.

The two models are mutually exclusive. Pick one at creation time.

| Fee type                      | Behavior                                                                                                                                                                                                                                                                                                                                |
| ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Inline `appFees`**          | Array of `{ recipient, fee }` objects. Fees pay out immediately to each recipient during order execution. Recipients must be valid addresses on the fee settlement chain, not the destination chain.                                                                                                                                    |
| **Registered `affiliateIds`** | Array where each entry is a plain affiliate id string or a `{ affiliateId, feeBps }` object that overrides the profile's default fee bps for this address only, without mutating the stored profile. Fees are held back, accumulated for dashboard visibility, and delivered to the affiliate's configured payout destination on claim. |

```ts theme={null}
body: JSON.stringify({
  // accumulation example; liquidation uses destinationChain/destinationAsset/destinationAddress
  sourceChain: 'solana',
  sourceAsset: 'USDC',
  destinationAsset: 'BTC',
  recipientSparkAddress: 'spark1UserRecipient...',
  feeBps: 5,
  slippageBps: 50,
  affiliateIds: [
    'referrer-alice',
    { affiliateId: 'platform-fee', feeBps: 25 },
  ],
}),
```

Fee math follows the same rules as orchestration quotes. The platform fee is deducted first, then each app or affiliate fee is applied to the remainder. A 20% platform cut is retained on every app fee.

The fee settlement chain depends on the route:

* Destinations on a supported chain (any EVM chain, Solana, Tempo, and similar) settle fees on Solana USDC.
* `spark:USDB` destinations settle fees on Spark USDB.
* `spark:BTC`, `bitcoin:BTC`, and `lightning:BTC` destinations do not support fee plans, because the route has no stablecoin leg to settle against.

For a `bitcoin:BTC -> ethereum:USDC` liquidation address, the settlement chain is Solana USDC, so inline `appFees` recipients must be Solana addresses.

The `appFees` field in create, list, and get responses reflects the frozen plan. Each entry always has `recipient` and `feeBps`. Entries backed by a registered affiliate also carry `affiliateId`, and their `recipient` is the profile's configured `payoutAddress`. Inline entries omit `affiliateId`. The array is omitted entirely from responses for addresses created without a fee plan.

<Warning>
  You cannot combine `appFees` and `affiliateIds` on the same address. Pick one model at creation time.
</Warning>

<Info>
  For fee math, affiliate registration, and claim payouts, see [Quotes and Orders](/products/orchestration/api/quotes-and-orders#post-v1orchestrationquote) and [Resource Management](/products/orchestration/api/resources#affiliates).
</Info>

## Webhooks

Deposits on both primitives produce normal `order.*` webhook events. Register an endpoint with `POST /v1/webhooks`, verify `X-Flashnet-Signature` on inbound requests, and treat webhook delivery as at-least-once. See [Webhooks](/products/orchestration/webhooks).

## Next steps

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