Kulcare Docs
DeveloperCare plans

Audit API Reference

Base URL: /audit Authentication: Bearer Token Required Content-Type: application/json

This document describes the Audit domain API endpoints for tracking user activities, PHI access, LLM calls, document changes, and consent management.


Table of Contents


Activity Logs

General user activity audit trail for tracking all user actions across the platform.

List Activity Logs

Retrieve a paginated list of activity logs with optional filtering.

Endpoint: GET /audit/activity_logs

Query Parameters

ParameterTypeRequiredDescription
start_datestringNoFilter by start date (ISO 8601 format: YYYY-MM-DD)
end_datestringNoFilter by end date (ISO 8601 format: YYYY-MM-DD)
include_filtersbooleanNoWhen true, the response carries meta.filters (below). Opt-in, so a client that never renders the dropdowns does not pay for them.
user_idUUID or systemNoFilter by user ID. system selects rows with no actor — the renewal sweep, webhooks — which the UI renders as "Automatic".
activity_actionstringNoFilter by action type. Values: login, logout, create, read, update, delete, export, print, share, bulk_action
resource_typestringNoFilter by resource type (e.g., Clinical::Patient, Clinical::Encounter)
facility_idUUIDNoFilter by facility ID
searchstringNoSearch in description, resource_name, and user_email
pageintegerNoPage number (default: 1)
per_pageintegerNoItems per page (default: 50, max: 200)

Request Example

GET /audit/activity_logs?start_date=2024-01-01&end_date=2024-12-31&activity_action=create&page=1&per_page=20

Response

{
  "data": [
    {
      "id": "01950001-0000-7000-8000-000000000002",
      "action": "create",
      "resource_type": "Clinical::Patient",
      "resource_id": "01900008-0000-7000-8000-000000000001",
      "resource_name": "Rajesh Kumar",
      "description": "Created new patient record: Rajesh Kumar",
      "user": {
        "id": "01900003-0000-7000-8000-000000000001",
        "name": "Dr. Raj Kumar",
        "email": "dr.raj@cityhospital.com"
      },
      "created_at": "2026-02-18T06:44:51Z",
      "updated_at": null
    }
  ],
  "meta": {
    "pagination": {
      "current_page": 1,
      "per_page": 20,
      "total_entries": 45,
      "total_pages": 3
    },
    "filters": {
      "resource_types": ["Billing::Subscription", "Identity::UserMembership", "User"],
      "actions": ["create", "login", "update"],
      "users": [
        { "id": "9f1c…", "name": "Ada Lovelace" },
        { "id": "3b7e…", "name": "Grace Hopper (suspended)" },
        { "id": "system", "name": "Automatic" }
      ]
    }
  }
}

Export Activity Logs

Export activity logs as CSV or JSON, under the same filters as the list: what is on screen is what is exported.

Endpoint: POST /audit/activity_logs/export

Request Body

{
  "start_date": "2024-01-01",
  "end_date": "2024-12-31",
  "user_id": "system",
  "activity_action": "update",
  "resource_type": "Billing::Subscription",
  "facility_id": "01900002-0000-7000-8000-000000000001",
  "format": "csv"
}

Body Parameters

ParameterTypeRequiredDescription
start_datestringNoFrom this date (ISO 8601); either bound may be given alone
end_datestringNoUp to this date (ISO 8601)
user_idUUID or systemNoAs on the list: a user's rows, or system for actor-less rows
activity_actionstringNoFilter by action type; a value that is not an action matches nothing
resource_typestringNoFilter by resource type
facility_idUUIDNoFilter by facility ID
episode_idUUIDNoAs on the list
searchstringNoAs on the list
tenant_idUUIDNoPlatform admin only: the tenant to export; unknown is 404
formatcsv or jsonNoDefault csv

Response

The file itself, as an attachment (text/csv or application/json). The JSON form is { "data": [rows], "meta": { "exported_at", "count", "total", "truncated" } }, and the header X-Export-Truncated: true is set when the export hit its row cap.

Status Code: 200 OK


Filter options (meta.filters)

