# AGENTS.md: Stripe integration

## Safety first
- The agent works in **test mode only** (`sk_test_...`). Never use or request live keys, and never create real charges, refunds, or payouts.
- Keys come from env (`STRIPE_SECRET_KEY`, `STRIPE_WEBHOOK_SECRET`); the publishable key is the only one allowed in client code.
- Pin the API version in the client constructor (or the SDK default) and note it in the README.

## Payments
- Prefer Stripe Checkout or the Payment Element over custom card forms. Never handle raw card numbers.
- Prices and amounts are decided on the server from your catalog (or Stripe Price ids), never trusted from the client. Amounts are integers in the smallest currency unit.
- Pass an `idempotencyKey` on create calls that could be retried (payment intents, refunds, customers).
- Store Stripe ids (`cus_`, `pi_`, `sub_`) on your records; Stripe stays the source of truth for payment state.

## Webhooks
- Verify every event with `stripe.webhooks.constructEvent(rawBody, sig, secret)` using the raw request body.
- Fulfill orders from webhooks (`checkout.session.completed`, `invoice.paid`, `customer.subscription.updated`), not from the success redirect.
- Handlers are idempotent (record processed `event.id`s), return 2xx quickly, and do slow work in a background job.

## Testing
- Local webhooks: `stripe listen --forward-to localhost:3000/api/stripe/webhook`; trigger with `stripe trigger checkout.session.completed`.
- Unit tests mock the Stripe client; use test cards (`4242 4242 4242 4242`, `4000 0000 0000 3220` for 3DS).
