# Payments: how money moves

> Fees, the 7-day hold, who may refund or withdraw, and the agent flow for selling a plan.

Vibiz is the merchant. A project's app can take payments (one-time and subscriptions) from its first call, in test mode and live, with no identity check (KYC) and no Stripe account of the owner's: identity and a bank are asked for only when the owner withdraws. Alternatively the owner can connect their own Stripe account and be paid out by it directly (below). The money is the project's balance until the owner withdraws it.

## Environments

Every `vibiz_payments` call takes `env`.

- **development** = test mode: test cards (`4242 4242 4242 4242`, any future date, any CVC), no real money, no hold. Agents may do everything here, including `simulate`.
- **production** = live. Agents may read (customer emails masked) and create products, prices and checkouts. Refunds, cancels, withdrawals and webhook/statement settings are the **owner's**: an agent key gets `403 owner_only`, because an agent key never moves live money. The owner does them in the console (project ▸ Payments) or with an owner key.

## Fees

Also on `vibiz_payments get` → `fees`, which is the source of truth.

- Card processing: **2.9% + 30¢** for most US cards, taken from each payment.
- Vibiz fee: **2%** by default, `fees.platform_bps` in basis points (200 = 2%; 0 = none). It is set per account (an admin can change it), so read it rather than assume it; on the owner's own Stripe account it is `fees.own_account_bps` (also 200 by default).
- On $100 with the defaults: $3.20 processing + $2.00 Vibiz fee, **$94.80** to the balance. `fees.example` has the numbers for this account.
- Refunds don't return the processing fee or the Vibiz fee. A dispute takes the amount plus a **$15** fee.

## When the money can be withdrawn

Live payments are **pending for `fees.hold_days` (7) days**, then available (`balance.next_available_at` says when). Test mode has no hold.

## Getting paid out

The **owner** verifies their identity and adds a bank account once (console ▸ Payments ▸ Get paid; `payouts.status` goes `not_started` → `needs_info`/`verifying` → `ready`). Then Withdraw (console, or `vibiz payments withdraw` with an owner key) sends the available balance to the bank; the payout account pays out on its own schedule. Vibiz does not promise an arrival date: `withdrawal.estimated_arrival` shows one once the bank payout is scheduled. A development withdrawal only moves test money.

## The owner's own Stripe account

Payments through Vibiz are the default (`vibiz_payments get` → `account.mode: "vibiz"`). Send the owner the own-account link **only when it fits**: they say they already have a Stripe account, or want sales paid out by their own Stripe account. Then:

1. `vibiz_payments { action: "connect_own_account", project_id, env: "production" }` (or `vibiz payments connect`) → `url`.
2. Give the owner the `url`. They sign in to the console, read what changes and choose: connect their Stripe account, or keep payments through Vibiz. You can't complete it, and only they can disconnect it.
3. Afterwards `get` shows `account.mode: "own"`. New sales are charged on their account and paid out by it: no hold and no Withdraw for them. Vibiz keeps `fees.own_account_bps` there. Money already in the Vibiz balance stays there and is withdrawn as before. The app's code (checkout, `hasActive`, webhooks) doesn't change.

Don't push it: the default needs nothing from the owner until they withdraw. `account.own.available: false` means it isn't offered right now.

## Never take card numbers

A buyer pays on the hosted checkout page. To charge someone, create a checkout (`lookup_key`/`price_id`, or `amount_cents` + `name`) and send them its `url`. Never pass a card number to a tool or an API.

## Agent flow for a plan

1. `vibiz_payments create_product { name: "Pro", price: { unit_amount_cents: 1500, type: "recurring", interval: "month", lookup_key: "pro-monthly" } }` with `env: "development"` first; the same again with `env: "production"` to go live: catalogs are separate per environment.
2. The app creates checkouts with `@vibiz/app` (`vibiz_docs app-payments`).
3. `vibiz_payments simulate payment` (development) runs a real test charge through the ledger and the app's webhooks.
4. Webhooks: `vibiz_payments webhook` (`vibiz_docs webhooks`).
