# agent attached the wrong price id: customer billed 999 instead of 9.99

## TL;DR
Never pass a raw price id from memory or a guess; resolve it from a price catalog lookup keyed by product and amount, then assert the unit amount matches what you promised the customer before charging. If the wrong charge already landed, void or refund it, then re-invoice with the verified price. A two-line amount check catches almost every one of these.

```text
agent attached the wrong price id: customer billed 999 instead of 9.99
```

## Fix it

1. **Look the price up, don't hardcode it.** Fetch the price object from the provider by id (or list prices for the product) and read its `unit_amount` and `currency`. Success check: the fetched amount equals the amount you quoted the customer, in the smallest currency unit.
2. **Assert before charge.** Add a guard: `if price.unit_amount != expected_amount_cents: abort`. Success check: a deliberate mismatch in staging aborts with a logged error and no charge.
3. **Keep a price catalog in config.** Map human names like `pro_monthly` to price ids in a config file reviewed like code, not in the agent's working memory. Success check: the config diff shows price ids changed through review.
4. **Recover a wrong charge.** Refund or void the wrong invoice, then create a correct one and tell the customer what happened. Success check: the customer has one active invoice for the correct amount and one voided/refunded record for the wrong one.

## When this applies

- An agent selects prices programmatically and a customer was charged an amount that looks like a wrong tier or a cents-vs-dollars mixup.
- You are building checkout or invoicing flows where the agent picks the price.

## When it doesn't

- The amount is wrong because of tax, FX, or proration math; those are calculation bugs, not price-id bugs.
- A human clicked the wrong price in the dashboard; no agent involved.

## Compatibility

- Pattern: agent-driven checkout/subscription builders on Stripe (Prices API), Paddle, Chargebee, or any provider with catalog price ids.
- Stripe API 2024-06 and later; the guard pattern is provider-agnostic.

### Variant: agent charged in cents instead of dollars

The agent passed `999` meaning dollars into an amount field that expects cents. Same fix: always normalize to the smallest unit and assert against the catalog.

### Variant: test price id leaked into production

The agent used a sandbox price in live mode. Same fix plus separate catalogs per environment, loaded by environment variable, never shared.

## Why it happens

Price ids are opaque strings that look interchangeable. An agent that guesses, recalls a stale id, or confuses two similarly named prices will charge whatever that id points at, and the API will not question it.

## Edge cases

- Archived prices: the provider still accepts an archived price id in some flows; check `active` on the price object too.
- Multi-currency: the same product has different price ids per currency; the catalog key must include currency.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_ZJW8likBtylFqx6q7kU_XA
