Customer Portal — API Contracts
Status: populated Owner: Product Engineering (Frontend) Last updated: 2026-04-18
1. Overview
The customer-portal does not expose its own API to external callers. This document describes:
- The Next.js Route Handlers (internal BFF endpoints) used by client components.
- The backend API endpoints consumed by Next.js server components and route handlers.
All backend calls go through Kong Gateway with Authorization: Bearer <platform-jwt>.
2. Next.js Route Handlers (BFF Layer)
These handlers live under app/api/ and are called by client-side React code. They proxy to Kong, attaching the JWT from the server-side session.
POST /api/auth/logout
Clears __session and __refresh cookies and redirects to /login.
POST /api/auth/refresh
Calls POST /v1/auth/refresh upstream; rotates __session cookie.
POST /api/api-keys
Proxies POST /v1/api-keys. Returns ApiKeyCreated to client. The rawKey field is passed through exactly once; not logged.
DELETE /api/api-keys/[keyId]
Proxies DELETE /v1/api-keys/{keyId}.
POST /api/send-test
Proxies POST /v1/messages with the test payload. Returns { messageId, status }.
POST /api/webhooks
Proxies POST /v1/webhooks. Returns newly created WebhookConfig including signingSecret.
PUT /api/webhooks/[webhookId]
Proxies PUT /v1/webhooks/{webhookId}.
DELETE /api/webhooks/[webhookId]
Proxies DELETE /v1/webhooks/{webhookId}.
3. Backend Endpoints Consumed
All URLs are relative to Kong base URL configured in NEXT_PUBLIC_API_BASE_URL / API_BASE_URL env vars.
Auth Service
| Method | Path | Used on page | Purpose |
|---|---|---|---|
| POST | /v1/auth/firebase | /login | Exchange Firebase ID token for platform JWT |
| GET | /v1/auth/me | All pages (server) | Verify customer claim; get account info |
| POST | /v1/auth/refresh | Middleware | Rotate JWT using refresh token |
| GET | /v1/api-keys | /api-keys | List API keys for account |
| POST | /v1/api-keys | /api-keys | Create new API key |
| DELETE | /v1/api-keys/{keyId} | /api-keys | Revoke API key |
SMS Orchestrator / Message Store
| Method | Path | Used on page | Purpose |
|---|---|---|---|
| POST | /v1/messages | /send-test | Send a test SMS |
| GET | /v1/messages | /messages | Paginated message log with filters |
| GET | /v1/messages/{messageId} | /messages detail | Single message detail |
Query params for GET /v1/messages:
| Param | Type | Description |
|---|---|---|
from | string | Filter by sender ID |
to | string | Filter by recipient number (E.164) |
status | string | queued, sent, delivered, failed |
startDate | ISO8601 | Inclusive start of date range |
endDate | ISO8601 | Inclusive end of date range |
page | integer | 1-based page number |
limit | integer | Max 100, default 20 |
Webhook Dispatcher
| Method | Path | Used on page | Purpose |
|---|---|---|---|
| GET | /v1/webhooks | /webhooks | List webhooks for account |
| POST | /v1/webhooks | /webhooks | Create webhook (returns signingSecret once) |
| PUT | /v1/webhooks/{webhookId} | /webhooks | Update URL / events |
| DELETE | /v1/webhooks/{webhookId} | /webhooks | Delete webhook |
Billing Service
| Method | Path | Used on page | Purpose |
|---|---|---|---|
| GET | /v1/billing/invoices | /billing | Paginated invoice list |
| GET | /v1/billing/invoices/{invoiceId} | /billing | Invoice detail + PDF URL |
| GET | /v1/billing/usage | /billing, /dashboard | Current period usage summary |
4. Standard Response Envelope
All backend services use:
{
"success": true,
"data": { ... },
"error": null,
"meta": { "page": 1, "limit": 20, "total": 143 }
}
The portal propagates error.message to the UI via toast notifications.
5. Error Handling
| HTTP Status | Portal behaviour |
|---|---|
| 401 | Attempt token refresh; if refresh fails, redirect to /login |
| 403 | Show "Access denied" toast; do not redirect |
| 422 | Display field-level validation errors in form |
| 429 | Show "Rate limit exceeded — try again shortly" toast |
| 5xx | Show generic "Something went wrong" toast; log to Sentry |