Customer Portal — Sync Contract
Status: populated Owner: Product Engineering (Frontend) Last updated: 2026-04-18
1. Overview
The customer-portal's sync contract is its dependency on Kong-routed backend API endpoints. All communication is synchronous REST over HTTPS.
2. Kong Routes Consumed
All routes pass through Kong at https://api.ghasi.io (public) or http://kong-proxy.kong.svc.cluster.local (internal server-side).
Auth Service Routes
| Method | Kong Route | Upstream | Auth Required |
|---|---|---|---|
| POST | /v1/auth/firebase | auth-service | No (pre-login) |
| POST | /v1/auth/refresh | auth-service | Refresh token cookie |
| GET | /v1/auth/me | auth-service | Bearer JWT |
| GET | /v1/api-keys | auth-service | Bearer JWT |
| POST | /v1/api-keys | auth-service | Bearer JWT |
| DELETE | /v1/api-keys/{keyId} | auth-service | Bearer JWT |
Message Routes
| Method | Kong Route | Upstream | Auth Required |
|---|---|---|---|
| POST | /v1/messages | sms-orchestrator | Bearer JWT |
| GET | /v1/messages | message-store / sms-orchestrator | Bearer JWT |
| GET | /v1/messages/{messageId} | message-store / sms-orchestrator | Bearer JWT |
Webhook Routes
| Method | Kong Route | Upstream | Auth Required |
|---|---|---|---|
| GET | /v1/webhooks | webhook-dispatcher | Bearer JWT |
| POST | /v1/webhooks | webhook-dispatcher | Bearer JWT |
| PUT | /v1/webhooks/{webhookId} | webhook-dispatcher | Bearer JWT |
| DELETE | /v1/webhooks/{webhookId} | webhook-dispatcher | Bearer JWT |
Billing Routes
| Method | Kong Route | Upstream | Auth Required |
|---|---|---|---|
| GET | /v1/billing/invoices | billing-service | Bearer JWT |
| GET | /v1/billing/invoices/{invoiceId} | billing-service | Bearer JWT |
| GET | /v1/billing/usage | billing-service | Bearer JWT |
3. JWT Contract
Kong validates the JWT signature using the JWKS published by auth-service. The portal consumes the following JWT claims:
| Claim | Type | Notes |
|---|---|---|
sub | string | userId |
account_id | string | Account UUID |
email | string | User email |
roles | string[] | Must include customer for portal access |
exp | unix timestamp | Used by middleware for cookie expiry |
iss | string | https://api.ghasi.io |
4. Kong Headers Injected by Auth Plugin
After JWT validation, Kong injects these headers into upstream requests. The portal itself does not need to set them — they are added by Kong before reaching the backend.
| Header | Value |
|---|---|
X-Account-Id | Extracted from account_id JWT claim |
X-User-Id | Extracted from sub JWT claim |
X-Consumer-Username | Kong consumer identifier |
5. Rate Limits
Kong applies the following rate limits on portal-facing routes:
| Route Group | Limit | Window |
|---|---|---|
| Auth endpoints | 10 req | per minute per IP |
| API key creation | 5 req | per minute per account |
| Message send | 60 req | per minute per account |
| Read endpoints (GET) | 120 req | per minute per account |
The portal handles 429 responses with a toast notification: "Rate limit exceeded — please try again shortly."
6. Timeout Configuration
Next.js server component fetch calls use these timeouts:
| Endpoint Group | Timeout |
|---|---|
Auth (/v1/auth/*) | 5s |
| Message send | 10s |
| Message list / detail | 8s |
| Billing | 8s |
| Webhooks | 5s |