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

# ZeroConf

> Bitcoin credit before confirmation

ZeroConf offers credit for eligible Bitcoin L1 deposits before confirmation, in exchange for a fee. Use the returned `expiresAt` for the decision deadline; offers currently last five minutes from creation, not receipt.

## Mechanism

Eligibility depends on partner and route policy and an available Spark plan. An offer is not guaranteed. Under the default ordinary-order policy, `zeroconfOffer.status: "pending"` moves the order to `awaiting_approval`. Acceptance starts the credit claim and returns `processing`; the delivery pipeline still has to run. A configured legacy policy can auto-accept ordinary offers. Standing deposits always require explicit consent.

Declining or expiry falls back to 1 confirmation. Accepted credit is single-leg: confirmation releases no extra amount.

## Scope

* Source chain `bitcoin`, `exact_in` only. Exact-out orders are always confirmation-based.
* Read the order or standing deposit for an offer; quote responses do not predict one.
* The credited amount must meet the 1,000-sat execution floor.

## Ordinary orders

Act only when `status` is `awaiting_approval` and `zeroconfOffer.status` is `pending`. Accept the offer:

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST https://orchestration.flashnet.xyz/v1/orchestration/zeroconf/accept \
    -H "Authorization: Bearer SERVER_KEY" \
    -H "X-Idempotency-Key: $(uuidgen)" \
    -H "Content-Type: application/json" \
    -d '{ "orderId": "ORDER_ID" }'
  ```

  ```typescript TypeScript theme={null}
  const res = await fetch("https://orchestration.flashnet.xyz/v1/orchestration/zeroconf/accept", {
    method: "POST",
    headers: {
      Authorization: "Bearer SERVER_KEY",
      "X-Idempotency-Key": crypto.randomUUID(),
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ orderId: "ORDER_ID" }),
  });
  const { status } = await res.json(); // "processing"
  ```
</CodeGroup>

<Info>
  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`.
</Info>

Decline it instead:

```bash theme={null}
curl -X POST https://orchestration.flashnet.xyz/v1/orchestration/zeroconf/decline \
  -H "Authorization: Bearer SERVER_KEY" \
  -H "X-Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{ "orderId": "ORDER_ID" }'
```

* `409 expired`: deadline passed. `409 conflict`: order state changed; refresh.
* `400 invalid_state`: order or offer is not awaiting a decision.

### Offer fields

* `version`: schema version, `1`.
* `status`: `pending`, `accepted`, `declined`, `expired`, or `confirmed` (the transaction reached 1 confirmation before a decision).
* `quoteId`, `sparkAddress`: Spark quote and credit destination.
* `txid`, `vout`: the L1 output being credited.
* `depositSats`: gross output value.
* `instantSats`: amount credited on accept.
* `feeSats`: Spark's static-deposit fee, not a Flashnet fee.
* `expiresAt`: authoritative decision deadline.
* `offeredAt`, `resolvedAt`: offer and decision timestamps.
* `sparkTxid`: Spark transaction once the claim runs.

`depositSats = instantSats + feeSats`. Read `feeSats` from each offer; it changes per deposit. An order whose `zeroconfOffer` is `{ status: "denied", deniedAt }` received no offer and has nothing to act on.

## Standing deposits

Standing offers require partner allowlisting and explicit deposit-scoped acceptance, even when legacy auto-accept is enabled. The public shape is separate from the ordinary order offer:

```text theme={null}
{ id, status, expiresAt, depositSats, feeSats, creditSats }
status: pending | accepted | declined | expired | superseded
```

Amounts are integer strings in sats: `depositSats = creditSats + feeSats`. Provider-plan fields are not returned. Confirmation can supersede an offer.

Send `POST /v1/standing-deposit-addresses/{ref}/deposits/{depositId}/zeroconf/accept` or `/decline` with `{ "offerId": "OFFER_ID" }`, a server key, and `X-Idempotency-Key`. Accept returns `202 { deposit }`; decline returns `200 { deposit }`. Use the offer's `id`; no order need exist yet.

On `409 standing_zeroconf_offer_conflict`, refresh the deposit. Retry an uncertain decision with the same idempotency key. Without acceptance, processing waits for confirmation.
