# HonestMX outcome-unit billing

HonestMX uses prepaid, non-expiring outcome units. Billing is based on whether the result is usable, not whether a request consumed compute.

| Result | Units | Billing reason |
|---|---:|---|
| Live `deliverable` | 1 | `deliverable_outcome` |
| Live DNS/SMTP-derived `undeliverable` | 1 | `undeliverable_outcome` |
| `catch_all` | 0 | `catch_all_free` |
| `unknown` | 0 | `unknown_free` |
| Invalid or unsupported input | 0 | `invalid_input_free` |
| Tenant result-cache hit | 0 | `cached_result_free` |
| Finder `found` | 3 | `finder_found` |
| Finder catch-all/miss/unknown | 0 | `finder_inconclusive_free` |

`credits_charged` remains as a compatibility field; new integrations should read `billing.billable`, `billing.units_charged`, and `billing.reason`.

## Quote and cap every automated request

`POST /v1/verifications/quote` is free and creates no work. It returns invalid/unsupported inputs, seven-day cache hits and the maximum billable units for the remaining inputs. Pass an approved ceiling as `max_billable_units` to single or batch submission. HonestMX rejects the whole submission before committing work when its maximum exceeds that ceiling.

Scoped API-key `daily_limit` and `monthly_limit` values are atomic exposure caps: submissions reserve their worst-case units. This deliberately favors a hard automation budget over maximizing utilization when later outcomes prove free.

## Prepaid checkout

When the deployment has Stripe packages configured, `GET /v1/billing` lists server-selected public package IDs and `POST /v1/billing/checkout` creates a hosted Checkout Session. The client cannot supply a price, amount or unit count. Signed Stripe events apply each paid purchase to the ledger exactly once. If Stripe is not configured, these endpoints report billing as disabled; operators can continue granting or selling units manually.
