PatientPulse API v2.0
Base URL: api.patientpulse.in

API Reference

Full reference for the PatientPulse REST API (452 endpoints) and PulseVault Mobile API (88 endpoints). Base URL: https://api.patientpulse.in

REST / JSON Bearer Auth FHIR R4 OpenAPI 3.0

Authentication & Session

All requests require a Bearer token in the Authorization header, except auth endpoints themselves. OTP-based login is the primary patient flow.

POST /auth/patient/request-otp Request OTP to patient mobile number β–Ύ

Sends an OTP via SMS (Twilio) or WhatsApp to the patient's registered phone number. Rate-limited to prevent abuse.

Request Body

ParameterTypeRequiredDescription
phonestringrequiredE.164 format phone number, e.g. +919876543210
channelenumoptionalsms (default) or whatsapp

Response β€” 200 OK

JSON
{
  "status": "otp_sent",
  "expires_in": 300,
  "channel": "sms"
}
POST /auth/patient/verify-otp Verify OTP and return session tokens β–Ύ

Verifies the OTP and returns an access token (JWT) and a refresh token (HttpOnly cookie).

ParameterTypeRequiredDescription
phonestringrequiredSame phone used for request-otp
otpstringrequired6-digit OTP received

Response β€” 200 OK

JSON
{
  "access_token": "eyJhbGciOiJIUzI1NiIs...",
  "token_type": "bearer",
  "expires_in": 900,
  "user": {
    "id": "pat_01JFGH3K2MNPQ4RS5TUVWXYZ",
    "phone": "+919876543210",
    "role": "patient"
  }
}
POST /auth/google Google OAuth login β–Ύ

Exchange a Google ID token for a PatientPulse session. Suitable for web app login flows.

ParameterTypeRequiredDescription
id_tokenstringrequiredGoogle ID token from OAuth flow
GET /auth/me Get current authenticated user profile β–Ύ

Returns the full profile of the currently authenticated user including role, organization, and permissions.

πŸ” Authentication Required

Include Authorization: Bearer <token> header.

AI & Clinical Intelligence

PatientPulse ships a full AI suite β€” lab interpretation, ambient clinical scribe, demand forecasting, and staffing recommendations. AI endpoints require AI_ENABLED=true in your environment.

POST /ai/interpret-lab-report AI interpretation of uploaded lab report β–Ύ

Pass a lab report (PDF or image reference) and receive structured clinical interpretation β€” abnormal flags, trend markers, recommended actions.

ParameterTypeRequiredDescription
record_idstringrequiredID of uploaded health record
patient_idstringrequiredPatient to contextualize results against
include_historybooleanoptionalCompare against prior lab results (default: true)

Response β€” 200 OK

JSON
{
  "interpretation": {
    "summary": "HbA1c elevated at 7.8% β€” borderline diabetic range.",
    "abnormal_markers": [
      { "name": "HbA1c", "value": "7.8%", "flag": "HIGH" },
      { "name": "Triglycerides", "value": "210 mg/dL", "flag": "HIGH" }
    ],
    "recommendations": ["Repeat HbA1c in 3 months", "Dietary consult advised"],
    "confidence": 0.91
  }
}
POST /ai/ambient-scribe Generate clinical notes from consultation audio/text β–Ύ

Submit consultation transcript or audio reference; receive a structured SOAP note with chief complaint, history, assessment, and plan.

ParameterTypeRequiredDescription
transcriptstringrequired*Consultation transcript text
audio_urlstringoptionalURL to audio recording (*one of transcript or audio_url required)
appointment_idstringoptionalLink note to existing appointment
GET /forecast OPD/Emergency demand forecast β–Ύ

Returns ML-generated demand forecast (XGBoost + Prophet ensemble) for OPD and Emergency departments. Used for capacity planning and staffing optimization.

Query ParamTypeDescription
departmentenumopd, emergency, ipd
horizon_daysintegerForecast horizon (1–14 days)
org_idstringFilter by organization

FHIR R4 Interoperability

PatientPulse implements HL7 FHIR R4 for patient data export and interoperability. Use these endpoints to fetch FHIR-compliant bundles for any patient.

GET /interop/fhir/r4/patients/{patient_id} Export patient as FHIR R4 bundle β–Ύ

Returns a complete FHIR R4 Bundle containing Patient, Conditions, Medications, Observations, and Appointments resources.

Response β€” 200 OK

FHIR JSON
{
  "resourceType": "Bundle",
  "type": "collection",
  "entry": [
    {
      "resource": {
        "resourceType": "Patient",
        "id": "pat_01JFGH3K2MNPQ4RS5TUVWXYZ",
        "name": [{ "text": "Ramesh Kumar" }],
        "birthDate": "1985-04-15",
        "identifier": [{ "system": "https://abha.gov.in", "value": "12-3456-7890-1234" }]
      }
    }
  ]
}

ABDM / ABHA Integration

First-class ABDM (Ayushman Bharat Digital Mission) integration. Link ABHA IDs, push/pull PHR records, and sync with HFR/HPR registries.

GET /interop/abdm/identity-links/{link_request_id} Get ABHA identity link status β–Ύ

Poll the status of an ABHA identity linking request. Links are initiated via the mobile app and processed asynchronously by the ABDM connector.

POST /interop/abdm/phr-push Push PHR records to ABDM health locker β–Ύ

Triggered automatically on consult completion (Feature 7A). Can also be called manually to push specific records to a patient's ABHA-linked health locker.

✦ Auto-triggered on Consult Completion

