Customer Portal — Domain Model
Status: populated
Owner: Product Engineering (Frontend)
Last updated: 2026-04-18
1. Overview
The customer-portal is a stateless frontend. It has no persistent domain entities of its own. The domain objects described here are view-layer representations — shaped from API responses for rendering purposes.
2. View Models
AuthSession
Held in Next.js server-side session cookie (encrypted). Never exposed to client JS.
| Field | Type | Source |
|---|
userId | string | JWT sub |
accountId | string | JWT claim account_id |
email | string | JWT claim email |
roles | string[] | JWT claim roles (should include customer) |
accessToken | string | Platform JWT |
expiresAt | ISO8601 | JWT exp |
ApiKeyListItem
| Field | Type | Notes |
|---|
keyId | string | ULID key_* |
name | string | User-supplied label |
scopes | string[] | sms:send, sms:read, billing:read |
status | active | revoked | |
lastUsedAt | ISO8601 | null | |
createdAt | ISO8601 | |
ApiKeyCreated
| Field | Type | Notes |
|---|
keyId | string | |
rawKey | string | Shown once; never stored |
scopes | string[] | |
createdAt | ISO8601 | |
MessageLogEntry
| Field | Type | Notes |
|---|
messageId | string | ULID |
to | string | E.164 |
from | string | Sender ID |
body | string | |
status | queued | sent | delivered | failed | |
submittedAt | ISO8601 | |
deliveredAt | ISO8601 | null | |
operatorName | string | null | |
errorCode | string | null | |
WebhookConfig
| Field | Type | Notes |
|---|
webhookId | string | |
url | string | HTTPS only |
events | string[] | |
signingSecret | string | null | Shown once at creation |
status | active | disabled | |
createdAt | ISO8601 | |
Invoice
| Field | Type | Notes |
|---|
invoiceId | string | |
periodStart | ISO8601 | |
periodEnd | ISO8601 | |
totalMessages | number | |
amountDue | string | Pre-formatted currency string |
status | paid | open | overdue | |
pdfUrl | string | null | Pre-signed URL |
UsageSummary
| Field | Type | Notes |
|---|
currentPeriodStart | ISO8601 | |
messagesSent | number | |
messagesDelivered | number | |
deliveryRate | number | 0–1 float |
creditBalance | string | Currency-formatted |
3. UI State (client-side only)
| State | Location | Purpose |
|---|
newKeyModal open/closed | /api-keys page | Controls key creation modal |
rawKeyValue | /api-keys page | Held in state; cleared on modal close |
messageFilters | URL search params | Date range, status, to/from inputs |
testSmsForm | /send-test page | react-hook-form field values |