Audit Trail API Integration Guide
Overview
This document provides comprehensive API integration details for the KulCare audit trail system. It covers all endpoints, parameters, response formats, and implementation guidelines for frontend applications and external integrations.
Table of Contents
- Authentication
- Base URLs
- Clinic-Level Endpoints
- Admin-Level Endpoints
- Response Formats
- Error Handling
- Rate Limiting
- Integration Examples
Authentication
All audit trail endpoints require authentication using JWT Bearer tokens.
Header Format:
Authorization: Bearer <jwt_token>Required Permissions:
- Clinic Endpoints: User must be authorized for the specific clinic
- Admin Endpoints: User must have admin role permissions
Base URLs
Production: https://api.kulcare.com
Staging: https://api-stg.kulcare.comClinic-Level Endpoints
1. GET /clinics/:clinic_id/audit_trails
Retrieve audit trails for a specific clinic with filtering and pagination.
URL: /clinics/{clinic_id}/audit_trails
Method: GET
Authentication: Required - Clinic authorization
Path Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| clinic_id | integer | Yes | Unique clinic identifier |
Query Parameters:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| page | integer | No | 1 | Page number for pagination |
| per_page | integer | No | 50 | Records per page (max: 200) |
| start_date | string | No | - | Filter start date (YYYY-MM-DD) |
| end_date | string | No | - | Filter end date (YYYY-MM-DD) |
| user_id | integer | No | - | Filter by specific user ID |
| event_key | string | No | - | Filter by event type |
| status | string | No | - | Filter by status (success/failure/failed) |
| patient_id | integer | No | - | Filter by patient ID |
| clinic_patient_id | integer | No | - | Filter by clinic patient ID |
Event Key Options:
Patient Management:
- patient.view
- patient.create
- patient.update
- patient.delete
- patient.medical_record.create
- patient.vital.create
- patient.medication.create
Appointments:
- appointment.book
- appointment.cancel
- appointment.update
Care Plans:
- careplan.update
- careplan.send
- careplan.email_send
- careplan.print
Billing:
- bill.create
- bill.delete
- payment.create
- payment.update
- payment.refund
Authentication:
- auth.login
- auth.logout
- auth.failed_login
- auth.registration
Administrative:
- audit.exportExample Request:
curl -X GET \
"https://api.kulcare.com/clinics/123/audit_trails?page=1&per_page=50&start_date=2024-01-01&event_key=patient.create" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."Success Response (200):
{
"success": true,
"message": "Audit trails fetched successfully",
"data": {
"audit_trails": [
{
"id": 12345,
"timestamp": "2024-01-15T10:30:00Z",
"created_at": "2024-01-15T10:30:00Z",
"key": "patient.create",
"event_status": "SUCCESS",
"description": "Patient record created successfully",
"ip_address": "192.168.1.100",
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36",
"device_type": "desktop",
"user_role": "doctor",
"user": {
"id": 789,
"name": "Dr. John Smith",
"type": "Doctor"
},
"patient": {
"id": 456,
"name": "Jane Doe"
},
"resource": {
"type": "Patient",
"id": 456
},
"parameters": {
"patient_age": 35,
"patient_gender": "female",
"registration_source": "web_portal"
}
}
],
"total_pages": 10,
"total_records": 500
}
}2. POST /clinics/:clinic_id/audit_trails/export
Request an audit trail export in CSV format.
URL: /clinics/{clinic_id}/audit_trails/export
Method: POST
Authentication: Required - Clinic authorization
Path Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| clinic_id | integer | Yes | Unique clinic identifier |
Request Body:
| Parameter | Type | Required | Description |
|---|---|---|---|
| start_date | string | No | Export start date (YYYY-MM-DD) |
| end_date | string | No | Export end date (YYYY-MM-DD) |
| event_key | string | No | Filter by specific event type |
Validation Rules:
- Maximum date range: 90 days
- If only start_date provided, exports single day
- If no dates provided, exports all available data
Example Request:
curl -X POST \
"https://api.kulcare.com/clinics/123/audit_trails/export" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
-d '{
"start_date": "2024-01-01",
"end_date": "2024-01-31",
"event_key": "patient.create"
}'Success Response (200):
{
"success": true,
"message": "Audit trail export enqueued",
"data": {
"export_id": 456,
"estimated_completion": "2024-01-15T10:35:00Z"
}
}Export Process:
- Request creates an export job in the background
- User receives email notification when export is ready
- Export file is available for 7 days
- File is automatically deleted after expiration
3. GET /clinics/:clinic_id/patients/:patient_id/audit_trails
Retrieve audit trails specific to a patient.
URL: /clinics/{clinic_id}/patients/{patient_id}/audit_trails
Method: GET
Authentication: Required - Clinic authorization
Path Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| clinic_id | integer | Yes | Unique clinic identifier |
| patient_id | integer | Yes | Unique patient identifier |
Query Parameters: Same as general audit trails endpoint, except patient filtering is automatic.
Example Request:
curl -X GET \
"https://api.kulcare.com/clinics/123/patients/456/audit_trails?page=1&per_page=50" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."Response Format: Same as general audit trails endpoint, but all entries are filtered to the specified patient.
Admin-Level Endpoints
1. GET /admin/audit_trails
Admin access to audit trails across all clinics with advanced filtering.
URL: /admin/audit_trails
Method: GET
Authentication: Required - Admin role
Query Parameters:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| page | integer | No | 1 | Page number for pagination |
| per_page | integer | No | 50 | Records per page (max: 200) |
| start_date | string | No | 30 days ago | Filter start date (YYYY-MM-DD) |
| end_date | string | No | today | Filter end date (YYYY-MM-DD) |
| clinic_id | integer | No | - | Filter by single clinic |
| clinic_ids | array | No | - | Filter by multiple clinics |
| user_id | integer | No | - | Filter by specific user |
| user_type | string | No | - | Filter by user type |
| event_key | string/array | No | - | Filter by event type(s) |
| status | string | No | - | Filter by status |
| patient_id | integer | No | - | Filter by patient |
| ip_address | string | No | - | Filter by IP (supports wildcards) |
| resource_type | string | No | - | Filter by resource type |
| sort_by | string | No | created_at | Sort column |
| sort_direction | string | No | desc | Sort direction (asc/desc) |
| include_summary | boolean | No | false | Include summary statistics |
User Type Options:
owner- Clinic ownersconsultant- Consultant doctorsstaff- Staff membersadmin- System administrators
Resource Type Options:
appointment- Appointment recordscareplan- Care plan recordspatient- Patient recordsuser- User recordsclinic- Clinic records
Sort By Options:
created_at- Date/time of eventevent_type- Event typeuser- User who performed actionstatus- Event status
Example Request:
curl -X GET \
"https://api.kulcare.com/admin/audit_trails?page=1&per_page=100&user_type=owner&status=failure&include_summary=true" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."Success Response (200):
{
"success": true,
"message": "Admin audit trails fetched successfully",
"data": {
"audit_trails": [
{
"id": 12345,
"timestamp": "2024-01-15T10:30:00Z",
"key": "auth.failed_login",
"event_status": "FAILURE",
"description": "Failed login attempt",
"ip_address": "192.168.1.100",
"user_agent": "Mozilla/5.0...",
"device_type": "desktop",
"user_role": "owner",
"user": {
"id": 789,
"name": "Dr. John Smith",
"type": "User"
},
"parameters": {
"error_code": "INVALID_CREDENTIALS",
"attempt_count": 3
}
}
],
"total_pages": 25,
"total_records": 2500,
"current_page": 1,
"per_page": 100,
"summary": {
"total_records": 2500,
"event_breakdown": {
"auth.login": 1200,
"auth.failed_login": 85,
"patient.create": 450,
"appointment.book": 765
},
"status_breakdown": {
"SUCCESS": 2350,
"FAILURE": 125,
"UNAUTHORIZED": 25
},
"user_type_breakdown": {
"owner": 800,
"consultant": 1200,
"staff": 450,
"admin": 50
},
"clinic_breakdown": {
"City Medical Center": 400,
"Downtown Clinic": 350,
"Suburban Health": 275
},
"daily_activity": {
"2024-01-14": 450,
"2024-01-15": 520,
"2024-01-16": 480
},
"top_ip_addresses": {
"192.168.1.100": 45,
"10.0.0.15": 32,
"172.16.0.5": 28
}
}
}
}2. GET /admin/audit_trails/summary
Get summary statistics for admin dashboard.
URL: /admin/audit_trails/summary
Method: GET
Authentication: Required - Admin role
Query Parameters:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| start_date | string | No | 30 days ago | Summary start date |
| end_date | string | No | today | Summary end date |
| clinic_id | integer | No | - | Filter by clinic |
| user_type | string | No | - | Filter by user type |
Example Request:
curl -X GET \
"https://api.kulcare.com/admin/audit_trails/summary?start_date=2024-01-01&end_date=2024-01-31" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."Success Response (200):
{
"success": true,
"message": "Audit trail summary fetched successfully",
"data": {
"total_records": 15750,
"date_range": {
"start_date": "2024-01-01",
"end_date": "2024-01-31"
},
"event_breakdown": {
"auth.login": 3500,
"patient.create": 2200,
"appointment.book": 4500,
"careplan.send": 1800,
"auth.failed_login": 250
},
"status_breakdown": {
"SUCCESS": 14800,
"FAILURE": 750,
"UNAUTHORIZED": 200
},
"user_type_breakdown": {
"owner": 4200,
"consultant": 7800,
"staff": 3200,
"admin": 550
},
"top_clinics": {
"City Medical Center": 2800,
"Downtown Clinic": 2400,
"Suburban Health": 2100,
"Metro Healthcare": 1900,
"Community Clinic": 1650
},
"top_ip_addresses": {
"192.168.1.100": 450,
"10.0.0.15": 380,
"172.16.0.5": 320,
"192.168.2.50": 285,
"10.0.1.25": 240
},
"daily_activity": {
"2024-01-01": 485,
"2024-01-02": 520,
"2024-01-03": 495,
"2024-01-04": 510,
"2024-01-05": 475
}
}
}Response Formats
Standard Response Structure
All API responses follow a consistent structure:
{
"success": boolean,
"message": string,
"data": object
}Audit Trail Entry Structure
{
"id": integer,
"timestamp": "ISO 8601 string",
"created_at": "ISO 8601 string",
"key": "string (event type)",
"event_status": "SUCCESS|FAILURE|UNAUTHORIZED",
"description": "string",
"ip_address": "string",
"user_agent": "string",
"device_type": "mobile|tablet|desktop",
"user_role": "string",
"user": {
"id": integer,
"name": "string",
"type": "string"
},
"patient": {
"id": integer,
"name": "string"
} | null,
"resource": {
"type": "string",
"id": integer
} | null,
"parameters": object
}Pagination Structure
{
"audit_trails": [...],
"total_pages": integer,
"total_records": integer,
"current_page": integer,
"per_page": integer
}Error Handling
Error Response Format
{
"success": false,
"message": "Error description",
"errors": {
"field_name": ["Error message"]
}
}HTTP Status Codes
| Code | Description | Common Causes |
|---|---|---|
| 200 | Success | Request completed successfully |
| 400 | Bad Request | Invalid parameters or request format |
| 401 | Unauthorized | Missing or invalid authentication token |
| 403 | Forbidden | User lacks permission for requested resource |
| 404 | Not Found | Clinic or resource doesn't exist |
| 422 | Unprocessable Entity | Validation errors in request data |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Internal Server Error | Server-side error occurred |
Common Error Examples
Invalid Date Format (422):
{
"success": false,
"message": "Validation failed",
"errors": {
"start_date": ["invalid date format"]
}
}Date Range Too Large (422):
{
"success": false,
"message": "Validation failed",
"errors": {
"date_range": ["export limited to 90 days"]
}
}Unauthorized Clinic Access (403):
{
"success": false,
"message": "You do not have permission to access this clinic's audit trails"
}Invalid Authentication (401):
{
"success": false,
"message": "Authentication token is invalid or expired"
}Rate Limiting
Limits:
- Standard Users: 100 requests per minute
- Admin Users: 500 requests per minute
- Export Requests: 5 exports per hour per user
Headers:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1642680000Rate Limit Exceeded Response (429):
{
"success": false,
"message": "Rate limit exceeded. Please try again later."
}Integration Examples
Basic Integration Pattern
// Basic audit trail fetch
const fetchAuditTrails = async (clinicId, filters = {}) => {
const params = new URLSearchParams(filters);
const response = await fetch(
`${API_BASE_URL}/clinics/${clinicId}/audit_trails?${params}`,
{
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
}
}
);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
return response.json();
};Export Request Pattern
// Request audit trail export
const exportAuditTrails = async (clinicId, exportParams) => {
const response = await fetch(
`${API_BASE_URL}/clinics/${clinicId}/audit_trails/export`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(exportParams)
}
);
if (!response.ok) {
const error = await response.json();
throw new Error(error.message || 'Export request failed');
}
return response.json();
};Error Handling Pattern
// Comprehensive error handling
const handleApiError = (error, response) => {
if (response?.status === 401) {
// Redirect to login
window.location.href = '/login';
return;
}
if (response?.status === 403) {
// Show permission denied message
showError('You do not have permission to access this resource');
return;
}
if (response?.status === 422) {
// Handle validation errors
const errors = error.errors || {};
Object.keys(errors).forEach(field => {
showFieldError(field, errors[field].join(', '));
});
return;
}
// General error handling
showError(error.message || 'An unexpected error occurred');
};Pagination Pattern
// Handle pagination
const loadAuditTrailPage = async (clinicId, page, filters) => {
try {
const response = await fetchAuditTrails(clinicId, {
...filters,
page,
per_page: 50
});
return {
entries: response.data.audit_trails,
pagination: {
currentPage: page,
totalPages: response.data.total_pages,
totalRecords: response.data.total_records
}
};
} catch (error) {
console.error('Failed to load audit trails:', error);
throw error;
}
};Filtering Pattern
// Apply filters with debouncing
const applyFilters = debounce(async (clinicId, filters) => {
// Clean up empty filter values
const cleanFilters = Object.fromEntries(
Object.entries(filters).filter(([_, value]) =>
value !== null && value !== undefined && value !== ''
)
);
try {
const response = await fetchAuditTrails(clinicId, {
...cleanFilters,
page: 1 // Reset to first page when filtering
});
return response.data;
} catch (error) {
handleApiError(error);
throw error;
}
}, 300);Admin Integration Pattern
// Admin audit trail fetch with summary
const fetchAdminAuditTrails = async (filters = {}) => {
const params = new URLSearchParams({
...filters,
include_summary: 'true'
});
const response = await fetch(
`${API_BASE_URL}/admin/audit_trails?${params}`,
{
headers: {
'Authorization': `Bearer ${adminToken}`,
'Content-Type': 'application/json'
}
}
);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
return response.json();
};Best Practices
Performance Optimization
- Use Pagination: Always implement pagination for large datasets
- Apply Filters: Use date ranges and event filters to reduce data volume
- Cache Responses: Cache frequently accessed data with appropriate TTL
- Batch Requests: Avoid making multiple rapid requests
Security Considerations
- Token Management: Implement token refresh mechanisms
- Permission Validation: Always validate user permissions before API calls
- Input Sanitization: Sanitize all user inputs before sending to API
- Error Logging: Log errors for monitoring but don't expose sensitive data
Integration Guidelines
- Error Handling: Implement comprehensive error handling for all scenarios
- Loading States: Show appropriate loading indicators during API calls
- Rate Limiting: Respect rate limits and implement backoff strategies
- Data Validation: Validate data on client side before API submission
Related Documentation
- Audit Trail Technical Documentation - Complete system architecture
- Authentication System - Authentication details
- API Error Codes - Complete error reference
Last updated: January 2024