Platform Administration

The SUPER_ADMIN console for running POSVelo as a multi-tenant service

Who this page is for

These are provider tools, not tenant tools. They belong to the platform owner running POSVelo as a SaaS — the SUPER_ADMIN role. A regular business ADMIN never sees them. Everything here lives under /api/v1/super-admin/* and the /admin screens, and is gated by a verified platform SUPER_ADMIN check.

The Console at a Glance

ScreenRouteWhat you do there
Tenants/admin/tenantsList, search, create, suspend / reactivate businesses
Tenant detail/admin/tenants/[id]One tenant's profile, subscription, and usage vs. limits; impersonate
Create tenant/admin/tenants/newOnboard a business directly with a chosen plan and status
Billing/admin/billingPlatform MRR, subscription counts, and the plan catalog editor
System/admin/systemMaintenance mode + cross-tenant broadcast composer
Audit/admin/auditPlatform-wide audit log viewer (every tenant)

Onboarding & Suspension

A SUPER_ADMIN can create a tenant directly — the same transaction the self-serve signup uses (tenant + main store + ADMIN user + invoice sequences), but with the plan and status set up front for sales-assisted onboarding.

MethodEndpointNotes
POST/api/v1/super-admin/tenantsCreate a tenant; omit the admin password to auto-generate a one-time temp password returned once
GET/api/v1/tenants/:id/usageCurrent plan + per-resource usage vs. limit (backs the usage view)
Suspension is instant, not next-login

Suspending a tenant takes effect on their very next request — a still-valid access token is rejected with 401 immediately, rather than continuing to work until it expires. The status is cached for ~30 seconds and invalidated the moment you change it, so a suspend (or reactivate) propagates within seconds across instances.

Impersonation

When a tenant reports a problem you cannot reproduce, you can step into their shoes — safely, and with a paper trail. Impersonation mints a separate token scoped to that tenant's oldest active ADMIN.

MethodEndpointBehavior
POST/api/v1/super-admin/tenants/:tenantId/impersonateRequires a reason (min 10 chars); returns a token that expires in a fixed 15 minutes
POST/api/v1/auth/impersonate/endEnds the session (an audit close-out) — available to the impersonation token itself
Guard rails built into impersonation

The token lasts a fixed 15 minutes regardless of the normal access-token expiry, and has no refresh token, so it cannot be silently renewed. The platform tenant itself cannot be impersonated, nor can a tenant with no active ADMIN. Both starting and ending are audited (TENANT_IMPERSONATION_STARTED / _ENDED), and GET /auth/me surfaces an impersonation claim so the app can show the “you are impersonating” banner.

Plan Catalog

The plan catalog and its Stripe sync are managed here too, from /admin/billing. Because plans, pricing, and limit enforcement are a billing concern, the full reference — including how price edits re-create Stripe Prices — lives on the billing page.

See the billing page for plan details

Creating plans, editing prices, and the limit-enforcement rules are covered in Subscriptions & Billing. The platform console is simply where a SUPER_ADMIN performs them.

Platform-Wide Audit

Every audited action across every tenant is readable in one place. A tenant ADMIN sees only their own audit trail; a SUPER_ADMIN sees all of them.

MethodEndpointScope
GET/api/v1/auditOne tenant's audit logs (ADMIN, report:read)
GET/api/v1/audit/allEvery tenant — filter by tenantId, action, entityType, entityId, date range (SUPER_ADMIN)

Maintenance Mode

Maintenance mode lets you take the API offline for a window — e.g. during a migration — while keeping the doors you need to flip it back off.

1

Enable it

PATCH /api/v1/super-admin/system/maintenance with a message. Read the current state any time with GET on the same path.

2

What still works while it's on

The gate allowlists health checks, auth, the entire super-admin surface, and Stripe webhooks — so you can still sign in, flip it back off, and keep billing flowing. Everything else returns 503.

3

Disable it

Setting it off resets the message and the enabled-by / enabled-at metadata. The state is cached ~30s, so multi-instance deployments converge within that window of a toggle.

Maintenance state lives in the platform tenant's settings

The toggle is an API call, not a redeploy — it is stored in the platform tenant's settings JSON. That is why auth and the super-admin routes stay open: an operator must always be able to authenticate and reach this endpoint to turn it back off.

Cross-Tenant Broadcast

Send a single in-app notification to users across every tenant — for a planned maintenance notice, a new feature, or a policy change.

http
How a broadcast fans out

The broadcast resolves every active user across every tenant that matches an optional plan / status filter (the platform tenant is always excluded), groups recipients by their own tenant, and writes + publishes through the same notification pipeline as a normal per-tenant broadcast — so each recipient gets it on their live bell exactly like any other notification. The action is audited with the resulting tenant and user counts. See Real-Time Notifications for the delivery mechanism.

Endpoint Summary

CapabilityEndpoint
Create tenantPOST /api/v1/super-admin/tenants
Tenant usage vs. limitsGET /api/v1/tenants/:id/usage
Impersonate / endPOST …/tenants/:id/impersonate · POST /api/v1/auth/impersonate/end
Billing overview (MRR)GET /api/v1/super-admin/billing/overview
Tenant subscriptionGET /api/v1/super-admin/tenants/:tenantId/subscription
Plan catalog CRUDGET/POST/PATCH /api/v1/super-admin/billing/plans
Platform auditGET /api/v1/audit/all
Maintenance modeGET/PATCH /api/v1/super-admin/system/maintenance
BroadcastPOST /api/v1/super-admin/system/broadcast