Set ABDM_AUTO_PUSH_ON_CONSULT=true to enable automatic FHIR bundle push after each consultation.

Appointments

POST /appointments Book a new appointment β–Ύ
ParameterTypeRequiredDescription
patient_idstringrequiredPatient identifier
doctor_idstringrequiredAssigned doctor
slot_idstringrequiredAvailability slot from GET /availability/slots
visit_typeenumrequiredopd, telemedicine, followup
notesstringoptionalChief complaint or notes for doctor
GET /availability/slots List available appointment slots β–Ύ
Query ParamTypeDescription
doctor_idstringFilter by doctor
datedateTarget date (ISO 8601)
specialtystringFilter by medical specialty

Insurance & Claims

POST /insurance/claims File a new insurance claim β–Ύ

Submit a pre-authorization or claim to the payer via NHCX. Returns a correlation_id for status polling.

GET /insurance/nhcx/claim-status/{correlation_id} Poll NHCX claim status β–Ύ

Polls the National Health Claims Exchange for real-time claim status using the correlation ID returned at claim submission.

PulseVault Mobile API Node.js / Express

The PulseVault mobile backend provides 88 endpoints for the Android consumer app. Base URL: https://api.pulsevault.in/v1

POST /v1/auth/request-otp Request OTP (Vault) β–Ύ

Identical contract to PatientPulse auth. Can be proxied to canonical PatientPulse backend via NODE_AUTH_PROXY_ENABLED=true.

GET /v1/profiles/{profileId}/vault Get patient health record vault β–Ύ

Returns all health records for a profile, grouped by category (labs, prescriptions, imaging, discharge summaries).

Response β€” 200 OK

JSON
{
  "profile_id": "prof_abc123",
  "records": {
    "labs": [/* ... */],
    "prescriptions": [/* ... */],
    "imaging": [/* ... */]
  },
  "total_records": 47,
  "last_updated": "2025-11-14T10:30:00Z"
}
POST /v1/profiles/{profileId}/records/{recordId}/extraction-jobs Start AI marker extraction from a record β–Ύ

Queues an async AI job to extract structured health markers (diagnoses, medications, vitals) from a health record document.

452 total PatientPulse endpoints + 88 PulseVault endpoints. Download the full OpenAPI spec for complete reference.

Download OpenAPI 3.0 Spec β†’

Errors & Rate Limits

All error responses are JSON with an error key. The table below covers every non-2xx status your integration should handle.

HTTP Statuserror codeWhen it happensFix
401 invalid_api_key Key not found, revoked, or environment mismatch (sandbox key on production endpoint) Issue a new key in the Developer Portal
402 plan_required Your plan tier is below the minimum required for this endpoint (e.g. calling AI features on the free plan) Upgrade at developer-portal.html#plans
402 subscription_required Attempted to issue a production key with no active paid subscription Subscribe via Razorpay on the Developer Portal
429 quota_exceeded Monthly API call quota exhausted for your plan (free: 10K, growth: 500K) Upgrade plan or wait for the monthly reset
422 validation_error Request body fails schema validation Check the detail array for field-level messages
404 not_found Resource (patient, appointment, claim…) does not exist or belongs to a different org Verify the ID and your org_id
500 internal_error Unexpected server error Retry with exponential back-off; open a GitHub issue if persistent

Rate-Limit Headers

Every response from an API-key-authenticated request carries these headers:

HeaderValueNotes
X-RateLimit-Limit10000 / 500000 / unlimitedMonthly quota for your plan
X-RateLimit-Remaininginteger β‰₯ 0Calls left this calendar month
X-RateLimit-PeriodmonthlyResets on the 1st of each month

Example 429 Response

JSON
{
  "error": "quota_exceeded",
  "monthly_calls": 10001,
  "quota": 10000,
  "plan": "free",
  "reset": "first day of next calendar month",
  "upgrade_url": "https://patientpulse.in/developer-portal#plans"
}

Developer Keys API

Manage API keys programmatically. All routes require an org-admin JWT token in the Authorization: Bearer <jwt> header.

POST /developer/keys Issue a new sandbox or production API key β–Ύ
FieldTypeRequiredDescription
environmentenumoptionalsandbox (default) or production. Production requires an active paid subscription.
scopesstring[]optionalPermission scopes: read:patients, write:appointments, ai:interpret, interop:fhir, admin:org, etc.
labelstringoptionalHuman-readable label, max 120 chars
⚠ Plaintext shown once only

The full key is returned in the response and never stored. Store it securely immediately β€” you cannot retrieve it again.

GET /developer/keys List all keys for the authenticated org (no plaintext) β–Ύ
Query ParamTypeDescription
include_revokedboolDefault false. Set true to include revoked keys in the response.
DELETE /developer/keys/{key_id} Revoke a key immediately β–Ύ

Sets revoked_at timestamp. All subsequent requests using this key will receive 401 invalid_api_key. Irreversible β€” rotate instead if you need a replacement.

POST /developer/keys/{key_id}/rotate Revoke + reissue with identical settings β–Ύ

Atomically revokes the old key and creates a replacement with the same environment, plan, scopes, and label. The new plaintext key is returned once.

GET /developer/usage API usage metrics for your org β–Ύ
Query ParamValuesDescription
period7d Β· 30d Β· 90dLookback window (default 30d)
key_idintegerFilter to a specific key

Try It

Send a live request to the sandbox API.

Response
{ "status": "otp_sent", "expires_in": 300, "channel": "sms" }
200 OK 42ms