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 seeCUSTOMER-PORTAL.md.
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).
The Users tab lists every admin account and manages their lifecycle:
.
_ -) plus a password of at least 8 characters.
The new account can sign in immediately.Existing sessions stay valid until sign-out or server restart; deactivation blocks new logins.
The Rate card tab sets list prices per API operation. Changes apply to the next API call — no restart.
Three price kinds:
status,
storage-list).fixedCents per call
(e.g. transform at 4¢).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.
The Customer types tab defines plans:
Defaults: free (1×, $1 credit), pro (0.5×,
$10 credit, 8¢ default rule), business (0.25×, $100 credit,
8¢ default rule).
The Customers tab manages individual accounts:
Stripe (metered via the
billing job) or Purchase order (manual invoicing with PO
numbers and 30-day terms).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.
Everything the UI does is available over HTTP
(x-admin-key or session Bearer):
POST /admin/api/loginGET /admin/api/users ·
POST /admin/api/users ·
POST /admin/api/users/:username/activate|deactivateGET /admin/api/pricing ·
PUT/DELETE /admin/api/endpoints/:idPUT/DELETE /admin/api/tiers/:idGET/POST /admin/api/customers ·
PUT /admin/api/customers/:idPOST /admin/api/invoices/generate ·
GET /admin/api/invoices ·
POST /admin/api/invoices/:id/issue|paidGET /admin/api/reports/billing ·
GET /admin/api/reports/usage-trendGET /admin/api/zapier/status