Billing
Prepay tenant credit, see usage, and add funds from the dashboard or your agent.
Credit and pricing
Each tenant shares one balance across its applications. New accounts receive $5 welcome credit by default. Usage is metered hourly, with fractional cents carried forward until a whole cent can be charged. Empty accounts incur no usage charge.
Users, including bots, cost $1 per 1,000 users per month. The first 1 GB of object storage per tenant is included; additional storage costs $1 per GB per month. Storage uses 1 GB = 1,073,741,824 bytes. The metering month is 30 days (720 hours).
monthly cents = 100 × users / 1000
+ 100 × max(0, storage_bytes − 1073741824) / 1073741824
interval cents = monthly cents × elapsed_hours / 720
For example, 1,500 users and 3 GB storage cost $1.50 + $2.00 = $3.50 per month. One hour accrues 350 / 720 = about 0.486111 cents. A tenant with 100 users and no storage overage costs $0.10 per month. Usage is sampled at metering time; after an interruption, elapsed time is capped at 31 days.
When credit runs out
A negative balance pauses every application in the tenant. Top up to a nonnegative balance to resume. The dashboard, billing API, health checks, and public JWKS endpoint remain available. Usage routes and hosted auth pages return HTTP 402:
{
"detail": {
"error": "billing_paused",
"message": "This application's tenant has run out of credit. Top up at https://api.ezauth.org/dashboard/billing."
}
}
Pausing blocks requests; it does not delete users or stored objects. Retained users and storage continue to accrue usage charges.
Add credit
Open /dashboard/billing and choose a tenant. Pay by card through Stripe Checkout, approve a PayPal payment, or send the exact native amount to the crypto address shown. The default top-up range is $5–$1,000. Available methods depend on the operator's configuration. Supported default crypto chains are Bitcoin, Ethereum, Base, Arbitrum, Optimism, and Polygon.
Card payments complete through a verified webhook. PayPal is captured on return or completed through its webhook. Crypto credit is issued only after ezAuth rechecks confirmations.info; a callback alone cannot assert payment. Pending crypto payments can be checked manually and are also polled hourly.
Auto-reload and alerts
Select “Save card for auto-reload” during a card top-up, then enable auto-reload in billing settings. By default, ezAuth attempts a $20 card reload when the balance falls below $5. Auto-reload runs before pausing, during metering. A failed reload is retried no more than once per 24 hours; changing the saved card or a successful credit resets that failure marker.
Email warnings are optional and default to a $5 threshold. A warning is sent once until a top-up rearms it. Reload failures respect this preference; pause notices and top-up receipts are always sent. You can remove the saved card in the dashboard.
Backend billing API
Use an application's secret key. Every operation is scoped to its tenant and remains accessible while paused. USD values are exact decimal strings; send no more than two decimal places.
Check balance and methods
curl https://api.ezauth.org/v1/billing \
-H "Authorization: Bearer sk_live_..."
{
"balance_cents": 500,
"balance_usd": "5",
"paused": false,
"usage": {"users": 100, "storage_bytes": 0, "estimated_monthly_cost_cents": "10"},
"payment_methods": ["stripe", "paypal", "crypto"],
"crypto_chains": ["bitcoin", "ethereum", "base", "arbitrum", "optimism", "polygon"]
}
Create a crypto top-up
curl -X POST https://api.ezauth.org/v1/billing/topups \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{"amount_usd":"20.00","method":"crypto","chain":"base"}'
The response includes payment_id, method, status, amount_usd, chain, address, amount_native, and expires_at. Send exactly amount_native on the specified chain before expiry. The returned payment ID identifies the ezAuth top-up.
Poll the top-up
curl https://api.ezauth.org/v1/billing/topups/PAYMENT_ID \
-H "Authorization: Bearer sk_live_..."
This also checks the crypto provider and applies confirmed credit. Status is pending, completed, failed, or expired. Repeated checks never duplicate credit.
To use a browser payment, POST the same amount with method: "stripe" or "paypal". The response includes a checkout/approval url. Unconfigured methods, unsupported chains, or amounts outside the configured range return HTTP 400.
Read the ledger
curl 'https://api.ezauth.org/v1/billing/transactions?limit=50' \
-H "Authorization: Bearer sk_live_..."
Returns the newest ledger rows, including signed integer amount_cents, balance_after_cents, description, provider, details, and timestamp. The maximum limit is 200.
Operator setup
See .env.example and DEPLOYMENT.md for the Billing settings. Configure only the payment rails you offer. Set BILLING_ENABLED=false to disable metering, pausing, and enforcement.
| Provider | Webhook URL and setup |
|---|---|
| Stripe | https://api.ezauth.org/v1/billing/webhooks/stripe — register checkout.session.completed and payment_intent.succeeded; save its signing secret. |
| PayPal | https://api.ezauth.org/v1/billing/webhooks/paypal — register PAYMENT.CAPTURE.COMPLETED; configure the webhook ID for signature verification. |
| Crypto | https://api.ezauth.org/v1/billing/webhooks/crypto — supplied automatically when creating payments. |
Crypto requires a confirmations.info API key and receive addresses registered via POST /addresses. The provider monitors transfers to those addresses. Choose the correct PayPal sandbox/live environment and set the public base URL before creating payments.