PHR Realtime Events

All PHR-patient real-time events are published to a single per-ABHA Pusher channel, phr-{hash} (see phrChannelForAbha in pusher-service.ts). The frontend resolves this channel name (plus the Pusher public key) from GET /v1/realtime/channels?abhaAddress=..., then subscribes and listens for the events below.

All events are emitted via triggerUserEvent(abhaAddress, event, payload).

Most operator-facing events (consent lifecycle, care-context linking, health-info pushes, subscriptions, NHCX) emit on the facility channel via triggerFacilityEvent and never reach the PHR app. The exceptions are listed below: the patient self-fetch pair, the patient-share acknowledgement, and notification:created, which is fanned out to both channels whenever the notification carries an abhaAddress.

The authoritative list is REALTIME_EVENTS.phr in realtime.events.ts, which GET /v1/realtime/channels returns as its events field — bind by constant name rather than hard-coding the strings below. For the endpoint contract (request/response shape, auth, and the GET /v1/realtime/events replay fallback) see the Realtime section of NHCX & Platform.

Events

Event Triggered when Source
user-linking:on-discovered Discovery result is ready (care contexts found, or an error such as ABDM-1010) handleOnDiscover (user-linking.callback.service.ts), and the rare sync path in user-linking.service.ts
user-linking:init HIP receives ABDM's init callback; OTP-based linking has started handleInit
user-linking:on-init HIU receives the init result; carries the linkRefNumber the frontend needs to confirm handleOnInit
user-linking:confirmed HIP-side confirm: OTP verified, care contexts marked linked handleConfirm
user-linking:on-confirmed HIU-side confirm result delivered handleOnConfirm
patient-share:on-share HIU on-share callback lands — the patient's scan-and-share profile was accepted and a queue token assigned handleHiuOnShare (patient-share.callback.service.ts)
phr-self-fetch:granted A patient self-fetch consent (PATRQT) is granted — fired on grant and again when the artefact detail arrives, so treat it as idempotent handleConsentGranted / handleArtefactFetched (consent-callback.operations.ts)
phr-self-fetch:syncing The health-information request for a granted self-fetch artefact was accepted; records are on their way. One per artefact on a multi-HIP grant same as above
notification:created Any notification is persisted with an abhaAddress — mirrors the facility bell into the PHR notifications tab createNotification (notification.service.ts)

Payloads

user-linking:on-discovered

{
  transactionId: string | null
  patientRef: string | null
  careContexts: { referenceNumber: string; display: string }[]
  matchedBy: string[]            // e.g. ["ABHA_ADDRESS"]
  isError: boolean
  errorCode: string | null       // e.g. "ABDM-1010"
  errorMessage: string | null
}

user-linking:init

{
  transactionId: string | null
  abhaAddress: string | null
  careContextCount: number
  expiresAt: string // ISO 8601, OTP/session expiry
  linkRefNumber: string
}

user-linking:on-init

{
  transactionId: string | null
  linkRefNumber: string | null // pass this to /care-context/confirm
  authenticationType: string | null // e.g. "DIRECT"
  communicationMedium: string | null // e.g. "MOBILE"
  communicationExpiry: string | null // ISO 8601
  isError: boolean
  errorMessage: string | null
}

user-linking:confirmed

{
  transactionId: string | null
  abhaAddress: string
  linkedContexts: string[]       // care context reference numbers
  linkedAt: string               // ISO 8601
}

user-linking:on-confirmed

{
  transactionId: string | null
  linkedContextCount: number
  isError: boolean
  errorMessage: string | null
  linkedAt: string // ISO 8601
}

patient-share:on-share

{
  requestId: string
  status: string                 // "SUCCESS" when a token was assigned, else "ERROR"
  tokenNumber: string | null     // queue token to present at the counter
  context: string | null         // counter/department the token is for
  expiry: string | null          // ISO 8601
  error: { code: string; message: string } | null
  receivedAt: string             // ISO 8601
}

Emitted for every on-share callback carrying an abhaAddress, including failures — check status before showing a token. A notification:created follows on SUCCESS only.

phr-self-fetch:granted

{
  consentId: string
}

Fires as soon as the grant callback lands, so the UI can advance from "Consent requested" to "Consent granted" without waiting for on-fetch, which the sandbox delivers unreliably. It fires a second time when the artefact detail arrives — dedupe on consentId.

phr-self-fetch:syncing

{
  consentId: string
}

The health-information request was accepted for one artefact; records will land in the LHR shortly. A multi-HIP grant has one artefact per HIP and emits this once per artefact, all with the same consentId, so it is not a completion signal — poll the records endpoint for actual delivery.

notification:created

{
  id: string
  type: string // NotificationType enum, e.g. "CONSENT_GRANTED"
  title: string
  body: string | null
  abhaAddress: string | null
  metadata: Record<string, unknown> | null
  sourceEvent: string // the event that caused it, e.g. "patient-share:on-share"
  isRead: false
  createdAt: string // ISO 8601
}

The identical payload also goes to the facility channel — this is the same notification seen from the patient's side, not a separate one. Only notifications created with an abhaAddress reach the PHR channel.