ABDM (Ayushman Bharat Digital Mission) Integration
This document provides comprehensive coverage of the ABDM integration in Kulcare API Backend, enabling seamless connectivity with India's national digital health ecosystem.
Overview
The ABDM integration enables Kulcare to participate in India's unified digital health infrastructure through:
- ABHA (Ayushman Bharat Health Account) creation and management
- Health Information Provider (HIP) functionality for sharing patient data
- Health Information User (HIU) functionality for requesting patient data
- FHIR-compliant data exchange
- Care Context Linking for patient record management
- Consent Management for secure data sharing
Key Features
- Multi-modal ABHA registration (Aadhaar, Mobile)
- Patient-initiated and HIP-initiated linking
- Secure consent-based data sharing
- FHIR R4 compliant health records
- Real-time webhook handling
- Comprehensive audit trails
Architecture
The ABDM integration follows the application's parts-based architecture:
parts/abdm/
├── controllers/ # API controllers for different ABDM services
│ └── abdm/
│ ├── abha/ # ABHA registration and authentication
│ ├── hip/ # Health Information Provider endpoints
│ └── hiu/ # Health Information User endpoints
├── models/ # Data models and business logic
├── services/ # External API service integrations
├── interactors/ # Business logic orchestration
├── serializers/ # JSON response formatters
├── policies/ # Authorization policies
├── migrate/ # Database migrations
└── routes.rb # Route definitionsService Components
- ABHA Services: Handle user registration, authentication, and profile management
- HIP Services: Manage care context linking and data sharing as a provider
- HIU Services: Handle consent requests and data retrieval as a user
- Gateway Services: Manage authentication tokens and API communication
- FHIR Services: Convert Kulcare data to FHIR-compliant formats
Data Models
Core Models
AbdmGatewayToken
Manages authentication tokens for ABDM Gateway communication.
# Table: abdm_gateway_tokens
class AbdmGatewayToken < ApplicationRecord
# Columns:
# access_token: string - JWT access token
# expires_at: integer - Token expiration timestamp
# refresh_token: string - JWT refresh token
# refresh_expires_at: integer - Refresh token expiration
def is_valid?
expires_at > Time.current.to_i
end
def self.current_token
token = first
return nil unless token&.is_valid?
token.access_token
end
endAbdmService
Represents registered ABDM services for clinics.
# Table: abdm_services
class AbdmService < ApplicationRecord
belongs_to :clinic
# Columns:
# clinic_id: integer - Associated clinic
# service_type: string - HIP, HIU, or both
# service_id: string - ABDM service identifier
# active: boolean - Service status
enum service_type: { hip: 'HIP', hiu: 'HIU', both: 'BOTH' }
scope :active, -> { where(active: true) }
endAbdmCareContext
Manages care context linking between patients and health records.
# Table: abdm_care_contexts
class AbdmCareContext < ApplicationRecord
belongs_to :clinic
belongs_to :clinic_patient
belongs_to :care_context, polymorphic: true
# Columns:
# clinic_id: integer - Associated clinic
# clinic_patient_id: integer - Patient reference
# abdm_reference: string - ABDM care context reference
# abdm_display: string - Display name for care context
# care_context_id: integer - Related care context (Careplan, etc.)
# care_context_type: string - Type of care context
# status: string - Linking status (PENDING, LINKED, etc.)
# patient_notified: boolean - Patient notification status
# fhir_record: jsonb - FHIR representation of the record
enum status: {
pending: 'PENDING',
linked: 'LINKED',
unlinked: 'UNLINKED',
expired: 'EXPIRED'
}
def fhir_bundle
return fhir_record if fhir_record.present?
care_context&.fhir_careplan
end
endAbdmRequest
Tracks all ABDM API requests for audit and debugging.
# Table: abdm_requests
class AbdmRequest < ApplicationRecord
belongs_to :clinic
# Columns:
# request_id: string - Unique request identifier
# clinic_id: integer - Associated clinic
# request_type: string - Type of request
# payload: jsonb - Request payload
# response: jsonb - Response data
# status: string - Request status
# created_at: datetime - Request timestamp
enum status: {
pending: 'PENDING',
success: 'SUCCESS',
failed: 'FAILED',
timeout: 'TIMEOUT'
}
scope :recent, -> { order(created_at: :desc) }
scope :by_type, ->(type) { where(request_type: type) }
endLinking Models
HipLinkRequest
Manages HIP-initiated linking requests.
# Table: hip_link_requests
class HipLinkRequest < ApplicationRecord
belongs_to :clinic
belongs_to :clinic_patient
# Columns:
# clinic_id: integer - Associated clinic
# clinic_patient_id: integer - Patient reference
# request_id: string - ABDM request ID
# status: string - Request status
# modes: jsonb - Available authentication modes
# link_token: string - Generated link token
# expires_at: datetime - Token expiration
enum status: {
initiated: 'INITIATED',
auth_required: 'AUTH_REQUIRED',
completed: 'COMPLETED',
failed: 'FAILED'
}
def expired?
expires_at < Time.current
end
endHipConsent
Tracks consent artifacts and permissions.
# Table: hip_consents
class HipConsent < ApplicationRecord
belongs_to :clinic
belongs_to :clinic_patient
# Columns:
# consent_id: string - ABDM consent identifier
# clinic_id: integer - Associated clinic
# clinic_patient_id: integer - Patient reference
# status: string - Consent status
# consent_detail: jsonb - Consent artifact details
# granted_at: datetime - When consent was granted
# expires_at: datetime - When consent expires
enum status: {
requested: 'REQUESTED',
granted: 'GRANTED',
denied: 'DENIED',
expired: 'EXPIRED',
revoked: 'REVOKED'
}
scope :active, -> { where(status: 'GRANTED').where('expires_at > ?', Time.current) }
def active?
granted? && expires_at > Time.current
end
endHiuConsentRequest
Manages HIU consent requests for data access.
# Table: hiu_consent_requests
class HiuConsentRequest < ApplicationRecord
belongs_to :clinic
belongs_to :doctor
belongs_to :clinic_patient
# Columns:
# clinic_id: integer - Requesting clinic
# doctor_id: integer - Requesting doctor
# clinic_patient_id: integer - Target patient
# health_id: string - Patient's ABHA ID
# purpose_code: string - Purpose of data request
# hi_types: jsonb - Types of health information requested
# start_ts: datetime - Data request start date
# end_ts: datetime - Data request end date
# expire_at: datetime - Consent expiration
# status: string - Request status
# consent_request_id: string - ABDM consent request ID
# data_fetch_status: string - Data retrieval status
enum status: {
initiated: 'INITIATED',
pending: 'PENDING',
granted: 'GRANTED',
denied: 'DENIED',
expired: 'EXPIRED'
}
enum data_fetch_status: {
not_started: 'NOT_STARTED',
in_progress: 'IN_PROGRESS',
completed: 'COMPLETED',
failed: 'FAILED'
}
endAPI Endpoints
ABHA Registration & Authentication
Aadhaar-based Registration
POST /abdm/abha/auth/aadhaar_signup/send_otp
POST /abdm/abha/auth/aadhaar_signup/verify_otp
POST /abdm/abha/auth/aadhaar_signup/send_mobile_otp
POST /abdm/abha/auth/aadhaar_signup/verify_mobile_otp
POST /abdm/abha/auth/aadhaar_signup/create_abha_address
POST /abdm/abha/auth/aadhaar_signupExample: Send Aadhaar OTP
curl -X POST https://api.kulcare.com/abdm/abha/auth/aadhaar_signup/send_otp \
-H "Authorization: Bearer YOUR_AUTH_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"aadhaar_number": "123456789012"
}'Response:
{
"success": true,
"message": "OTP sent successfully",
"data": {
"transaction_id": "txn_abc123",
"expires_in": 300
}
}Mobile-based Authentication
POST /abdm/abha/auth/mobile/send_otp
POST /abdm/abha/auth/mobile/verify_otpABHA Login
POST /abdm/abha/mobile/login/send_otp
POST /abdm/abha/mobile/login/verify_otp
POST /abdm/abha/mobile/loginHIP (Health Information Provider) Endpoints
Care Context Linking
POST /abdm/hip/links/fetch_modes
GET /abdm/hip/links/auth_modes
POST /abdm/hip/links/auth_init
POST /abdm/hip/links/auth_confirm
POST /abdm/hip/links/link_token_generate
POST /abdm/hip/links/add_contexts
POST /abdm/hip/links/notify_patient
POST /abdm/hip/links/check_tokenExample: Generate Link Token
curl -X POST https://api.kulcare.com/abdm/hip/links/link_token_generate \
-H "Authorization: Bearer YOUR_AUTH_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"patient_reference": "patient_123",
"care_contexts": [
{
"reference": "careplan_456",
"display": "Diabetes Management Plan"
}
]
}'HIU (Health Information User) Endpoints
Consent Requests
POST /abdm/hiu/consent_requests
GET /abdm/hiu/consent_requests
GET /abdm/hiu/consent_requests/:idExample: Create Consent Request
curl -X POST https://api.kulcare.com/abdm/hiu/consent_requests \
-H "Authorization: Bearer YOUR_AUTH_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"patient_health_id": "patient@abdm",
"purpose_code": "CAREMGT",
"hi_types": ["Prescription", "DiagnosticReport"],
"date_range": {
"from": "2024-01-01",
"to": "2024-12-31"
},
"data_expire_at": "2025-06-30"
}'Webhook Endpoints
ABDM Gateway sends callbacks to these endpoints:
HIP Linking Webhooks
POST /abdm/v0.5/users/auth/on-fetch-modes
POST /abdm/v0.5/users/auth/on-init
POST /abdm/v0.5/users/auth/on-confirm
POST /abdm/api/v3/hip/token/on-generate-token
POST /abdm/v0.5/users/auth/notify
POST /abdm/v1.0/patients/profile/share
POST /abdm/v0.5/links/link/on-add-contexts
POST /abdm/v0.5/patients/sms/on-notifyPatient Linking Webhooks
POST /abdm/v0.5/care-contexts/discover
POST /abdm/v0.5/links/link/init
POST /abdm/v0.5/links/link/confirmConsent Webhooks
POST /abdm/v0.5/consents/hip/notify
POST /abdm/v0.5/consent-requests/on-init
POST /abdm/v0.5/consents/hiu/notify
POST /abdm/v0.5/consents/on-fetchData Transfer Webhooks
POST /abdm/v0.5/health-information/hip/request
POST /abdm/v0.5/health-information/hiu/on-request
POST /abdm/hiu/data/notificationFHIR Implementation
Kulcare implements FHIR R4 standards for health data exchange.
Supported FHIR Resources
Core Resources
- Bundle: Container for all resources
- Composition: Document structure and metadata
- Patient: Patient demographics and identifiers
- Practitioner: Healthcare provider information
- Organization: Healthcare facility details
- Encounter: Clinical encounter information
Clinical Resources
- Condition: Diagnosis and health problems
- MedicationRequest: Prescribed medications
- Observation: Clinical observations and measurements
- Appointment: Follow-up appointments
- CarePlan: Treatment plans and care coordination
FHIR Bundle Structure
# Example FHIR Bundle generation
def fhir_careplan
FhirBundle.new(
resourceType: 'Bundle',
id: Util.encode_id(id),
type: 'document',
timestamp: created_at.iso8601,
entry: [
fhir_composition_entry,
fhir_patient_entry,
fhir_practitioner_entry,
fhir_organisation_entry,
fhir_encounter_entry,
*fhir_condition_entries,
*fhir_medication_entries
]
)
endData Mapping
| Kulcare Entity | FHIR Resource | Mapping Notes |
|---|---|---|
| ClinicPatient | Patient | Demographics and identifiers |
| Doctor | Practitioner | Healthcare provider details |
| Clinic | Organization | Healthcare facility |
| Appointment | Encounter | Clinical encounter |
| CareplanComplaint | Condition | Diagnosis and problems |
| CareplanMedicine | MedicationRequest | Prescriptions |
| Careplan | Composition | Document structure |
Example FHIR Patient Resource
{
"resourceType": "Patient",
"id": "patient_123",
"identifier": [
{
"use": "usual",
"system": "https://healthid.ndhm.gov.in",
"value": "patient@abdm"
}
],
"name": [
{
"use": "official",
"text": "John Doe",
"given": ["John"],
"family": "Doe"
}
],
"telecom": [
{
"system": "phone",
"value": "+91-9999999999",
"use": "mobile"
}
],
"gender": "male",
"birthDate": "1990-01-01",
"address": [
{
"use": "home",
"text": "123 Main Street, Mumbai, Maharashtra, India",
"city": "Mumbai",
"state": "Maharashtra",
"country": "IN"
}
]
}Authentication Flows
ABHA Registration Flow
Aadhaar-based Registration
- Send Aadhaar OTP: Initiate registration with Aadhaar number
- Verify Aadhaar OTP: Confirm Aadhaar authentication
- Send Mobile OTP: Verify mobile number
- Verify Mobile OTP: Confirm mobile authentication
- Suggest Address: Get ABHA address suggestions
- Create ABHA Address: Finalize ABHA creation
- Complete Registration: Receive ABHA credentials
Mobile-based Registration
- Send Mobile OTP: Initiate with mobile number
- Verify Mobile OTP: Complete mobile verification
- Create Profile: Complete ABHA profile setup
Login Flow
Mobile Login
- Send Login OTP: Request OTP for existing ABHA
- Verify Login OTP: Authenticate user
- Receive Tokens: Get access and refresh tokens
Care Context Linking
HIP-Initiated Linking
- Fetch Authentication Modes: Get available auth methods
- Initialize Authentication: Start auth process
- Confirm Authentication: Complete patient verification
- Generate Link Token: Create secure linking token
- Add Care Contexts: Link patient records
- Notify Patient: Inform patient of successful linking
Patient-Initiated Linking
- Discover Care Contexts: Patient searches for records
- Initialize Linking: Patient initiates link request
- Confirm Linking: Complete the linking process
Implementation Example
# Generate link token for patient
class GenerateLinkToken
def self.call(clinic:, patient:, care_contexts:)
# Create link request
link_request = HipLinkRequest.create!(
clinic: clinic,
clinic_patient: patient,
request_id: SecureRandom.uuid,
status: 'initiated'
)
# Generate secure token
token = SecureRandom.base64(32)
link_request.update!(
link_token: token,
expires_at: 1.hour.from_now
)
# Create care contexts
care_contexts.each do |context_data|
AbdmCareContext.create!(
clinic: clinic,
clinic_patient: patient,
abdm_reference: context_data[:reference],
abdm_display: context_data[:display],
care_context: context_data[:resource],
status: 'pending'
)
end
# Send to ABDM Gateway
AbdmGateway::TokenService.notify_token_generation(
link_request.request_id,
token
)
link_request
end
endConsent Management
HIU Consent Request Flow
- Create Consent Request: Request permission to access data
- Wait for Approval: Patient approves through PHR app
- Receive Consent Artifact: Get approved consent details
- Request Data: Fetch health information from HIP
- Process Data: Handle received FHIR data
HIP Data Sharing Flow
- Receive Consent: Process consent artifact
- Prepare Data: Convert records to FHIR format
- Encrypt & Share: Securely transmit data
- Audit: Log all data sharing activities
Implementation Example
# Create HIU consent request
class CreateConsentRequest
def self.call(clinic:, doctor:, patient:, purpose:, hi_types:, date_range:)
consent_request = HiuConsentRequest.create!(
clinic: clinic,
doctor: doctor,
clinic_patient: patient,
health_id: patient.health_id,
purpose_code: purpose,
hi_types: hi_types,
start_ts: date_range[:from],
end_ts: date_range[:to],
expire_at: 6.months.from_now,
status: 'initiated'
)
# Send to ABDM Gateway
response = AbdmGateway::ConsentService.create_request(
consent_request.consent_request_id,
{
patient: { id: patient.health_id },
hiu: { id: clinic.abdm_service.service_id },
requester: {
name: doctor.full_name,
identifier: doctor.registration_number
},
purpose: { code: purpose },
hiTypes: hi_types,
permission: {
accessMode: 'VIEW',
dateRange: date_range,
dataEraseAt: 1.year.from_now,
frequency: { unit: 'HOUR', value: 1 }
}
}
)
if response.success?
consent_request.update!(
consent_request_id: response.data['consentRequestId'],
status: 'pending'
)
else
consent_request.update!(status: 'failed')
end
consent_request
end
endSecurity & Privacy
Data Protection
- Encryption: All sensitive data encrypted at rest and in transit
- Token Security: JWT tokens securely stored and transmitted
- Audit Trails: Complete logging of all ABDM operations
- Access Control: Role-based access to ABDM functions
Privacy Compliance
- Consent Management: Explicit consent for all data sharing
- Data Minimization: Only share necessary health information
- Right to Withdraw: Support consent withdrawal
- Data Retention: Proper data retention and deletion policies
ABDM Compliance
- FHIR Standards: Full compliance with FHIR R4
- ABDM Protocols: Adherence to ABDM integration guidelines
- Security Standards: Implementation of ABDM security requirements
- Audit Requirements: Meeting ABDM audit and logging standards
Error Handling
Common Error Scenarios
- Authentication Failures: Invalid OTP, expired tokens
- Authorization Errors: Insufficient permissions
- Network Issues: Gateway timeouts, connectivity problems
- Data Validation: Invalid FHIR data, missing required fields
- Consent Issues: Expired consent, insufficient permissions
Error Response Format
{
"success": false,
"message": "Detailed error message",
"error_code": "ABDM_ERROR_CODE",
"errors": {
"field": ["Specific field errors"]
}
}Error Recovery Strategies
- Retry Logic: Automatic retry for transient failures
- Token Refresh: Automatic token renewal
- Fallback Mechanisms: Alternative flows for critical operations
- User Feedback: Clear error messages for user action
Monitoring & Debugging
Key Metrics
- Token Refresh Rate: Frequency of token renewals
- Webhook Success Rate: Percentage of successful webhook processing
- Care Context Linking Rate: Success rate of linking operations
- Data Sharing Volume: Amount of health data shared
- Error Rates: Frequency and types of errors
Debug Commands
Check ABDM Service Status
clinic = Clinic.find(clinic_id)
abdm_service = clinic.abdm_services.first
puts "Service Type: #{abdm_service.service_type}"
puts "Service ID: #{abdm_service.service_id}"Validate FHIR Data
careplan = Careplan.find(careplan_id)
fhir_bundle = careplan.fhir_careplan
puts "FHIR Bundle: #{fhir_bundle.to_json}"Check Request History
requests = AbdmRequest.where(clinic_id: clinic_id)
.order(created_at: :desc)
.limit(5)
requests.each do |req|
puts "Type: #{req.request_type}, Status: #{req.status}"
endHealth Check Endpoint
# GET /abdm/health
def health_check
{
gateway_token: AbdmGatewayToken.first&.is_valid?,
recent_webhooks: AbdmWebhook.where('created_at > ?', 1.hour.ago).count,
active_consents: HipConsent.where(status: 'GRANTED').count,
pending_links: AbdmCareContext.where(status: 'PENDING').count
}
endIntegration Best Practices
For Mobile Applications
- Token Storage: Securely store ABHA tokens using encrypted storage
- Token Refresh: Implement automatic token refresh mechanism
- Error Handling: Graceful handling of network and API errors
- User Experience: Clear feedback for ABDM operations
- Privacy: Ensure user consent before any data sharing
- Offline Support: Cache essential data for offline access
For Backend Integration
- Webhook Reliability: Implement retry mechanisms for webhook processing
- Data Validation: Validate all FHIR data before sharing
- Consent Verification: Always verify consent before data access
- Audit Logging: Log all ABDM operations for compliance
- Error Monitoring: Monitor and alert on ABDM integration failures
Related Documentation
- Authentication System - User authentication and authorization
- Medical Records APIs - Medical record management
- Patient APIs - Patient management endpoints
- FHIR Implementation Guide - FHIR standards compliance