Companies & Users (Admin)
Audience: Support, super-admins, ops · Where in app: /admin/companies, /admin/users, /admin/blocked · Access: Super-admin only (user_type === 'admin'); backend re-checks every endpoint.
These screens are how staff manage tenants. Companies is the primary object (a tenant — owner, subscription, AI credits, feature flags); Users is the people layer (the owner and members, with impersonation); Blocked is the moderation list (block abusive IPs, URLs, or companies). All three reuse the main backend's /company, /user, and /blocked endpoints rather than dedicated admin-only controllers — the admin gate is applied at the route/middleware level.
What it does
- Companies: search/filter every company, view a company's full profile, edit its fields and feature flags, grant manual AI credits / free periods, inspect its AI credit logs and usage, archive, and permanently delete.
- Users: search/filter every user, view/edit a user, delete, and impersonate ("login as") to reproduce a customer's exact session.
- Blocked: create/edit/delete entries that block an IP, URL, or company.
How it works
- The Companies and Users lists are thin admin wrappers over the same backend list endpoints the rest of the app uses (
GET /company,GET /user), passing admin-only filters. Pagination isskip/limit(the FE converts page/pageSize). - Impersonation calls
POST /user/:id/login, which returns a fresh auth token for the target user. The admin then operates as that user. This is the canonical way to debug "it works for me but not for the customer." - Feature flags are toggled via dedicated
PUT /company/:id/<flag>endpoints (one per flag). Most are simple toggles; a few set a numeric allowance. - AI credits are managed via
PUT /company/admin/manual-ai-creditsandPUT /company/admin/free-period. The customer-facing credit balance lives on the company's subscription; every change is audit-logged toai_credit_logs(AICreditLogModel). - Company-name resolution for cost-tracking:
POST /company/admin/names-by-idsresolves a set ofcompany_ids to names — used by the cost-tracking Company Spend tab, sincems-aidoes not store names.
Screens & fields
Companies — list (/admin/companies)
frontend/src/views/admin/companies/List.vue. Search by company name or owner.
Filters:
| Filter | Values | Param |
|---|---|---|
| Status (archived) | Active / Archived | archived |
| Client type | All / Agency / Direct | clientType |
| Subscription type | All / Trial / Active / Canceled (Trial hidden when Agency selected) | subscriptionType |
| Low AI credits | toggle | lowAiCredits |
| Agency | by agency id | agencyId |
Columns: Company, Owner, Agency (hidden for direct), Package, AI Credits, status, and Actions.
Company — detail / edit (/admin/companies/:id, .../edit)
Detail.vue / Edit.vue. View/edit company fields plus feature toggles. Toggle endpoints (frontend/src/repositories/admin/companies.js):
- Lead Intelligence (
/lead-intelligence) + allowed (/lead-intelligence-allowed) - RB2B (
/rb2b), Snitcher (/snitcher+/snitcher-allowed), Apollo (/apollo) - Verified Visitor Badge (
/verified-visitor-badge) - AI inbound/outbound call allowed (
/ai-inbound-call-allowed,/ai-outbound-call-allowed) and per-agent allowances (/ai-inbound-call-agents-allowed,/ai-outbound-call-agents-allowed) - WhatsApp agents allowed (
/whatsapp-agents-allowed) - Webhooks (
/webhooks), Affiliate link (/affiliate-link), Widget whitelabel (/widget-whitelabel) - Knox/Nox enable/disable (
POST /company/:id/knox/{enable|disable}) and Knox memories view/delete (/knox-memories)
Admin-only credit controls:
- Free period:
PUT /company/admin/free-period(free_period_minutes). - Manual AI credits:
PUT /company/admin/manual-ai-credits(credits_calculation,number_of_credits).
Lifecycle: Archive (GET /company/:id/archive) and permanent delete (DELETE /company/:id — only for archived companies; removes the company and all related data).
Company — AI Credit Logs (/admin/companies/:id/ai-credit-logs)
AICreditLogs.vue → GET /ai-credit-logs?company_id=.... The audit trail of every credit change (AICreditLogModel, collection-level audit). Each row has source (e.g. ai_tokens_credit_job, manual_ai_credits_job, subscription_renewal, buy_addon, agency_admin_set, admin_override), action (consume / refill / reset / set / addon / override), before/after/delta for remaining_ai_credits and remaining_purchased_ai_credits, consumed_credits, an optional consumption window, and token_usage/metadata. Filterable by source, action, start_date, end_date.
Note: these are customer-facing AI credits (the balance a customer spends), tracked in the main backend — distinct from the provider spend ledger in cost-tracking, which lives in
ms-ai.
Company — AI Usage (/admin/companies/:id/ai-credits-usage)
AiCreditsUsage.vue → GET /admin/companies/:id/ai-credits-usage. Detailed super-admin usage breakdown: summary, by_agent, by_model, paginated raw events, and subscription, over a from/to window.
Users — list (/admin/users)
frontend/src/views/admin/users/List.vue. Search by name or email. Filters: user_type, status. Columns: user, Company, Agency, User Type, Status, plus Actions. The Impersonate action (handleImpersonate, "Login as this user") calls POST /user/:id/login.
User — detail / edit (/admin/users/:id, .../edit)
Detail.vue / Edit.vue. View/edit user fields; a Login as User button (impersonation); shows the user's recent AI credit logs (GET /ai-credit-logs?user_id=...). Delete via DELETE /user/:id.
Moderation — Blocked List
/admin/blocked, .../create, .../:id/edit (frontend/src/views/admin/blocked/*, repo blocked.js). Block one of three types (BLOCKED_TYPE): ip, url, company. Endpoints: GET /blocked (filter by type, search), GET /blocked/:id, POST /blocked, PUT /blocked/:id, DELETE /blocked/:id. This is the entry point for shutting down abusive traffic or a bad actor company.
Behaviors & edge cases
- Impersonation is full takeover.
POST /user/:id/loginissues a real token for the target user — anything you do is done as them. Use it for support repro, and be deliberate about side effects (do not send messages / change settings as the customer unless intended). - Permanent delete is destructive and gated.
DELETE /company/:idremoves the company and all related data; the flow expects the company to be archived first.DELETE /user/:idremoves the user. Neither is reversible. - Manual AI credits bypass the normal billing path — they write directly to the subscription's credit balance and are logged with an admin source (
admin_override/manual_ai_credits_job/agency_admin_set). Use the AI Credit Logs screen to see who changed what. - Feature toggles are per-company and take effect immediately; "allowed" variants set a numeric cap rather than a boolean.
- Filters interact: selecting Agency client type hides the Trial subscription filter (and clears it if it was set), because agency subscriptions don't model trials the same way.
- Two different "credits". Customer AI credits (this cluster, main backend) ≠ provider cost credits (cost-tracking,
ms-ai, 1 credit = $0.01). Don't conflate them.
Technical implementation
- Frontend views:
frontend/src/views/admin/companies/*,frontend/src/views/admin/users/*,frontend/src/views/admin/blocked/* - Frontend repos:
frontend/src/repositories/admin/companies.js,users.js,blocked.js - Backend endpoints:
/company*,/user*,/blocked*,/ai-credit-logs,/admin/companies/:id/ai-credits-usage,/company/admin/{names-by-ids,free-period,manual-ai-credits} - Models:
AICreditLogModel(ai_credit_logs), plus Company/User/Subscription models - Related service: ../services/backend.md
Related
- overview.md — admin portal index
- revenue.md — subscription revenue
- cost-tracking.md — AI provider spend (separate "credit" concept)
- ../subsystems/identity-graph.md