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

# The two-phase authorize lifecycle: authorize, capture, release

> How Orbit's two-phase wallet authorization reserve funds for a long multi-step flow — authorize places a solvency-checked hold and locks the balance, capture settles the final figure with no second ledger movement, and release returns an abandoned hold exactly once — and when a flow uses it instead of the synchronous charge path.

# The two-phase authorize lifecycle

Most wallet charges on Orbit are **synchronous** — the platform rates the
usage and debits it in one shot, and the ledger appends one row. That path
fits any flow whose price is knowable before the money moves: a message
send, a top-up, a per-minute voice settle.

A second class of flow does not fit that shape: the [number purchase
flow](/guides/buy-numbers), a KYC-gated order, a bulk capacity
reservation, a conference event. In those flows the platform quotes a
figure, then hands the order to a third-party leg that can succeed, fail,
or sit in review for days. Pricing is exactly once — the flow either
settles at the quoted figure or abandons it — and the danger is letting
that flow tie up the wallet incorrectly in one of two ways:

1. **Charge at the end** — the wallet race. While the third-party leg
   runs, other concurrent flows keep spending from the same balance; by
   settlement time the wallet may no longer cover the original quote. The
   quote said yes, the third-party leg succeeded, and the settle debit
   fails — an instance of the
   *delivered-but-unbilled* class.
2. **Charge at the start** — the abandoned-order class. The wallet debits
   at the moment of authorization, but nothing gives the funds back when
   the order fails or times out: the balance sits locked for weeks until
   someone turns the operation into a manual refund request.

The two-phase authorize primitive exists to close both gaps with one
contract: **authorize first, then settle exactly one way.**

The lifecycle has three states and three transitions:

```
            authorize (hold)             capture (settle)
 open ───────────────────────────────► authorized ─────────────► settled
                                              │
                                              └──────────► released
                                               release (compensating credit)
```

Authorize locks the funds so every other flow sees them as spent; from
that point the flow ends in **exactly one** of two terminal outcomes —
capture, which settles at or below the authorized figure, or release,
which compensates the hold in full.

## State machine: open, authorized, settled, released

Any multi-leg flow names its own hold id (for example the order id on a
number purchase) and walks the same machine:

* **open → authorized** — when the flow begins, the authorize phase
  places a solvency-checked hold for the quoted figure. Succeeds only if
  the wallet covered it at authorize time; a wallet below the quote
  refuses the whole flow before the third-party leg is ever dialed.
* **authorized → settled** — when the third-party leg completes, the
  capture phase validates the final settled figure against the authorized
  figure. An attempt to settle for **more** than the authorized figure
  fails — if the carrier's final price came back higher mid-flight, the
  flow releases this hold and re-authorizes rather than settling past the
  quote.
* **authorized → released** — when the flow abandons (a compliance review
  that never closes, an order you cancel, a retry that established the
  reservation was no longer needed), the release phase credits back the
  authorized figure exactly once. This is the humane path that prevents
  the abandoned-hold money leak from lingering for months.

Only one terminal outcome applies per hold id. The authorize debit and
its eventual capture-feeling-row or release credit are all visible in the
append-only ledger — the same ledger the
[wallets, credits, and charges](/concepts/wallets-credits-and-charges)
concept describes — so a finance reconciliation over the tenant's own
records sees the hold, one terminal movement, and no double-count.

## Idempotency and the charge-key contract

Every authorize debit is keyed on the hold id with a `hold:<holdId>`
idempotency key, and the release phase re-derives its own one-shot credit
key from the **same** hold id. Two consequences matter for an
integration:

* **Retry-safe authorize.** If a network blip drops the authorize
  response but the debit went through, retrying with the same hold id
  collapses to the cached result and does not move the wallet again —
  the same retry semantics the
  [idempotency and safe retries](/concepts/idempotency-and-safe-retries)
  concept page guarantees for any balance mutation. Replayed authorize
  responses are flagged so your own code does not re-fire side effects
  (order creation, webhook emission, downstream leg submission) on a
  deduplicated authorize.
