---
title: "Release"
url: https://services.dev/docs/money/release
captured: [money-release.txt]
codes: [act_refused, region_not_ratified]
---
# Release

URL: https://services.dev/docs/money/release

> When a charge releases. The order holds the money by an authorization, a capture or a mandate, and collects it only when the fact the price names is on the record, from delivery to a verified outcome. A refusal never charges, a job that ends early charges only the paid acts already committed, and a declined charge retries before it is unpaid.

Release answers when the buyer is charged. An order holds the price, and the charge waits for one fact on the record. Until it lands, the buyer owes nothing and can see what it's waiting on.

## The facts that release a charge

| `release` | The charge waits for | Use it when |
|---|---|---|
| left out, or `'delivery'` | the job's delivery | the work is the deliverable |
| `'accept'` | the buyer's acceptance, or 7 days after delivery with no send-back | the buyer judges the work |
| a submit step's name, such as `'file'` | that step's receipt from the outside system | no filing, no charge |
| `'<step>.accepted'` | the outside system's acceptance, not only its receipt | the filing counts only once accepted |
| `'<step>.<guard>'`, such as `'meet.held'` | that step committed past its guard | the act is what you sell: a meeting the account attended |
| `'outcome'`, or an end through `price.on` | a verified outcome: [outcomes](https://services.dev/docs/money/outcomes.md) | you're paid on results |

On a list priced `per` item with a submit release, each item releases on its own receipt, so an item the outside system can't find never charges.

## How the money is held

`check` derives how an order holds the money from its release and its deadline, and prints it as `hold`:

| `price.hold` | What the order does | `check` picks it when |
|---|---|---|
| `'authorization'` | authorizes the card, and captures at the fact | the fact lands inside 7 days, while a card authorization lasts |
| `'capture'` | captures at the order and holds the money under the job, outside your balance, until the fact | the fact can land later: an outside acceptance, a long `within` |
| `'mandate'` | saves the buyer's card or bank account with their consent, and charges it off-session at the end | the amount is known only at the end: a share, or `usd: 0` |

```bash
npx services.dev check services/annual-return.ts --only hold
```

```txt title="magic values: metadata.sandbox.outside = reject_once"
services/annual-return.ts · release file.accepted, within the agency's own window
  hold    capture · every filing's acceptance can land past 7 days, past a card authorization, so the order captures it and holds it under the job
```

An authorization about to lapse before its fact is captured and held the same way, at `charge.authorization_expiring`, so a slow outside system never costs you the charge. A captured hold that returns is a refund, and its processing stays spent. A bank debit has no later capture: charged at the end, it is `pending` for about four days, then collected, and a window that holds it counts from the collection.

## Released on a receipt

One line names the fact:

```bash
grep -n "release\|ends" services/trademark-response.ts
```

```txt title="magic values: metadata.sandbox.outside = reject_once"
27:  ends: { abandoned: { charge: 'acts', by: ['client', 'clock'] } },
28:  price: { usd: 349, release: 'file' },
```

A rejection keeps the charge held while the job routes back and repairs. The receipt releases it, and it's final seven days after delivery:

```txt
→ GET /owner/matters/job_7Hq3/charges   # released on the office's receipt
```

```txt title="200 · job_7Hq3 · trademark-response · chg_7Hq3 and chg_7Hq4 · $349.00 · earned · magic values: metadata.sandbox.outside = reject_once"
  Mon 2 Nov 10:04    charge.held        $349.00   authorized at the order, both charges together, on the client's card
  Fri 6 Nov 16:40    submission.sent    file → USPTO
  Fri 6 Nov 16:41    receipt.rejected   missing_specimen → evidence          still held
  Mon 9 Nov 15:02    submission.sent    file → USPTO, with the new specimen
  Mon 9 Nov 15:12    receipt.accepted   rcp_7Hq3
  Mon 9 Nov 15:12    charge.collected   $349.00   captured: api.lawyer $174.00, the attorney $175.00
  Mon 16 Nov 15:12   charge.earned      $349.00   final, 7 days after delivery
```

## Released on the outside system's acceptance

With several filings, `'<step>.accepted'` waits for every one, and acceptance can come months after the order, so the money is captured and held under the job. A repair inside the outside system's window keeps its first filing time:

```txt
→ GET /owner/returns/job_4Tx2/charges   # released on the outside system's acceptance
```

```txt title="200 · job_4Tx2 · annual-return · chg_4Tx2 · $1,800.00 · earned · magic values: metadata.sandbox.outside = reject_once"
  2026-01-12   charge.held        $1,800.00   captured at the order and held under job_4Tx2, outside apis.tax's balance
  2026-03-09   receipt.accepted   US · rcp_4Tx2 transmitted and accepted          still held: 1 of 2
  2026-03-09   receipt.rejected   US-CA · ein_mismatch → repair                  still held
  2026-03-11   receipt.accepted   US-CA · rcp_4Tx3, inside the 10-day window, on time
  2026-03-11   charge.collected   $1,800.00   transferred to apis.tax: every filing accepted
  2026-03-18   charge.earned      $1,800.00   final
```

## Refusals never charge

A refusal holds nothing and charges nothing, whether the rules refuse the order, the gate refuses an act, or a credential is stale. The buyer pays no AI either:

```txt
→ POST /matters {"service":"contract-review","contract":"msa.pdf","client":{"name":"Ada Lovelace","email":"signs@example.test"},"client_region":"US-FL","max_usd":99,"key":"msa-1"}
```

```txt title="403 · BLOCKED · region_not_ratified · The rules don't ratify advise in US-FL. Nothing was charged. · magic values: metadata.sandbox.outside = reject_once"
  money   nothing held, nothing charged, no AI spent
  cure    the rules row's regions are US-CA, US-NY and US-TX
```

## A job that ends early

An end declares what it charges. `charge: 'acts'` charges the paid acts already committed and returns the rest of the hold, so a person who acted is paid and the buyer pays for nothing undelivered:

```txt
→ GET /owner/matters/job_7Hq8   # the client withdrew after the attorney advised
```

```txt title="200 · job_7Hq8 · contract-review · ended · withdrawn, by the client · $50.00 charged · magic values: metadata.sandbox.outside = reject_once"
  money   charge.held $99.00 → advise committed → withdrawn → charge.collected $50.00 → charge.released $49.00
  why     ends.withdrawn charges 'acts': the attorney's advice was committed, the memo was not delivered
  ledger  +$50.00 · attorney's fee $50.00, sold by the attorney (rail member) · AI $1.26 · coverage $4.00 · you −$5.26
```

A job that lapses before any paid act charges nothing:

```txt
→ GET /owner/matters/job_7Hq9   # an evidence ask lapsed before any paid act
```

```txt title="200 · job_7Hq9 · trademark-response · ended · abandoned, by the clock · $0.00 · magic values: metadata.sandbox.outside = reject_once"
  money   charge.held $349.00 → ask.expired → charge.voided · the authorization dropped, no processing
  ledger  +$0.00 · AI $0.84 · you −$0.84
```

| `ends.<end>.charge` | Charged |
|---|---|
| `true` | the whole price, as at delivery |
| `'acts'` | each paid act already committed, at its fee |
| `false` | nothing; the hold returns |

## When the charge fails

A capture from a live authorization doesn't fail. A charge made at the end, on a mandate or a renewal, can, and each one runs the same way:

| Moment | Status | Event | What happens |
|---|---|---|---|
| The bank declines | `failed` | `charge.failed` | Stripe retries on its schedule, and an `ask` asks the buyer to update their card or bank account |
| A retry collects | `collected` | `charge.collected` | the job runs on as if the first try had collected |
| `Brand.dunning` runs out, 14 days unless set | `unpaid` | `charge.unpaid` | the buyer's next orders answer 402 with the balance; accrued pay stands, and the loss is yours, with no take on it |

Outcome money and renewals run the same way: [outcomes](https://services.dev/docs/money/outcomes.md#when-the-charge-fails), [subscriptions](https://services.dev/docs/money/subscriptions.md#a-renewal-that-fails).

## The charge object

Each seller's part of a job is one charge, `chg_`, with its release fact, its dates, its amount in cents and the Stripe objects behind it ([flow of funds](https://services.dev/docs/money/flow-of-funds.md)):

```txt
→ GET /charges/chg_7Hq3
```

```json title="captured/money-release.txt · 200 · magic values: metadata.sandbox.outside = reject_once"
{
  "id": "chg_7Hq3",
  "object": "charge",
  "job": "job_7Hq3",
  "checkout": "chk_7Hq3",
  "seller": "brand",
  "amount": 17400,
  "currency": "usd",
  "status": "earned",
  "hold": "authorization",
  "release": { "on": "file", "fact": "rcp_7Hq3", "at": "2026-11-09T15:12:40Z" },
  "held_at": "2026-11-02T10:04:18Z",
  "collected_at": "2026-11-09T15:12:40Z",
  "final_at": "2026-11-16T15:12:40Z",
  "take": { "base": 17000, "rate": "plan" },
  "refunded": 0,
  "stripe": { "type": "separate", "on_behalf_of": "acct_…L4w1", "payment_intent": "pi_…Hq3", "charge": "ch_…Hq3", "transfers": ["tr_…Hq3", "tr_…Hq3c"], "transfer_group": "job_7Hq3" },
  "livemode": true
}
```

| Status | Event | Means |
|---|---|---|
| `authorized` | `charge.held` | the order authorized the price on a card |
| `held` | `charge.held` | the order captured the price and holds it under the job until the fact |
| `mandated` | `charge.mandated` | a share or a `usd: 0` price: the buyer's card or bank account and consent are saved, and no money is held |
| — | `charge.authorization_expiring` | an authorization lapses in a day: the charge is captured and held |
| `pending` | `charge.pending` | a bank debit is in flight; it collects in about four days, or fails |
| `collected` | `charge.collected` | the fact landed: the buyer is charged and the ledger splits it |
| `earned` | `charge.earned` | past the send-back window, or the outcome's |
| `released` | `charge.released` | the unused part of a hold went back |
| `voided` | `charge.voided` | the job ended with nothing to charge |
| `failed`, `unpaid` | `charge.failed`, `charge.unpaid` | a charge at the end was declined, and stayed unpaid when dunning ran out |
| `refunded` | `charge.refunded` | money went back after collection: [refunds](https://services.dev/docs/money/refunds-and-disputes.md) |

## In each app

| App | What it shows |
|---|---|
| Customer portal | Held, not charged, and the fact it waits for: "charged when the office accepts the filing", or a mandate: "charged at won, up to $12,000" |
| Delivery portal | A member's pay accrues when their act is accepted, whatever the release waits for |
| Owner console | Held money by the fact it waits on, and each job's charges with their dates |

## Every form

| Key | Written | Left out | Does |
|---|---|---|---|
| `price.release` | `'delivery' \| 'accept' \| <step> \| '<step>.accepted' \| '<step>.<guard>' \| 'outcome'` | a submit step's receipt, the last one's when there are several; else delivery | The fact that releases the charge |
| `price.hold` | `'authorization' \| 'capture' \| 'mandate'` | derived from the release and `within` | How the order holds the money |
| `ends.<end>.charge` | `true \| 'acts' \| false` | `true` | What an end charges |
| `Brand.dunning` | `{ for?: Within; ask?: boolean }` | `{ for: '14d', ask: true }` | How long a failed charge retries, and whether the buyer is asked to update their card or bank account |

| Code | When |
|---|---|
| [`release_unproven`](https://services.dev/docs/reference/check/release_unproven.md) | `check`: `price.release` names no step that runs |
| [`region_not_ratified`](https://services.dev/docs/reference/errors.md#region_not_ratified), [`act_refused`](https://services.dev/docs/reference/errors.md#act_refused) | an order or an act the rules don't allow; nothing is charged |

---

- Up: [Money](https://services.dev/docs/money.md)
- Previous: [Outcomes](https://services.dev/docs/money/outcomes.md)
- Next: [Lines and rails](https://services.dev/docs/money/lines-and-rails.md)