Sent only when the request carries include_filters=1. The values the audit trail's filters may offer, computed server-side for the tenant. The viewer used to derive these from the page it had just rendered — one page — so a filter could only reach a value already on screen (#2165).

KeySource
resource_types, actionsDistinct values over the tenant's rows, minus the commission resources this endpoint never returns.
usersEveryone who has acted in the tenant's trail — the same people the rows name — with a suspended member labelled; plus { "id": "system", "name": "Automatic" } when there are actor-less rows.

Not narrowed by the request's own filters, so picking one Resource does not collapse the list to it. Cached per tenant for sixty seconds.

Absent — not empty — when there is no tenant scope (a platform admin's cross-tenant view) or the options could not be computed. A client should then fall back to whatever it can derive from the page.

PHI Access Logs

PHI (Protected Health Information) access audit trail for HIPAA/DPDP compliance. Restricted to compliance officers and admins.

List PHI Access Logs

Retrieve a paginated list of PHI access logs with optional filtering.

Endpoint: GET /audit/phi_access_logs

Query Parameters

ParameterTypeRequiredDescription
start_datestringNoFilter by start date (ISO 8601 format)
end_datestringNoFilter by end date (ISO 8601 format)
user_idUUIDNoFilter by user ID
patient_idUUIDNoFilter by patient ID
access_typestringNoFilter by access type. Values: view, download, print, share
access_reasonstringNoFilter by access reason. Values: treatment, payment, operations, emergency, research, legal
emergency_accessbooleanNoFilter emergency access only (true/false)
facility_idUUIDNoFilter by facility ID
pageintegerNoPage number (default: 1)
per_pageintegerNoItems per page (default: 50, max: 200)

Request Example

GET /audit/phi_access_logs?patient_id=01900008-0000-7000-8000-000000000001&start_date=2024-01-01&end_date=2024-12-31

Response

{
  "data": [
    {
      "id": "01950002-0000-7000-8000-000000000001",
      "access_type": "view",
      "access_reason": "treatment",
      "user_role": "doctor",
      "emergency_access": false,
      "user": {
        "id": "01900003-0000-7000-8000-000000000001",
        "name": "Dr. Raj Kumar",
        "email": "dr.raj@cityhospital.com"
      },
      "patient": {
        "id": "01900008-0000-7000-8000-000000000001",
        "name": "Rajesh Kumar"
      },
      "resource": {
        "type": "Clinical::Patient",
        "id": "01900008-0000-7000-8000-000000000001"
      },
      "created_at": "2026-02-18T06:44:50Z",
      "updated_at": null
    },
    {
      "id": "01950002-0000-7000-8000-000000000004",
      "access_type": "view",
      "access_reason": "emergency",
      "user_role": "doctor",
      "emergency_access": true,
      "user": {
        "id": "01900003-0000-7000-8000-000000000001",
        "name": "Dr. Raj Kumar",
        "email": "dr.raj@cityhospital.com"
      },
      "patient": {
        "id": "01900008-0000-7000-8000-000000000001",
        "name": "Rajesh Kumar"
      },
      "resource": {
        "type": "Clinical::Patient",
        "id": "01900008-0000-7000-8000-000000000001"
      },
      "created_at": "2026-02-18T06:44:52Z",
      "updated_at": null
    }
  ],
  "meta": {
    "pagination": {
      "current_page": 1,
      "per_page": 50,
      "total_entries": 5,
      "total_pages": 1
    }
  }
}

Get PHI Access Summary

Get aggregated statistics for PHI access for compliance dashboard.

Endpoint: GET /audit/phi_access_logs/summary

Query Parameters

ParameterTypeRequiredDescription
start_datestringNoFilter by start date (ISO 8601 format)
end_datestringNoFilter by end date (ISO 8601 format)
facility_idUUIDNoFilter by facility ID

Request Example

GET /audit/phi_access_logs/summary?start_date=2024-01-01&end_date=2024-12-31

Response

{
  "data": {
    "total_accesses": 1250,
    "by_access_type": {
      "view": 1000,
      "download": 150,
      "print": 75,
      "share": 25
    },
    "by_access_reason": {
      "treatment": 900,
      "payment": 150,
      "operations": 100,
      "emergency": 50,
      "research": 25,
      "legal": 25
    },
    "emergency_access_count": 50,
    "emergency_access_rate": 4.0,
    "unique_patients_accessed": 350,
    "unique_users_accessing": 25
  }
}

LLM Call Logs

Audit trail for all LLM API calls. No PHI is stored - only metadata, tokens, and performance metrics.

List LLM Call Logs

Retrieve a paginated list of LLM call logs with optional filtering.

Endpoint: GET /audit/llm_call_logs

Query Parameters

ParameterTypeRequiredDescription
start_datestringNoFilter by start date (ISO 8601 format)
end_datestringNoFilter by end date (ISO 8601 format)
call_typestringNoFilter by call type. Values: transcription, suggestion, summary, extraction, embedding, moderation
providerstringNoFilter by provider. Values: openai, anthropic, google, azure_openai, aws_bedrock
statusstringNoFilter by status. Values: success, error, timeout, rate_limited
facility_idUUIDNoFilter by facility ID
pageintegerNoPage number (default: 1)
per_pageintegerNoItems per page (default: 50, max: 200)

Request Example

GET /audit/llm_call_logs?provider=openai&status=success&start_date=2024-01-01

Response

{
  "data": [
    {
      "id": "01950003-0000-7000-8000-000000000001",
      "call_type": "transcription",
      "provider": "openai",
      "model": "gpt-4o-transcribe",
      "status": "success",
      "input_tokens": 1500,
      "output_tokens": 800,
      "total_tokens": 2300,
      "latency_ms": 2500,
      "estimated_cost_usd": "0.023",
      "is_successful": true,
      "created_at": "2026-02-18T06:44:48Z",
      "updated_at": null
    },
    {
      "id": "01950003-0000-7000-8000-000000000003",
      "call_type": "suggestion",
      "provider": "anthropic",
      "model": "claude-3-sonnet",
      "status": "success",
      "input_tokens": 3500,
      "output_tokens": 600,
      "total_tokens": 4100,
      "latency_ms": 4200,
      "estimated_cost_usd": "0.041",
      "is_successful": true,
      "created_at": "2026-02-18T06:44:49Z",
      "updated_at": null
    }
  ],
  "meta": {
    "pagination": {
      "current_page": 1,
      "per_page": 50,
      "total_entries": 5,
      "total_pages": 1
    }
  }
}

Get LLM Analytics

Get aggregated LLM usage analytics and statistics.

Endpoint: GET /audit/llm_call_logs/analytics

Query Parameters

ParameterTypeRequiredDescription
start_datestringNoFilter by start date (ISO 8601 format)
end_datestringNoFilter by end date (ISO 8601 format)
facility_idUUIDNoFilter by facility ID

Request Example

GET /audit/llm_call_logs/analytics?start_date=2024-01-01&end_date=2024-12-31

Response

{
  "data": {
    "statistics": {
      "total_calls": 5000,
      "success_rate": 95.5,
      "error_rate": 4.5,
      "total_tokens": 2500000,
      "total_cost_usd": "125.50",
      "average_latency_ms": 2800
    },
    "by_provider": {
      "Openai": 3500,
      "Anthropic": 1200,
      "Google": 300
    },
    "by_call_type": {
      "Transcription": 2500,
      "Suggestion": 1500,
      "Summary": 800,
      "Extraction": 200
    },
    "by_status": {
      "successful": 4775,
      "failed": 225
    },
    "daily_usage": [
      {
        "date": "2024-01-01",
        "calls": 150,
        "tokens": 75000,
        "cost_usd": 3.75
      },
      {
        "date": "2024-01-02",
        "calls": 165,
        "tokens": 82500,
        "cost_usd": 4.125
      }
    ]
  }
}

Document Audit Logs

Clinical document change tracking for medico-legal compliance.

List Document Audit Logs

Retrieve a paginated list of document audit logs with optional filtering.

Endpoint: GET /audit/document_audit_logs

Query Parameters

ParameterTypeRequiredDescription
start_datestringNoFilter by start date (ISO 8601 format)
end_datestringNoFilter by end date (ISO 8601 format)
document_typestringNoFilter by document type (e.g., Clinical::Encounter, Clinical::MedicationRequest)
document_idUUIDNoFilter by document ID (requires document_type)
actor_idUUIDNoFilter by actor (practitioner) ID
document_actionstringNoFilter by action. Values: created, updated, amended, signed, voided, printed
is_legal_recordbooleanNoFilter legal records only (true/false)
pageintegerNoPage number (default: 1)
per_pageintegerNoItems per page (default: 50, max: 200)

Request Example

GET /audit/document_audit_logs?document_type=Clinical::Encounter&document_action=signed&is_legal_record=true

Response

{
  "data": [
    {
      "id": "01950004-0000-7000-8000-000000000002",
      "document_type": "Clinical::Encounter",
      "document_id": "01900009-0000-7000-8000-000000000001",
      "action": "signed",
      "change_summary": "Signed and finalized encounter note",
      "is_legal_record": true,
      "document_name": "Encounter",
      "user": {
        "id": "01900004-0000-7000-8000-000000000001",
        "name": "Dr. Raj Kumar",
        "role": "physician"
      },
      "created_at": "2026-02-18T06:44:53Z",
      "updated_at": null
    }
  ],
  "meta": {
    "pagination": {
      "current_page": 1,
      "per_page": 50,
      "total_entries": 5,
      "total_pages": 1
    }
  }
}

Get Document Audit Log

Retrieve a specific document audit log entry with full details.

Endpoint: GET /audit/document_audit_logs/:id

Path Parameters

ParameterTypeRequiredDescription
idUUIDYesDocument audit log ID

Request Example

GET /audit/document_audit_logs/01950004-0000-7000-8000-000000000002

Response

{
  "data": {
    "id": "01950004-0000-7000-8000-000000000002",
    "document_type": "Clinical::Encounter",
    "document_id": "01900009-0000-7000-8000-000000000001",
    "action": "signed",
    "change_summary": "Signed and finalized encounter note",
    "is_legal_record": true,
    "document_name": "Encounter",
    "actor_role": "physician",
    "previous_version_id": "01950004-0000-7000-8000-000000000001",
    "change_details": {
      "status": "finished",
      "signed_at": "2026-02-18T07:12:42Z"
    },
    "reason": null,
    "attestation": "I attest that this encounter note is accurate and complete to the best of my knowledge.",
    "has_signature": true,
    "signed": true,
    "signature_data": {
      "algorithm": "RSA-SHA256",
      "signed_at": "2026-02-18T07:12:42Z"
    },
    "user": {
      "id": "01900004-0000-7000-8000-000000000001",
      "name": "Dr. Raj Kumar",
      "role": "physician"
    },
    "created_at": "2026-02-18T06:44:53Z",
    "updated_at": null
  }
}

Patient consent tracking for GDPR/DPDP compliance.

Retrieve a paginated list of consent audit logs with optional filtering.

Endpoint: GET /audit/consent_audit_logs

Query Parameters

ParameterTypeRequiredDescription
start_datestringNoFilter by start date (ISO 8601 format)
end_datestringNoFilter by end date (ISO 8601 format)
patient_idUUIDNoFilter by patient ID
consent_typestringNoFilter by consent type. Values: treatment, data_sharing, telemedicine, research, marketing
consent_actionstringNoFilter by action. Values: granted, revoked, updated
collection_methodstringNoFilter by collection method. Values: written, electronic, verbal
active_onlybooleanNoShow only active consents (true/false)
pageintegerNoPage number (default: 1)
per_pageintegerNoItems per page (default: 50, max: 200)

Request Example

GET /audit/consent_audit_logs?patient_id=01900008-0000-7000-8000-000000000001&active_only=true

Response

{
  "data": [
    {
      "id": "01950005-0000-7000-8000-000000000001",
      "consent_type": "treatment",
      "action": "granted",
      "collection_method": "electronic",
      "status": "active",
      "valid_from": "2025-01-19T00:00:00Z",
      "valid_until": null,
      "patient": {
        "id": "01900008-0000-7000-8000-000000000001",
        "name": "Rajesh Kumar"
      },
      "created_at": "2026-02-18T06:44:54Z",
      "updated_at": null
    },
    {
      "id": "01950005-0000-7000-8000-000000000003",
      "consent_type": "telemedicine",
      "action": "granted",
      "collection_method": "electronic",
      "status": "active",
      "valid_from": "2026-02-11T00:00:00Z",
      "valid_until": "2027-02-18T00:00:00Z",
      "patient": {
        "id": "01900008-0000-7000-8000-000000001",
        "name": "Rajesh Kumar"
      },
      "created_at": "2026-02-18T06:44:54Z",
      "updated_at": null
    }
  ],
  "meta": {
    "pagination": {
      "current_page": 1,
      "per_page": 50,
      "total_entries": 5,
      "total_pages": 1
    }
  }
}

Retrieve a specific consent audit log entry with full details.

Endpoint: GET /audit/consent_audit_logs/:id

Path Parameters

ParameterTypeRequiredDescription
idUUIDYesConsent audit log ID

Request Example

GET /audit/consent_audit_logs/01950005-0000-7000-8000-000000000003

Response

{
  "data": {
    "id": "01950005-0000-7000-8000-000000000003",
    "consent_type": "telemedicine",
    "action": "granted",
    "collection_method": "electronic",
    "status": "active",
    "valid_from": "2026-02-11T00:00:00Z",
    "valid_until": "2027-02-18T00:00:00Z",
    "scope": {
      "categories": ["video_consultation", "remote_monitoring", "chat_consultation"],
      "purposes": ["telemedicine_consultation", "follow_up_care"]
    },
    "granted_to": null,
    "scope_categories": ["video_consultation", "remote_monitoring", "chat_consultation"],
    "granted_to_entities": [],
    "ip_address": "192.168.1.100",
    "validity_period": {
      "from": "2026-02-11",
      "until": "2027-02-18",
      "duration_days": 365
    },
    "patient": {
      "id": "01900008-0000-7000-8000-000000000001",
      "name": "Rajesh Kumar"
    },
    "witness": null,
    "created_at": "2026-02-18T06:44:54Z",
    "updated_at": null
  }
}

Msg Logs

SMS and WhatsApp message delivery audit logs for tracking communication delivery status.

List Msg Logs

Retrieve a paginated list of message logs with optional filtering.

Endpoint: GET /audit/msg_logs

Query Parameters

ParameterTypeRequiredDescription
start_datestringNoFilter by start date (ISO 8601 format: YYYY-MM-DD)
end_datestringNoFilter by end date (ISO 8601 format: YYYY-MM-DD)
msg_typestringNoFilter by message type. Values: sms, whatsapp
msg_statusstringNoFilter by status. Values: sent, delivered, failed, rejected, pending
phone_numberstringNoFilter by phone number
facility_idUUIDNoFilter by facility ID
pageintegerNoPage number (default: 1)
per_pageintegerNoItems per page (default: 50, max: 200)

Request Example

GET /audit/msg_logs?msg_type=sms&msg_status=delivered&start_date=2024-01-01&end_date=2024-12-31

Response

{
  "data": [
    {
      "id": "01950006-0000-7000-8000-000000000001",
      "msg_type": "sms",
      "phone_number": "+919876543210",
      "msg_status": "delmsg_text": "Your appointment is confirmed for tomorrow at ivered",
      "10 AM.",
      "is_delivered": true,
      "is_failed": false,
      "provider": "Msg91",
      "created_at": "2026-02-24T09:54:37Z"
    },
    {
      "id": "01950006-0000-7000-8000-000000000002",
      "msg_type": "whatsapp",
      "phone_number": "+919876543211",
      "msg_status": "delivered",
      "msg_text": "Your appointment is confirmed for tomorrow at 10 AM. Reply CONFIRM to confirm.",
      "is_delivered": true,
      "is_failed": false,
      "provider": "WATI",
      "created_at": "2026-02-24T08:54:37Z"
    }
  ],
  "meta": {
    "pagination": {
      "current_page": 1,
      "per_page": 50,
      "total_entries": 6,
      "total_pages": 1
    }
  }
}

Get Msg Log

Retrieve a specific message log entry with full details.

Endpoint: GET /audit/msg_logs/:id

Path Parameters

ParameterTypeRequiredDescription
idUUIDYesMessage log ID

Request Example

GET /audit/msg_logs/01950006-0000-7000-8000-000000000001

Response

{
  "data": {
    "id": "01950006-0000-7000-8000-000000000001",
    "msg_type": "sms",
    "phone_number": "+919876543210",
    "msg_text": "Your appointment is confirmed for tomorrow at 10 AM.",
    "msg_status": "delivered",
    "is_delivered": true,
    "is_failed": false,
    "provider": "Msg91",
    "failure_reason": null,
    "sms_request_id": "REQ001",
    "unique_identifier": "abc123-def456-ghi789",
    "wati_message_id": null,
    "facility": {
      "id": "01900002-0000-7000-8000-000000000001",
      "name": "City Hospital Main"
    },
    "created_at": "2026-02-24T09:54:37Z"
  }
}

Get Msg Logs Summary

Get aggregated message statistics for the dashboard.

Endpoint: GET /audit/msg_logs/summary

Query Parameters

ParameterTypeRequiredDescription
start_datestringNoFilter by start date (ISO 8601 format)
end_datestringNoFilter by end date (ISO 8601 format)
facility_idUUIDNoFilter by facility ID

Request Example

GET /audit/msg_logs/summary?start_date=2024-01-01&end_date=2024-12-31

Response

{
  "data": {
    "total_messages": 150,
    "success_rate": 85.5,
    "sms_count": 100,
    "whatsapp_count": 50,
    "delivered_count": 128,
    "failed_count": 22,
    "breakdown_by_type": {
      "sms": {
        "total_messages": 100,
        "success_rate": 88.0,
        "sms_count": 100,
        "whatsapp_count": 0,
        "delivered_count": 88,
        "failed_count": 12
      },
      "whatsapp": {
        "total_messages": 50,
        "success_rate": 80.0,
        "sms_count": 0,
        "whatsapp_count": 50,
        "delivered_count": 40,
        "failed_count": 10
      }
    },
    "breakdown_by_status": {
      "sent": 45,
      "delivered": 128,
      "failed": 18,
      "rejected": 4,
      "pending": 5
    }
  }
}

Email Logs

Email delivery audit logs from SendGrid and AWS SES for tracking email engagement.

List Email Logs

Retrieve a paginated list of email logs with optional filtering.

Endpoint: GET /audit/email_logs

Query Parameters

ParameterTypeRequiredDescription
start_datestringNoFilter by start date (ISO 8601 format: YYYY-MM-DD)
end_datestringNoFilter by end date (ISO 8601 format: YYYY-MM-DD)
eventstringNoFilter by event. Values: send, sent, delivered, open, click, bounce, dropped, deferred, spamreport
emailstringNoFilter by recipient email
categorystringNoFilter by category. Values: appointment_reminder, prescription_ready, test_results, payment_confirmation, follow_up_reminder, marketing, newsletter
facility_idUUIDNoFilter by facility ID
consolidatebooleanNoGroup by webhook_id for accurate status (default: false)
pageintegerNoPage number (default: 1)
per_pageintegerNoItems per page (default: 50, max: 200)

Request Example

GET /audit/email_logs?event=delivered&category=appointment_reminder&start_date=2024-01-01

Response

{
  "data": [
    {
      "id": "01950007-0000-7000-8000-000000000001",
      "email": "patient1@example.com",
      "event": "delivered",
      "category": "appointment_reminder",
      "is_delivered": true,
      "is_failed": false,
      "provider": "SendGrid",
      "created_at": "2026-02-24T09:54:37Z",
      "ts": "2026-02-24T09:54:30Z"
    },
    {
      "id": "01950007-0000-7000-8000-000000000002",
      "email": "patient2@example.com",
      "event": "open",
      "category": "prescription_ready",
      "is_delivered": true,
      "is_failed": false,
      "provider": "SendGrid",
      "created_at": "2026-02-24T08:54:37Z",
      "ts": "2026-02-24T08:54:30Z"
    }
  ],
  "meta": {
    "pagination": {
      "current_page": 1,
      "per_page": 50,
      "total_entries": 6,
      "total_pages": 1
    }
  }
}

Get Email Log

Retrieve a specific email log entry with full details.

Endpoint: GET /audit/email_logs/:id

Path Parameters

ParameterTypeRequiredDescription
idUUIDYesEmail log ID

Request Example

GET /audit/email_logs/01950007-0000-7000-8000-000000000001

Response

{
  "data": {
    "id": "01950007-0000-7000-8000-000000000001",
    "email": "patient1@example.com",
    "event": "delivered",
    "category": "appointment_reminder",
    "is_delivered": true,
    "is_failed": false,
    "provider": "SendGrid",
    "error_message": null,
    "sendgrid_webhook_id": "sg-webhook-123-abc",
    "ses_email_webhook_id": null,
    "clinic_email_list_id": null,
    "clinic_email_campaign_id": null,
    "clinic_weekly_stats_id": null,
    "facility": {
      "id": "01900002-0000-7000-8000-000000000001",
      "name": "City Hospital Main"
    },
    "created_at": "2026-02-24T09:54:37Z",
    "ts": "2026-02-24T09:54:30Z"
  }
}

Get Email Logs Summary

Get aggregated email statistics for the dashboard.

Endpoint: GET /audit/email_logs/summary

Query Parameters

ParameterTypeRequiredDescription
start_datestringNoFilter by start date (ISO 8601 format)
end_datestringNoFilter by end date (ISO 8601 format)
facility_idUUIDNoFilter by facility ID

Request Example

GET /audit/email_logs/summary?start_date=2024-01-01&end_date=2024-12-31

Response

{
  "data": {
    "total_emails": 500,
    "delivery_rate": 92.5,
    "open_rate": 45.2,
    "click_rate": 12.8,
    "unique_recipients": 350,
    "sent_count": 462,
    "delivered_count": 427,
    "opened_count": 193,
    "clicked_count": 55,
    "failed_count": 35,
    "breakdown_by_event": {
      "send": 100,
      "sent": 362,
      "delivered": 427,
      "open": 193,
      "click": 55,
      "bounce": 25,
      "dropped": 8,
      "deferred": 2,
      "spamreport": 0
    },
    "breakdown_by_provider": {
      "sendgrid": 450,
      "ses": 50
    }
  }
}

Error Responses

All endpoints follow a consistent error response format:

Validation Error (422)

{
  "data": null,
  "error": {
    "code": "validation_failed",
    "message": "Start date must be before end date",
    "details": [
      {
        "field": "start_date",
        "message": "Start date must be before end date"
      }
    ]
  },
  "meta": {
    "request_id": "550e8400-e29b-41d4-a716-446655440000"
  }
}

Not Found (404)

{
  "data": null,
  "error": {
    "code": "not_found",
    "message": "Document audit log not found",
    "details": []
  },
  "meta": {
    "request_id": "550e8400-e29b-41d4-a716-446655440000"
  }
}

Unauthorized (401)

{
  "data": null,
  "error": {
    "code": "unauthorized",
    "message": "Authentication required",
    "details": []
  },
  "meta": {
    "request_id": "550e8400-e29b-41d4-a716-446655440000"
  }
}

Notes

  1. Authentication: All audit endpoints require a valid Bearer token in the Authorization header.

  2. Tenant Isolation: All data is scoped to the authenticated user's tenant via Row Level Security (RLS).

  3. Pagination: Default page size is 50, maximum is 200.

  4. Date Filtering: All dates should be in ISO 8601 format (YYYY-MM-DD).

  5. Audit tables are append-only: The updated_at field will always be null for audit records.

  6. PHI Access Logs: Restricted to users with compliance officer or admin roles.

  7. Legal Records: Document audit logs marked as is_legal_record: true are signed and cannot be modified.

  8. Msg Logs: Tracks SMS and WhatsApp message delivery. Provider is automatically detected (Msg91 for SMS, WATI for WhatsApp).

  9. Email Logs: Tracks email delivery from SendGrid/SES. Use consolidate=true to group by webhook_id for accurate status tracking.

On this page