* **Exactly-once release.** The releasing compensation also derives its
  idempotency key from the hold id, so a concurrently retried release
  collapses to one credit. Both the hold's original debit and the
  release credit stay in the ledger — finance reconciliation sees both,
  not a silent refund.

The hold id itself is a caller-supplied slug naming the logical
reservation (on a number purchase, the order id). The slug allows
lowercase letters, digits, colons, hyphens, and underscores — a safe
shape that keeps the derived `hold:<holdId>` key collision-free across
flows.

## Where this applies: multi-leg flows

Any flow whose funds must be locked before a long-running third-party leg
completes is a candidate:

* **Number (DID) purchase** — a hold is placed at order time so the
  exact inventory quote is locked while the carrier leg runs.
* **KYC order intake** — an order with a compliance review step locks
  the amount while the review is in flight.
* **Bulk reservation** — a capacity reservation holds the quoted figure
  while a bulk scan decides which members to commit.
* **Conference billing** — a provisional authorize against a quoted
  ceiling while the event is live.

These are flow-level decisions a tenant makes. In every case the
authorize phase validates solvency before the third-party leg ever runs,
and the settle capture phase validates the final figure at or below the
authorized upper bound.

## How it differs from the synchronous charge

The synchronous debit that rates and charges a usage event in one call —
the default debits described on
[wallets, credits, and charges](/concepts/wallets-credits-and-charges) —
is correct whenever the platform can compute the price **before** money
moves. The two-phase authorize is the alternative for the class of flow
that cannot:

| | Synchronous charge | Two-phase authorize |
| - | - | - |
| Price known before money moves | yes | no (third-party leg runs first) |
| Time to settle | zero | bounded by the third-party leg |
| Wrong figure recovery | top-up + re-charge | release and re-authorize |

If a flow has no long third-party leg — a message send, a per-min voice
settle, an AI token charge — the synchronous path is the right tool and
cheaper to administer. The two-phase authorize primitive exists
precisely for the handful of flows where the quote escapes synchronous
settlement.

## Release: what an abandoned hold does

Two distinct failure shapes exist on the money path — the
over-reserve-forever leak (charge up-front on an abandoned flow) and
the under-reserve retroactive race (charge at settle time). The release
phase exists to close the first; the authorize phase exists to close the
second.

What happens on the abandon path matters for ops:

* A hold that abandons stays open on the wallet until the release phase
  runs. There is no automatic timeout sweeper — the flow owns the
  decision, and nothing about the platform guesses "the flow probably
  finished by now" into auto-compensation. If the third-party leg
  completed, the settle capture may still validate and clear the hold
  correctly even long after authorize.
* The release credit compensates the original authorize debit exactly
  once, even under concurrent abandoned-order retries, so the wallet
  ends neither locked nor double-credited.

This page is the conceptual contract. The person-level flow walkthrough
for the DID purchase path lives in the
[buying numbers guide](/guides/buy-numbers); the ledger mechanics
(idempotency, units, pause semantics) live on
[wallets, credits, and charges](/concepts/wallets-credits-and-charges);
the rating pipeline that chooses between the two authorize shapes lives
on [billing and wallet](/concepts/billing-and-wallet).

## Related pages

* [Wallets, credits, and charges](/concepts/wallets-credits-and-charges) —
  the ledger and units both charge types post into.
* [How billing meters your usage](/concepts/billing-and-wallet) — the
  rating pipeline that selects between a synchronous charge and a
  two-phase authorize.
* [Idempotency and safe retries](/concepts/idempotency-and-safe-retries) —
  the 24-hour replay window both phases ride on.
* [Buying numbers](/guides/buy-numbers) — the DID purchase flow walk
  that exercises authorize, capture, and release end to end.
