Billing & Plans
Billing is handled via Razorpay Subscriptions. Plans are defined in the plans table in the Central Registry and govern limits across all DotEvolve products.
Plans Table
plans (
slug text PRIMARY KEY,
name text NOT NULL,
display_name text,
price_monthly integer,
price_yearly integer,
features jsonb,
max_users integer, -- -1 = unlimited
max_workers integer,
max_job_steps integer,
max_article_attrs integer,
rate_limit_max integer,
rate_limit_window integer,
razorpay_plan_id text,
is_active boolean
)
Default plans: starter (5 users), growth (20 users), enterprise (unlimited).
Self-Signup Flow
sequenceDiagram
participant U as User
participant P as portal.dotevolve.net/signup
participant PA as Portal API
participant SB as Supabase Auth
participant RZP as Razorpay
U->>P: Fill signup form (org, email, password, app, plan)
P->>PA: POST /api/v1/tenants/signup
PA->>SB: Create auth user
PA->>PA: Create tenant (pending_payment)
PA->>PA: Create app assignment + user role
PA->>PA: Sync app_metadata
PA->>RZP: Create customer + subscription
RZP-->>PA: subscription_id, customer_id
PA->>PA: Store Razorpay IDs on tenant
PA-->>P: 201 Created
P-->>U: "Signup Successful — Go to Login"
note over RZP,PA: Later: payment confirmed
RZP->>PA: POST /api/v1/webhooks/razorpay (subscription.activated)
PA->>PA: Set tenant status = active
PA->>PA: Trigger subdomain provisioning
Signup Endpoints
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /api/v1/tenants/signup/apps |
public | List apps available for self-signup |
| GET | /api/v1/tenants/signup/plans |
public | List active plans with pricing |
| POST | /api/v1/tenants/signup |
public | Atomic self-signup |
Razorpay Webhook Events
| Event | Action |
|---|---|
subscription.activated |
Set status: active, trigger subdomain provisioning, create alert |
subscription.cancelled |
Set status: suspended, create alert |
subscription.halted |
Set status: suspended, create alert |
payment.failed |
Create alert for Super_Admin and Tenant_Admin |
Webhook signatures are verified via HMAC-SHA256 using the Razorpay webhook secret.
Plan Limits in Downstream Services
dot-foot-factory-api fetches plan limits from dot-portal-api at request time (Redis-cached, 15 min TTL):
GET /api/v1/internal/tenants/:tenantId/plan-limits
x-service-secret: <secret>
The response merges plan defaults with tenant-level settings overrides. This replaces the old MongoDB Plan collection.
Billing Reminders
A daily cron job in dot-portal-api queries Razorpay for upcoming renewal dates and sends reminder emails via Resend at 90, 30, 15, 7, 3, 2, and 1 days before the billing date. Cancelled and suspended tenants are skipped.