# User Management Walkthrough How the company manages pricing, customer types, and customer accounts in the **admin console** at `/admin`. > Audience: operations staff. For invoicing/reports see `ACCOUNTING.md`; for > the end-user view see `CUSTOMER-PORTAL.md`. --- ## 1. Admin accounts Admin sign-ins live in the `admin_users` table — passwords are stored as **scrypt hashes**, never in plain text. On an empty database the table is seeded from the environment: | Account | Username | Password (dev default) | Env override | |---|---|---|---| | Primary admin | `admin` | `admin-dev-key` | `ADMIN_USER` / `ADMIN_KEY` | | Demo / stakeholder | `demo` | `$$$Adm1n###` | `DEMO_ADMIN_USER` / `DEMO_ADMIN_PASSWORD` | The seed runs **only when the table is empty** — after that, accounts are managed in the console and survive restarts (SQLite) and env changes. Sign-in issues a session token; API access is also possible with the `x-admin-key: $ADMIN_KEY` header (used by automation). ## 2. Users tab (admin account management) The **Users** tab lists every admin account and manages their lifecycle: ![Admin users](screenshots/admin-users.png) - **Create** — username (letters, digits, `.` `_` `-`) plus a password of at least 8 characters. The new account can sign in immediately. - **Deactivate / Activate** — a deactivated account is blocked from signing in right away (401), and reactivation restores access. Deactivation persists in the database. - **Safety guard** — the console refuses to deactivate the **last active admin**, so you can never lock everyone out. Existing sessions stay valid until sign-out or server restart; deactivation blocks *new* logins. ## 3. Rate card (per-endpoint pricing) The **Rate card** tab sets list prices per API operation. Changes apply to the **next API call** — no restart. ![Rate card](screenshots/admin-rate-card.png) Three price kinds: - **free** — never charged (e.g. `status`, `storage-list`). - **fixed** — a flat `fixedCents` per call (e.g. `transform` at 4¢). - **variable** — `baseCents` per call plus size-based charges: `perKbCents` per KB of metadata and `perMbCents` per MB of file attachments (e.g. `storage`: 10¢ + 1¢/KB + 50¢/MB). This is how storing data with metadata or attachments is priced by size. Add an endpoint with its `operationId` from `openapi.yaml`. Deleting an endpoint makes calls to it fail with 403 unless the customer's type has a default rule. ## 4. Customer types (tiers) The **Customer types** tab defines plans: ![Customer types](screenshots/admin-tiers.png) - **Multiplier** — scales every list price (0.5 = 50% of list, 0.25 = 75% off). - **Monthly credit (cents)** — free included usage per month, consumed before anything is billable. Defaults: `free` (1×, $1 credit), `pro` (0.5×, $10 credit, 8¢ default rule), `business` (0.25×, $100 credit, 8¢ default rule). ## 5. Customers The **Customers** tab manages individual accounts: ![Customers](screenshots/admin-customers.png) - **Type** — assign any tier. - **Multiplier override** — a per-customer deal that replaces the tier multiplier (e.g. a strategic account at 0.2×). - **Email** — used for portal login/claiming and email invoicing. - **Billing** — `Stripe` (metered via the billing job) or `Purchase order` (manual invoicing with PO numbers and 30-day terms). - **Create** — generates a customer id and API key. **The API key is shown once** in the notification — copy it immediately. Customers created here can **claim** their portal account: the first signup at `/portal` with a matching email sets their password on the existing account instead of creating a new one. ## 6. Admin API reference Everything the UI does is available over HTTP (`x-admin-key` or session Bearer): - `POST /admin/api/login` - `GET /admin/api/users` · `POST /admin/api/users` · `POST /admin/api/users/:username/activate|deactivate` - `GET /admin/api/pricing` · `PUT/DELETE /admin/api/endpoints/:id` - `PUT/DELETE /admin/api/tiers/:id` - `GET/POST /admin/api/customers` · `PUT /admin/api/customers/:id` - `POST /admin/api/invoices/generate` · `GET /admin/api/invoices` · `POST /admin/api/invoices/:id/issue|paid` - `GET /admin/api/reports/billing` · `GET /admin/api/reports/usage-trend` - `GET /admin/api/zapier/status`