<!-- Generated raw Markdown for /concepts/accepted-vs-finalized; product pin 638fa1e9ca7face19a442cef43754f0d627c7705. -->

A SubEtha payment settles in **two phases with two names**, and every page on
this site keeps them distinct. `accepted` is what the HTTP request path can
observe; `finalized` happens minutes later and never on the request path.
Neither implies the other has happened, and no API response, log line, or doc
sentence may use one to mean the other.

## Why two phases exist at all

x402 is synchronous: the provider must confirm payment before serving the
resource. But zERC20's construction earns its on-chain properties from the
time gap between the burn and the proven mint — the mint must **not** happen
in the same breath as the burn. SubEtha resolves that tension by splitting
settlement: serve on the burn (`accepted`), mint later (`finalized`).

## `accepted` — synchronous, on the request path

A payment is **accepted** when the burn transfer to the offer's one-time
`payTo` address is confirmed on-chain. Under the default `acceptOnReceipt`
behavior that means, concretely:

1. the burn transaction has a **successful receipt** (so it is mined — the
   facilitator effectively waits about one block),
2. the transaction's `IndexedTransfer` event pays **at least the quoted
   amount** to the burn address on the right token, and
3. the burn address **holds the funds**.

The facilitator does *not* wait for the zERC20 indexer to ingest the transfer
before accepting (`acceptOnReceipt` defaults to `true`; set it `false` for the
conservative wait-for-ingest behavior). That wait is not needed for
freeloader resistance — a successful receipt already means the funds are
burned and the payer cannot reclaim them — so it is paid later, by
finalization, which cannot proceed without it anyway.

On the x402 wire, **`/settle` success is exactly `accepted`**. The
`SettleResponse` carries `extra: { phase: "accepted" }`, and its `transaction`
field is the **burn** transaction hash — the on-chain event a payer can audit
— never the mint.

Serving is fail-closed: the middleware runs verify → handler (response
buffered) → settle, and if settle does not succeed the buffered response is
discarded and the client receives a 402. Nothing is served on a failed
settle.

## `finalized` — asynchronous, never on the request path

A payment is **finalized** when the proof-gated mint to the real recipient
(the treasury, or the FeeSplit contract) lands on-chain. This is driven by
the facilitator's **finalize loop**, off the request path:

1. wait for the indexer to ingest the burn and for the transfer root to be
   proved on-chain (on the local stack, roughly one to two minutes),
2. generate the Groth16 proof and call the official verifier
   (`Verifier.singleTeleport` on the default path),
3. the mint lands — the payment transitions to `finalized`.

No client request ever waits for this. The provider has typically served the
resource minutes before the mint exists. A payer that wants evidence of its
own payment audits the burn transaction from the `SettleResponse`; the mint
is deliberately not attributable to that burn by an on-chain observer (see
[Privacy: what SubEtha hides — and what stays public](/concepts/privacy/)).

## The gap between the two is a real state

Between `accepted` and `finalized` the facilitator's journal carries the
payment as pending. Things that can happen in that gap, and what they mean:

- **`pending_burn` (gasless path only).** If `/settle` answers while the
  facilitator's broadcast burn is still unmined, the response is
  `{ success: false, errorReason: "pending_burn" }`. Re-sending the **same**
  payload is idempotent and safe — the burn is never double-executed — but
  building a fresh payload for it risks paying twice.
- **Reorg invalidation.** A receipt is not finality. Before minting, the
  finalize pass re-verifies the chain evidence; if the burn transaction has
  vanished and the burn address readably holds less than the amount, the
  entry transitions to `failed` with a `reorg-invalidated` reason instead of
  finalizing. On the local development stack reorgs do not occur in practice;
  the machinery is the safety floor for anything beyond it.
- **Facilitator restart.** The journal restores pending entries on start and
  the finalize loop resumes them. An `accepted` payment does not need the
  payer or provider to do anything for finalization to complete.

None of these affect what was served: `accepted` already happened on its own
evidence, and the resource decision is never revisited.

## Rules this site holds itself to

- `accepted` and `finalized` are never interchanged, abbreviated to a shared
  "settled", or presented as one state with a delay.
- "Payment succeeded" on the request path always means `accepted`, nothing
  stronger.
- The mint is never described as part of serving the resource.

The normative field-by-field wire format for both phases is the
[wire protocol reference](/reference/protocol/); the conceptual walk-through
of a whole payment is [x402 v2 on SubEtha](/concepts/x402-v2/).
