Skip to main content

API client and Kong integration

References: API_PATH_CONVENTIONS.md, patient-portal-requirements-doc.md §6, TECHNICAL_REQUIREMENTS.md, apps/patient-portal/README.md (web BFF → same Kong paths), packages/@ghasi/patient-portal-client (PortalApi / SchedulingApi), BACKEND_GAPS_AND_ROADMAP.md (patient-eligible routes and gaps).


1. Allowed paths

The mobile app is a browser-equivalent public client (Bearer to Kong—no Next.js BFF):

  • MAY call Kong-public /v1/... for patient flows, and /fhir/R4/... if the product exposes FHIR through Kong.
  • The web patient portal uses same-origin /api/portal/* and /api/clinical/* Route Handlers that forward to the same ${base}/v1/... URLs; mobile calls those /v1/... paths directly with Authorization: Bearer (see apps/patient-portal/README.md §API proxy pattern).
  • MUST NOT call: /internal/... (API_PATH_CONVENTIONS.md).

Base URL: https://{tenant-or-global-host} from configuration (KONG_PUBLIC_BASE_URL).


2. Authentication header

All protected calls:

Authorization: Bearer <access_token>

If using multi-tenant host routing, follow deployment docs; tenantId must still come from the token, not from user-editable fields.

JWT and patient binding: For patient-scoped scheduling and results, the access token should include patient_id or patientId matching the portal account’s patient; without it, APIs may return 403 (e.g. PATIENT_ID_CLAIM_REQUIRED). Configure Keycloak mappers accordingly (apps/patient-portal/README.md §Authentication).


3. Primary endpoints (aligned with web forwards)

Implement the logical operations defined by PortalApi and SchedulingApi in @ghasi/patient-portal-client; the HTTP mapping below matches apps/patient-portal Route Handlers (e.g. forwardPortal, forwardClinical). Authorization: many directory/scheduling routes are still staff-oriented in deployment; see BACKEND_GAPS_AND_ROADMAP.md before assuming PATIENT JWT success on every row.

3.1 Portal service (/v1/portal/...)

MethodPathPurpose
GET/v1/portal/meSession + portal account; 404 if account not provisioned for IdP subject (apps/patient-portal/README.md §Provisioning errors)
GET/v1/portal/record/summaryAggregated dashboard / record summary
GET / POST/v1/portal/appointmentsPortal appointment requests (request workflow—not the same as confirmed scheduling appointments; see GAP-BOOK-001 in BACKEND_GAPS_AND_ROADMAP.md)
POST/v1/portal/accounts/{accountId}/demographics-requestsDemographics change request
(TBD)/v1/portal/results / policy BFFReleased results list/detail when implemented (GAP-RES-001); web may use GET /v1/results?patientId= via clinical/results until portal BFF is final—follow PortalApi.listReleasedResults() in client package

Messaging, billing, export: follow module specs when licensed (SPEC.md FR-PORT-010..012).

3.2 Scheduling and provider directory (clinical APIs)

MethodPathPurpose
GET/v1/practitionersProvider search (q, status, etc.)
GET/v1/practitioners/{id}Provider detail
GET/v1/schedules?actorId=Schedules for an actor
GET/v1/slots?scheduleId=&from=&to=Available slots (web: slots route)
POST/v1/appointments/selfPatient self-service book (body omits patientId; patient context from JWT—web: appointments/self)
GET/v1/appointments?patientId=List appointments for patient (must enforce patient binding server-side—GAP-AUTH-001)
PUT/v1/appointments/{id}/cancel-selfPatient cancel own appointment (cancel-self)

Legacy / staff flows: POST /v1/appointments (non-self) may remain staff-only; mobile SHOULD use /v1/appointments/self and .../cancel-self for self-service parity with web.

Idempotency: send idempotency keys on writes if the backend supports them (patient-portal-requirements-doc.md §6).


4. Error handling

HTTPUX behavior
401Clear session or attempt refresh; then login screen
403Show “not allowed” with safe copy (no internal IDs); may indicate missing patient_id claim or module not licensed
404Treat as not found or hidden by policy—do not leak existence of resources; on GET /v1/portal/me, surface account not provisioned (apps/patient-portal/README.md §Provisioning errors)
409Conflict (e.g. slot taken)—surface retry per patient-portal-requirements-doc.md AC-Book-2
429Backoff; respect Retry-After if present

Parse structured error bodies when the API provides code / message for localization.


5. PHI in logs

  • Default no request/response body logging in production builds (COMPLIANCE_SECURITY.md §8).
  • Crash reporters: disable or filter PHI fields.

6. TLS

Use system trust store; optional certificate pinning only if security architecture mandates it (INTERNATIONAL_STANDARDS_AND_ENTERPRISE_ALIGNMENT.md §2.5).