HostAgentics Docs

HostAgentics Billing

Last updated: 2026-08-06

This document describes how billing works on the HostAgentics platform: Stripe Checkout flows, server-side price mapping, webhook processing, the subscription lifecycle, the customer portal, AI credit top-ups, and tax handling. It is an internal engineering document; the customer-facing price list lives in `docs/pricing.md` and `docs/fixed-pricing.md`.

1. Stripe Checkout flow

Plans, add-ons, and top-ups are purchased through Stripe Checkout:

1. The customer selects a plan in the dashboard. The client sends only a **product key** (e.g. `hostagentics_n8n_cloud`) and the chosen interval to the API.

2. The API resolves the canonical price from `packages/pricing` (the single source of truth), looks up the matching Stripe price ID (`STRIPE_PRICE_*` or the mirrored `products`/`plans` tables), and creates a Checkout Session server-side.

3. **Prices are never trusted from the browser.** The server maps internal product keys to Stripe price IDs; a client-supplied amount or price ID is rejected. This prevents tampering with the amount at checkout.

4. On success, Stripe redirects to the success URL; the resulting subscription or payment is recorded via webhooks (section 3), not by trusting the redirect.

2. Products, plans, and prices

  • Canonical definitions: `packages/pricing` — product keys, monthly/annual EUR prices, entitlements, AI credit, retention windows, and warning thresholds.
  • Mirrored into the database (`products`, `plans`, `planVersions`, `planEntitlements`) by seed and into Stripe by `stripe:setup` (`packages/billing`).
  • Currency is EUR (integer cents everywhere in the database). Annual plans bill once per year.
  • The database never stores a browser-supplied price; `planVersions.priceCents` comes from the canonical definition at the time the version was created.
  • 3. Webhook processing: verification, idempotency, dedupe

    Stripe webhooks (`STRIPE_WEBHOOK_SECRET`) are the source of truth for subscription and payment state:

  • **Verification**: every webhook is signature-verified before any processing.
  • **Idempotency**: event handlers are written to be re-runnable; the same event applied twice converges to the same state.
  • **Dedupe**: each processed event ID is recorded in `processedStripeEvents` (primary key = Stripe event ID). Duplicate deliveries are acknowledged and skipped. This is the replay-protection layer for billing events.
  • Handled event families: subscription created/updated/deleted, invoice paid/finalized, payment succeeded/failed, checkout completion for one-time payments (AI credit top-ups), and customer/portal updates.

    4. Subscription lifecycle

    `subscriptions.status` follows the lifecycle: `active → past_due → cancelled → retention → deleted`, with `grace_period` and `suspended` as supporting states:

  • **active** — plan entitlements apply in full.
  • **past_due** — payment failed; the platform keeps the runtime running through the grace period and retries per Stripe's dunning schedule. Customers are notified and can update their payment method via the customer portal.
  • **cancelled** — the customer (or the platform, after failed retention) ends the subscription. `cancelAtPeriodEnd` records an end-of-period cancellation; the plan stays active until the paid period ends.
  • **retention** — the step between cancellation and deletion. **Cancellation never skips retention**: after paid access ends, runtimes are stopped and data is preserved for `SUBSCRIPTION_RETENTION_DAYS` (seven days by default). Renewal/re-activation can resume the retained runtime during this window before a separate, audited deletion proceeds.
  • **deleted** — terminal; the org's runtime data is removed per the deletion policy. Deletion is a separate, audited operation (see `docs/incident-response.md` and the recovery runbook for the restore window).
  • Entitlements are re-evaluated on every plan change: the worker re-applies resource limits, AI credit grants, and retention windows from the current plan version. Add-ons (Resource Boost) are subscription items attributed to one explicit runtime (`subscriptionItems.runtimeId`).

    5. Customer portal

    The Stripe billing portal (customer session) lets customers manage payment methods, invoices, and subscription changes without exposing any billing capability through our API surface. Portal links are created server-side with the org's `stripeCustomerId`.

    6. AI credit top-ups

    AI credit top-ups (€10 / €25 / €50 / €100) are one-time payments, not subscriptions: a Checkout Session for a one-time price, settled as a payment, then credited to the org's `aiCreditWallets` balance by the webhook handler. Credits are prepaid and roll over; consumption is accounted in `aiCreditTransactions` (see `docs/ai-credit-system.md`).

    7. Tax (VAT)

    Where enabled (`STRIPE_TAX_ENABLED`), Stripe Tax calculates applicable VAT/sales tax at checkout based on the customer's jurisdiction and the registered entity details (`LEGAL_*` env vars, shown on invoices). Tax amounts are stored per invoice (`invoices.taxCents`) and appear on the invoice record. When tax is not enabled, no tax is calculated — this is a configuration decision, not a claim about tax obligations.

    8. Invoice storage

    Invoices are stored two ways: the Stripe invoice record (authoritative, with hosted invoice URL and PDF) and the mirrored `invoices` table (amount, tax, status, issue date, subscription). Mirroring keeps billing queries fast and offline of Stripe; Stripe remains the source of truth for the actual document.

    9. Related documents

  • `docs/pricing.md`, `docs/fixed-pricing.md` — customer-facing prices and policy
  • `docs/ai-credit-system.md` — wallet accounting
  • `docs/database.md` — billing schema