ABDM PHR Frontend API Implementation Plan
Overview
This document provides a comprehensive plan for implementing ABDM PHR (Personal Health Record) APIs in the frontend application. All APIs follow RESTful conventions and return JSON responses.
Base Configuration
const API_BASE_URL = process.env.REACT_APP_API_BASE_URL || 'https://api.kulcare.com';
const API_VERSION = '/v1';
// Headers for all requests
const defaultHeaders = {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': `Bearer ${getAuthToken()}`,
};1. ABHA Address Enrollment APIs
1.1 Mobile-Based Enrollment
Send OTP to Mobile
// POST /abdm/abha/abha_address/mobile_send_otp
interface MobileSendOtpRequest {
mobile: string; // 10-digit mobile number
}
interface MobileSendOtpResponse {
success: boolean;
data: {
txn_id: string;
message: string;
otp_sent: boolean;
};
}Verify Mobile OTP
// POST /abdm/abha/abha_address/mobile_verify_otp
interface MobileVerifyOtpRequest {
txn_id: string;
otp: string; // 6-digit OTP
}
interface MobileVerifyOtpResponse {
success: boolean;
data: {
txn_id: string;
verified: boolean;
mobile: string;
abha_number?: string; // If existing ABHA number found
};
}1.2 ABHA Number-Based Enrollment
Send OTP via ABHA Number
// POST /abdm/abha/abha_address/abha_number_send_otp
interface AbhaNumberSendOtpRequest {
abha_number: string; // 14-digit ABHA number (XX-XXXX-XXXX-XXXX)
}
interface AbhaNumberSendOtpResponse {
success: boolean;
data: {
txn_id: string;
message: string;
otp_sent: boolean;
mobile_masked: string; // e.g., "******7157"
};
}Verify ABHA Number OTP
// POST /abdm/abha/abha_address/abha_number_verify_otp
interface AbhaNumberVerifyOtpRequest {
txn_id: string;
otp: string;
}
interface AbhaNumberVerifyOtpResponse {
success: boolean;
data: {
txn_id: string;
verified: boolean;
abha_number: string;
user_details: {
firstName: string;
lastName?: string;
dayOfBirth: string;
monthOfBirth: string;
yearOfBirth: string;
gender: string;
mobile: string;
email?: string;
};
};
}1.3 ABHA Address Creation
Check Address Availability
// POST /abdm/abha/abha_address/check_availability
interface CheckAvailabilityRequest {
abhaAddress: string; // Proposed ABHA address (e.g., "john.doe@sbx")
}
interface CheckAvailabilityResponse {
success: boolean;
data: {
available: boolean;
suggestions?: string[]; // Alternative suggestions if not available
};
}Suggest ABHA Address
// POST /abdm/abha/abha_address/suggest_address
interface SuggestAddressRequest {
txn_id: string;
firstName: string;
lastName?: string;
dayOfBirth: string;
monthOfBirth: string;
yearOfBirth: string;
email?: string;
}
interface SuggestAddressResponse {
success: boolean;
data: {
txn_id: string;
suggestions: string[]; // Array of suggested ABHA addresses
};
}Complete Enrollment
// POST /abdm/abha/abha_address/complete_enrollment
interface CompleteEnrollmentRequest {
txn_id: string;
phrDetails: {
firstName: string;
middleName?: string;
lastName: string;
dayOfBirth: string;
monthOfBirth: string;
yearOfBirth: string;
gender: 'M' | 'F' | 'O'; // Male, Female, Other
email: string;
mobile: string;
address: string;
stateName: string;
stateCode: string; // 2-digit state code
districtName: string;
districtCode: string; // 3-digit district code
pinCode: string; // 6-digit PIN code
abhaAddress: string; // Selected ABHA address
password: string; // Min 8 chars with 1 uppercase, 1 lowercase, 1 number, 1 special char
};
}
interface CompleteEnrollmentResponse {
success: boolean;
data: {
abha_address: string;
abha_number: string;
token: string; // JWT token for PHR session
refresh_token: string;
profile: {
fullName: string;
abhaAddress: string;
abhaNumber: string;
mobile: string;
email: string;
kycVerified: boolean;
};
};
}2. PHR Login APIs
2.1 Login via Mobile Number
Send OTP to Mobile
// POST /abdm/phr/login/mobile_send_otp
interface LoginMobileSendOtpRequest {
mobile: string;
}
interface LoginMobileSendOtpResponse {
success: boolean;
data: {
txn_id: string;
message: string;
};
}Verify Mobile OTP
// POST /abdm/phr/login/mobile_verify_otp
interface LoginMobileVerifyOtpRequest {
txn_id: string;
otp: string;
}
interface LoginMobileVerifyOtpResponse {
success: boolean;
data: {
txn_id: string;
verified: boolean;
accounts?: Array<{
abhaAddress: string;
firstName: string;
lastName?: string;
}>;
};
}2.2 Login via Email
Send OTP to Email
// POST /abdm/phr/login/email_send_otp
interface LoginEmailSendOtpRequest {
email: string;
}
interface LoginEmailSendOtpResponse {
success: boolean;
data: {
txn_id: string;
message: string;
};
}Verify Email OTP
// POST /abdm/phr/login/email_verify_otp
interface LoginEmailVerifyOtpRequest {
txn_id: string;
otp: string;
}
interface LoginEmailVerifyOtpResponse {
success: boolean;
data: {
txn_id: string;
verified: boolean;
accounts?: Array<{
abhaAddress: string;
firstName: string;
lastName?: string;
}>;
};
}2.3 Login via ABHA Address
Send Mobile OTP (ABHA Address)
// POST /abdm/phr/login/send_mobile_otp
interface AbhaAddressMobileSendOtpRequest {
abhaAddress: string;
}
interface AbhaAddressMobileSendOtpResponse {
success: boolean;
data: {
txn_id: string;
message: string;
mobile_masked: string;
};
}Verify Mobile OTP (ABHA Address)
// POST /abdm/phr/login/verify_mobile_otp
interface AbhaAddressMobileVerifyOtpRequest {
txn_id: string;
otp: string;
}
interface AbhaAddressMobileVerifyOtpResponse {
success: boolean;
data: {
token: string;
refresh_token: string;
profile: UserProfile;
};
}Send Email OTP (ABHA Address)
// POST /abdm/phr/login/send_email_otp
interface AbhaAddressEmailSendOtpRequest {
abhaAddress: string;
}
interface AbhaAddressEmailSendOtpResponse {
success: boolean;
data: {
txn_id: string;
message: string;
email_masked: string;
};
}Verify Email OTP (ABHA Address)
// POST /abdm/phr/login/verify_email_otp
interface AbhaAddressEmailVerifyOtpRequest {
txn_id: string;
otp: string;
}
interface AbhaAddressEmailVerifyOtpResponse {
success: boolean;
data: {
token: string;
refresh_token: string;
profile: UserProfile;
};
}2.4 Login via ABHA Number
Send Aadhaar OTP
// POST /abdm/phr/login/send_aadhaar_otp
interface AadhaarSendOtpRequest {
abha_number: string;
}
interface AadhaarSendOtpResponse {
success: boolean;
data: {
txn_id: string;
message: string;
mobile_masked: string;
};
}Verify Aadhaar OTP
// POST /abdm/phr/login/verify_aadhaar_otp
interface AadhaarVerifyOtpRequest {
txn_id: string;
otp: string;
}
interface AadhaarVerifyOtpResponse {
success: boolean;
data: {
txn_id: string;
verified: boolean;
accounts?: Array<{
abhaAddress: string;
firstName: string;
lastName?: string;
}>;
};
}Send ABHA OTP
// POST /abdm/phr/login/send_abha_otp
interface AbhaSendOtpRequest {
abha_number: string;
}
interface AbhaSendOtpResponse {
success: boolean;
data: {
txn_id: string;
message: string;
mobile_masked: string;
};
}Verify ABHA OTP
// POST /abdm/phr/login/verify_abha_otp
interface AbhaVerifyOtpRequest {
txn_id: string;
otp: string;
}
interface AbhaVerifyOtpResponse {
success: boolean;
data: {
txn_id: string;
verified: boolean;
accounts?: Array<{
abhaAddress: string;
firstName: string;
lastName?: string;
}>;
};
}2.5 Login via Aadhaar
Send Aadhaar OTP (Direct)
// POST /abdm/phr/login/aadhaar_send_otp
interface DirectAadhaarSendOtpRequest {
aadhaar: string; // 12-digit Aadhaar number
}
interface DirectAadhaarSendOtpResponse {
success: boolean;
data: {
txn_id: string;
message: string;
mobile_masked: string;
};
}Verify Aadhaar OTP (Direct)
// POST /abdm/phr/login/aadhaar_verify_otp
interface DirectAadhaarVerifyOtpRequest {
txn_id: string;
otp: string;
}
interface DirectAadhaarVerifyOtpResponse {
success: boolean;
data: {
txn_id: string;
verified: boolean;
abha_number?: string;
accounts?: Array<{
abhaAddress: string;
firstName: string;
lastName?: string;
}>;
};
}2.6 Complete Login (Verify User)
// POST /abdm/phr/login/verify_user
interface VerifyUserRequest {
txn_id: string;
abhaAddress: string; // Selected ABHA address from accounts list
}
interface VerifyUserResponse {
success: boolean;
data: {
token: string;
refresh_token: string;
profile: UserProfile;
};
}3. PHR Profile Management APIs
3.1 Get User Profile
// POST /abdm/abha/patients/profile
interface GetProfileRequest {
token: string; // PHR session token
}
interface UserProfile {
fullName: string;
firstName: string;
middleName?: string;
lastName?: string;
abhaAddress: string;
abhaNumber: string;
healthIdNumber: string; // Formatted ABHA number
dayOfBirth: string;
monthOfBirth: string;
yearOfBirth: string;
gender: string;
mobile: string;
email?: string;
profilePhoto?: string; // Base64 encoded
address: string;
stateName: string;
stateCode: string;
districtName: string;
districtCode: string;
pinCode: string;
kycVerified: 'VERIFIED' | 'PENDING' | 'NOT_VERIFIED';
}
interface GetProfileResponse {
success: boolean;
data: UserProfile;
}3.2 Update Profile
// POST /abdm/abha/patients/update_profile
interface UpdateProfileRequest {
token: string;
profilePhoto?: string; // Base64 encoded image
firstName: string;
middleName?: string;
lastName?: string;
dayOfBirth: string;
monthOfBirth: string;
yearOfBirth: string;
gender: string;
email?: string;
mobile: string;
address: string;
stateName: string;
districtName: string;
pinCode: string;
stateCode: string;
districtCode: string;
}
interface UpdateProfileResponse {
success: boolean;
data: {
message: string;
profile: UserProfile;
};
}3.3 Get QR Code
// POST /abdm/abha/patients/qr_code
interface GetQrCodeRequest {
token: string;
}
interface GetQrCodeResponse {
success: boolean;
data: {
qrCode: string; // Base64 encoded QR code image
qrContent: string; // QR code content/data
};
}3.4 Get ABHA Card
// POST /abdm/abha/patients/card
interface GetCardRequest {
token: string;
}
interface GetCardResponse {
success: boolean;
data: {
card: string; // Base64 encoded ABHA card image/PDF
cardType: 'PNG' | 'PDF';
};
}3.5 Logout
// POST /abdm/abha/patients/logout
interface LogoutRequest {
token: string;
}
interface LogoutResponse {
success: boolean;
data: {
message: string;
logged_out: boolean;
};
}3.6 Update Email
Send OTP to New Email
// POST /abdm/abha/patients/email_send_otp
interface EmailSendOtpRequest {
token: string;
email: string; // New email address
}
interface EmailSendOtpResponse {
success: boolean;
data: {
txn_id: string;
message: string;
};
}Verify Email OTP
// POST /abdm/abha/patients/email_verify_otp
interface EmailVerifyOtpRequest {
token: string;
txn_id: string;
otp: string;
}
interface EmailVerifyOtpResponse {
success: boolean;
data: {
message: string;
email_updated: boolean;
email: string;
};
}3.7 Update Mobile
Send OTP to New Mobile
// POST /abdm/abha/patients/mobile_send_otp
interface MobileSendOtpRequest {
token: string;
mobile: string; // New mobile number
}
interface MobileSendOtpResponse {
success: boolean;
data: {
txn_id: string;
message: string;
};
}Verify Mobile OTP
// POST /abdm/abha/patients/mobile_verify_otp
interface MobileVerifyOtpRequest {
token: string;
txn_id: string;
otp: string;
}
interface MobileVerifyOtpResponse {
success: boolean;
data: {
message: string;
mobile_updated: boolean;
mobile: string;
};
}3.8 Update Password
// POST /abdm/abha/patients/update_password
interface UpdatePasswordRequest {
token: string;
old_password: string;
new_password: string; // Min 8 chars with complexity requirements
}
interface UpdatePasswordResponse {
success: boolean;
data: {
message: string;
password_updated: boolean;
};
}4. ABHA Linking APIs
4.1 Link via ABHA OTP
Send ABHA OTP
// POST /abdm/abha/patients/link_abha_send_otp
interface LinkAbhaSendOtpRequest {
token: string;
abha_number: string;
}
interface LinkAbhaSendOtpResponse {
success: boolean;
data: {
txn_id: string;
message: string;
mobile_masked: string;
};
}Verify ABHA OTP
// POST /abdm/abha/patients/link_abha_verify_otp
interface LinkAbhaVerifyOtpRequest {
token: string;
txn_id: string;
otp: string;
}
interface LinkAbhaVerifyOtpResponse {
success: boolean;
data: {
txn_id: string;
verified: boolean;
abha_details: {
abha_number: string;
name: string;
gender: string;
year_of_birth: string;
};
};
}Complete ABHA Linking
// POST /abdm/abha/patients/link_abha_request
interface LinkAbhaRequestRequest {
token: string;
txn_id: string;
}
interface LinkAbhaRequestResponse {
success: boolean;
data: {
message: string;
linked: boolean;
abha_number: string;
};
}4.2 Link via Aadhaar OTP
Send Aadhaar OTP
// POST /abdm/abha/patients/link_aadhaar_send_otp
interface LinkAadhaarSendOtpRequest {
token: string;
aadhaar: string;
}
interface LinkAadhaarSendOtpResponse {
success: boolean;
data: {
txn_id: string;
message: string;
mobile_masked: string;
};
}Verify Aadhaar OTP
// POST /abdm/abha/patients/link_aadhaar_verify_otp
interface LinkAadhaarVerifyOtpRequest {
token: string;
txn_id: string;
otp: string;
}
interface LinkAadhaarVerifyOtpResponse {
success: boolean;
data: {
txn_id: string;
verified: boolean;
abha_number?: string;
};
}4.3 Switch Profile
Initiate Profile Switch
// POST /abdm/abha/patients/switch_profile
interface SwitchProfileRequest {
token: string;
abha_address: string; // Target ABHA address to switch to
}
interface SwitchProfileResponse {
success: boolean;
data: {
txn_id: string;
otp_required: boolean;
message: string;
};
}Verify Profile Switch
// POST /abdm/abha/patients/verify_switch_profile
interface VerifySwitchProfileRequest {
token: string;
txn_id: string;
otp?: string; // Required if OTP was sent
}
interface VerifySwitchProfileResponse {
success: boolean;
data: {
switched: boolean;
new_token: string;
new_profile: UserProfile;
};
}5. Consent Management APIs
5.1 Fetch Consent Requests
// POST /abdm/cm/consents
interface FetchConsentsRequest {
token: string;
status?: 'REQUESTED' | 'GRANTED' | 'DENIED' | 'EXPIRED' | 'REVOKED';
from_date?: string; // ISO date format
to_date?: string;
page?: number;
limit?: number;
}
interface ConsentRequest {
consent_id: string;
hip_id: string;
hip_name: string;
requester_name: string;
purpose: {
text: string;
code: string;
ref_uri?: string;
};
hi_types: string[]; // Types of health information
permission: {
access_mode: 'VIEW' | 'STORE' | 'QUERY' | 'STREAM';
date_range: {
from: string;
to: string;
};
data_erase_at: string;
frequency: {
unit: 'HOUR' | 'DAY' | 'WEEK' | 'MONTH' | 'YEAR';
value: number;
repeats?: number;
};
};
status: string;
created_at: string;
last_updated: string;
}
interface FetchConsentsResponse {
success: boolean;
data: {
consents: ConsentRequest[];
total: number;
page: number;
limit: number;
};
}5.2 Approve Consent
// POST /abdm/cm/consents/approve
interface ApproveConsentRequest {
token: string;
consent_id: string;
pin?: string; // Optional PIN for additional verification
}
interface ApproveConsentResponse {
success: boolean;
data: {
message: string;
consent_id: string;
status: 'GRANTED';
artefact_id?: string; // Consent artefact ID
};
}5.3 Deny Consent
// POST /abdm/cm/consents/deny
interface DenyConsentRequest {
token: string;
consent_id: string;
reason?: string; // Optional reason for denial
}
interface DenyConsentResponse {
success: boolean;
data: {
message: string;
consent_id: string;
status: 'DENIED';
};
}5.4 Revoke Consent
// POST /abdm/cm/consents/revoke
interface RevokeConsentRequest {
token: string;
consent_id: string;
reason?: string; // Optional reason for revocation
}
interface RevokeConsentResponse {
success: boolean;
data: {
message: string;
consent_id: string;
status: 'REVOKED';
revoked_at: string;
};
}5.5 Fetch Consent Artefacts
// POST /abdm/cm/consent_artefacts/artefacts
interface FetchArtefactsRequest {
token: string;
consent_id?: string;
from_date?: string;
to_date?: string;
page?: number;
limit?: number;
}
interface ConsentArtefact {
artefact_id: string;
consent_id: string;
hip_id: string;
hip_name: string;
granted_on: string;
revoked_on?: string;
status: 'ACTIVE' | 'REVOKED' | 'EXPIRED';
permission_details: {
access_mode: string;
date_range: {
from: string;
to: string;
};
expiry_date: string;
};
}
interface FetchArtefactsResponse {
success: boolean;
data: {
artefacts: ConsentArtefact[];
total: number;
page: number;
limit: number;
};
}5.6 Get Specific Consent Artefact
// POST /abdm/cm/consent_artefacts/artefact_consent
interface GetArtefactRequest {
token: string;
artefact_id: string;
}
interface GetArtefactResponse {
success: boolean;
data: {
artefact: ConsentArtefact;
consent_details: ConsentRequest;
};
}6. User-Initiated Linking APIs
6.1 Get Healthcare Providers
// POST /abdm/hip/patient_requests/providers
interface GetProvidersRequest {
token: string;
name?: string; // Search by provider name
state?: string;
district?: string;
pincode?: string;
type?: 'HOSPITAL' | 'CLINIC' | 'LAB' | 'PHARMACY';
page?: number;
limit?: number;
}
interface HealthcareProvider {
hip_id: string;
name: string;
type: string;
address: {
line: string;
district: string;
state: string;
pincode: string;
};
tel?: string;
email?: string;
}
interface GetProvidersResponse {
success: boolean;
data: {
providers: HealthcareProvider[];
total: number;
page: number;
limit: number;
};
}6.2 Get Provider Details
// POST /abdm/hip/patient_requests/provider_details
interface GetProviderDetailsRequest {
token: string;
hip_id: string;
}
interface GetProviderDetailsResponse {
success: boolean;
data: {
provider: HealthcareProvider;
services: string[];
facilities: string[];
timings?: {
mon_fri?: string;
saturday?: string;
sunday?: string;
};
};
}6.3 Discover Patient Records
// POST /abdm/hip/patient_requests/discover
interface DiscoverRecordsRequest {
token: string;
hip_id: string;
patient_reference?: string; // Optional patient ID at HIP
}
interface DiscoverRecordsResponse {
success: boolean;
data: {
request_id: string;
hip_id: string;
matched_patients: Array<{
reference_number: string;
display: string;
care_contexts: Array<{
reference_number: string;
display: string;
}>;
}>;
};
}6.4 Initiate Linking
// POST /abdm/hip/patient_requests/link_init
interface LinkInitRequest {
token: string;
request_id: string; // From discover response
patient_reference: string;
care_contexts: Array<{
reference_number: string;
}>;
}
interface LinkInitResponse {
success: boolean;
data: {
link_reference: string;
otp_required: boolean;
message: string;
};
}6.5 Confirm Linking
// POST /abdm/hip/patient_requests/link_confirm
interface LinkConfirmRequest {
token: string;
link_reference: string;
otp?: string; // If OTP was required
}
interface LinkConfirmResponse {
success: boolean;
data: {
linked: boolean;
hip_id: string;
patient_reference: string;
care_contexts: string[];
message: string;
};
}7. Patient Profile Sharing
7.1 Share Profile with HIP
// POST /abdm/hip/links/profile_share
interface ProfileShareRequest {
token: string;
hip_id: string;
intent: 'REGISTRATION' | 'KYC' | 'LINK';
}
interface ProfileShareResponse {
success: boolean;
data: {
shared: boolean;
hip_id: string;
shared_at: string;
message: string;
};
}Error Response Format
All APIs follow a consistent error response format:
interface ErrorResponse {
success: false;
error: {
code: string; // Error code (e.g., "INVALID_OTP", "TOKEN_EXPIRED")
message: string; // Human-readable error message
details?: any; // Additional error details
};
}Implementation Guidelines
1. API Client Setup
// api-client.ts
import axios, { AxiosInstance } from 'axios';
class AbdmApiClient {
private client: AxiosInstance;
constructor() {
this.client = axios.create({
baseURL: `${API_BASE_URL}${API_VERSION}`,
headers: defaultHeaders,
timeout: 30000,
});
// Request interceptor for auth token
this.client.interceptors.request.use(
(config) => {
const token = getAuthToken();
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error) => Promise.reject(error)
);
// Response interceptor for error handling
this.client.interceptors.response.use(
(response) => response.data,
(error) => {
if (error.response?.status === 401) {
// Handle token refresh or redirect to login
handleTokenExpiry();
}
return Promise.reject(error.response?.data || error);
}
);
}
// API methods implementation
async sendMobileOtp(data: MobileSendOtpRequest): Promise<MobileSendOtpResponse> {
return this.client.post('/abdm/abha/abha_address/mobile_send_otp', data);
}
// ... other methods
}
export default new AbdmApiClient();2. State Management
// store/abdm-store.ts
import { create } from 'zustand';
interface AbdmState {
txnId: string | null;
token: string | null;
refreshToken: string | null;
profile: UserProfile | null;
consents: ConsentRequest[];
// Actions
setTxnId: (txnId: string) => void;
setTokens: (token: string, refreshToken: string) => void;
setProfile: (profile: UserProfile) => void;
clearSession: () => void;
}
export const useAbdmStore = create<AbdmState>((set) => ({
txnId: null,
token: null,
refreshToken: null,
profile: null,
consents: [],
setTxnId: (txnId) => set({ txnId }),
setTokens: (token, refreshToken) => set({ token, refreshToken }),
setProfile: (profile) => set({ profile }),
clearSession: () => set({
txnId: null,
token: null,
refreshToken: null,
profile: null
}),
}));3. React Query Integration
// hooks/useAbdmApi.ts
import { useMutation, useQuery } from '@tanstack/react-query';
import abdmApi from '../api/abdm-api-client';
// Send OTP mutation
export const useSendMobileOtp = () => {
return useMutation({
mutationFn: (data: MobileSendOtpRequest) => abdmApi.sendMobileOtp(data),
onSuccess: (data) => {
// Store transaction ID
useAbdmStore.getState().setTxnId(data.data.txn_id);
},
});
};
// Fetch profile query
export const useProfile = (token: string) => {
return useQuery({
queryKey: ['abdm-profile', token],
queryFn: () => abdmApi.getProfile({ token }),
enabled: !!token,
staleTime: 5 * 60 * 1000, // 5 minutes
});
};4. Component Implementation
// components/AbhaEnrollment.tsx
import React, { useState } from 'react';
import { useSendMobileOtp, useVerifyMobileOtp } from '../hooks/useAbdmApi';
const AbhaEnrollment: React.FC = () => {
const [mobile, setMobile] = useState('');
const [otp, setOtp] = useState('');
const [step, setStep] = useState<'mobile' | 'otp' | 'details'>('mobile');
const sendOtp = useSendMobileOtp();
const verifyOtp = useVerifyMobileOtp();
const handleSendOtp = async () => {
try {
await sendOtp.mutateAsync({ mobile });
setStep('otp');
} catch (error) {
// Handle error
console.error('Failed to send OTP:', error);
}
};
const handleVerifyOtp = async () => {
try {
const result = await verifyOtp.mutateAsync({
txn_id: txnId,
otp
});
if (result.data.verified) {
setStep('details');
}
} catch (error) {
// Handle error
console.error('Failed to verify OTP:', error);
}
};
// Render UI based on step
return (
<div>
{/* Implementation */}
</div>
);
};Security Considerations
-
Token Management
- Store tokens securely (httpOnly cookies or secure storage)
- Implement automatic token refresh
- Clear tokens on logout
-
OTP Handling
- Never log or store OTPs
- Implement rate limiting for OTP requests
- Add OTP expiry countdown in UI
-
Data Protection
- Encrypt sensitive data in transit
- Implement field-level encryption for PII
- Regular security audits
-
Input Validation
- Validate all inputs on frontend
- Sanitize data before sending to API
- Implement CSRF protection
Testing Strategy
-
Unit Tests
- Test API client methods
- Test state management
- Test utility functions
-
Integration Tests
- Test complete flows (enrollment, login, consent)
- Test error scenarios
- Test token refresh
-
E2E Tests
- Test critical user journeys
- Test cross-browser compatibility
- Test mobile responsiveness
Performance Optimization
-
API Optimization
- Implement request debouncing
- Cache frequent requests
- Batch API calls where possible
-
State Management
- Use selective subscriptions
- Implement lazy loading
- Optimize re-renders
-
Bundle Size
- Code splitting by feature
- Lazy load components
- Tree shake unused code
Monitoring and Analytics
-
API Monitoring
- Track API response times
- Monitor error rates
- Set up alerts for failures
-
User Analytics
- Track user journey completion
- Monitor drop-off points
- Analyze user behavior
-
Performance Metrics
- Core Web Vitals
- Time to Interactive
- First Contentful Paint
Deployment Checklist
- Environment variables configured
- API endpoints verified
- Security headers implemented
- Error tracking enabled
- Performance monitoring active
- Backup and recovery tested
- Load testing completed
- Security audit passed
- Documentation updated
- Team training completed