Documentation
Architecture overview, authentication, and your first API call.
Independent microservices built in Rust, deployed on Google Cloud Run.
Cari is built as a set of independent microservices, each responsible for a specific domain of healthcare operations. All services are written in Rust using the Axum web framework, backed by CockroachDB for distributed SQL storage, and deployed as containers on Google Cloud Run in the europe-west1 region.
The platform consists of the following backend services:
API gateway, PASETO auth, rate limiting, RBAC, FHIR validation
Registration, login, PASETO tokens, MFA, email verification
Doctor profiles, schedules, clinical records, prescriptions
Patient profiles, vitals, lab results, immunizations, consent
Org CRUD, members, rooms, admissions, invoices, payments
Resources, schedules, appointments, telemedicine, CHW visits
Recordings, AI transcription, clinical notes, voice dictation
Master Patient Index — matching, linking, deduplication
Drug interactions, AI diagnosis, risk scoring, early warnings
Claims, invoices, eligibility, pre-auth, fraud detection
Supply ordering, inventory, suppliers, purchase orders
Staff rostering, shifts, swaps, fairness, training, CME
Treatment protocol definitions and patient tracking
Mobile money — M-Pesa, MTN MoMo, Orange Money
WhatsApp messaging, templates, session management
Leads, contacts, campaigns, email sequences, analytics
User feedback collection (authenticated and anonymous)
Bidirectional sync with national health systems
The web application is built with Next.js (App Router) using React, TypeScript, Tailwind CSS, and Radix/shadcn UI components. It runs on Vercel or Cloud Run and communicates with the backend through a Next.js API proxy layer that forwards requests to the Rust gateway, handling cookie-based authentication transparently.
PASETO v4 public tokens — a modern, secure alternative to JWT.
Cari uses PASETO v4 (public) tokens for authentication. PASETO (Platform-Agnostic Security Tokens) is a modern alternative to JWT that eliminates entire classes of cryptographic vulnerabilities by design.
Call /api/auth/register or /api/auth/login to authenticate.
The server returns a PASETO access token and a refresh token, set as httpOnly cookies for web clients.
For API access, include the token in the Authorization header as Bearer <paseto_token>.
When the access token expires, call /api/auth/refresh with the refresh token to obtain a new access token.
Cari supports TOTP-based MFA (compliant with HIPAA 164.312(d) and NIST SP 800-63B AAL2). Use the /api/auth/mfa/enroll, /api/auth/mfa/verify, and /api/auth/mfa/challenge endpoints to manage MFA.
Web (browser)
Tokens are stored as httpOnly, secure cookies (paseto_token, refresh_token). The Next.js proxy forwards these automatically.
API (programmatic)
Include the PASETO token in the Authorization: Bearer <token> header with each request.
PASETO eliminates algorithm confusion attacks by design. Unlike JWT, there is no alg header to manipulate — the token version dictates the algorithm.
Register, authenticate, and fetch data in four steps.
curl -X POST https://api.cari.care/api/auth/register \
-H "Content-Type: application/json" \
-d '{
"email": "developer@example.com",
"password": "SecureP@ss123",
"first_name": "Jane",
"last_name": "Doe",
"registration_role": "DOCTOR"
}'curl -X POST https://api.cari.care/api/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "developer@example.com",
"password": "SecureP@ss123"
}'
# Response:
{
"success": true,
"data": {
"user": { "id": "...", "email": "developer@example.com", ... },
"token": "v4.public.eyJ..."
}
}curl https://api.cari.care/api/auth/me \
-H "Authorization: Bearer v4.public.eyJ..."
# Response:
{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "developer@example.com",
"first_name": "Jane",
"last_name": "Doe",
"roles": ["DOCTOR"]
}
}curl https://api.cari.care/api/organizations/{org_id}/patients \
-H "Authorization: Bearer v4.public.eyJ..."
# Response:
{
"success": true,
"data": [...],
"meta": { "page": 1, "limit": 20, "total": 42 }
}All API responses follow a consistent envelope format.
{
"success": true,
"data": { ... },
"meta": {
"page": 1,
"limit": 20,
"total": 100
}
}The meta field is included on paginated list endpoints. Single-resource endpoints return data without meta.
{
"success": false,
"error": {
"code": "UNAUTHORIZED",
"message": "Invalid or expired token"
}
}Validation errors
Missing or invalid token
Insufficient permissions
Resource does not exist
Too many requests
Internal server error
Per-IP rate limits enforced at the gateway using Redis-backed counters.
Auth endpoints
/api/auth/*
300 req/min
All other endpoints
Every other API path
600 req/min
When rate-limited, the API returns HTTP 429 with a message indicating when the limit resets.