Billing
Stripe subscriptions, plan tiers, and trial logic (ADR-005).
Overview
Intry uses direct Stripe — no Clerk Billing. Stripe is the source of truth; Clerk org publicMetadata is the read cache for plan tier in middleware (target).
Deep runbook: docs/TENANT_BILLING.md. Pricing spec: Confluence Pricing & Packaging.
Plan tiers
| Tier | Rate | Key features |
|---|---|---|
| Core | $7/unit/mo | Onboarding, call feed, portal, basic notifications |
| Standard | $9–10/unit/mo + $99/property | DeliveryScan, Guest Passes, Rolodex, Notification Templates |
| Pro | $12–14/unit/mo | Portfolio view, Scoped roles, PMS integrations, LPR, Facial recognition |
Trial logic
| Phase | Duration | Rate |
|---|---|---|
| Phase 1 | Days 1–30 | Free (Core only, 75 resident cap) |
| Phase 2 | Days 31–90 | $4/unit |
| Phase 3 | Day 91+ | Full Core rate |
Credit card required at trial signup via Stripe SetupIntent.
Data model
| Location | Fields |
|---|---|
| Tenant | stripeCustomerId, billingPlan, billingStatus, planTier |
| Clerk org publicMetadata (target) | plan_tier, stripe_customer_id, stripe_subscription_id, trial_end, billing_unit_count, virtual_number_cap |
| User.subscription | Per-user Stripe linkage for B2C flows |
After every Stripe webhook, Core should sync DB → Clerk via ClerkBillingSync.syncOrgMetadata() (IN-204). Until fully implemented, middleware may read plan tier from Tenant DB.
Middleware
- Target: read
plan_tierfrom Clerk session — no DB hit. - Fallback: read from
Tenant.planTierin DB. - Feature gates must not be bypassed — see
Tenant.entitlementsand plan tier middleware.
Stripe webhooks
| Path | Purpose |
|---|---|
/stripe | Subscription lifecycle, invoices |
Always verify Stripe-Signature. See docs/STRIPE_WEBHOOKS_SETUP.md.
Admin API
Org billing fields readable on GET /api/admin/tenants/:id/organization. Platform admin only may PATCH billing fields.
Last verified: 2026-06-21 (commit 293c4a7)