ConnectAI
Developers/Sending documents to patients

Sending documents to patients

Push a lab report or a prescription, and we deliver it to the patient on WhatsApp — under rules the clinic sets, not you.

Two flows, one mechanism. A pathology lab finishes a report and pushes it to us; a doctor writes a prescription in their own EMR and pushes that. In both cases the patient gets it on WhatsApp from the clinic they know, with no app to install and nothing to chase.

The clinic decides whether it is sent

This is the part to understand before you build. Uploading a document is not the same as sending it. Each clinic configures, per document type, whether we deliver automatically and whether quiet hours apply.

DefaultLab reportsPrescriptions
Auto-sendOnOff — a person at the clinic releases each one
Quiet hours respectedYesYes
Typical quiet window21:00 → 08:00 clinic time21:00 → 08:00 clinic time

Prescriptions default to held because a prescription is a clinical instruction issued in a doctor's name. A clinic should switch that on deliberately rather than discover it has been happening.

Your response always tells you which way it went, so you never have to guess:

`status`Meaning
SENTDelivered to the patient's WhatsApp
HELDStored, waiting — either auto-send is off, or it is inside quiet hours. releaseAfter says when
FAILEDWe tried and could not. statusReason says why
SUPPRESSEDA sandbox key. Stored, never sent — this is how you test safely

Lab report

POST /integration/v1/lab-reports
{
  "externalId": "LIS-RPT-55210",
  "patientPhone": "+919811223344",
  "patientName": "Rohan Mehta",
  "label": "Complete Blood Count",
  "file": {
    "filename": "cbc-report.pdf",
    "mimeType": "application/pdf",
    "base64": "JVBERi0xLjQKJc..."
  },
  "meta": { "sampleCollectedAt": "2026-09-24T08:10:00+05:30", "labName": "Sunrise Diagnostics" }
}

201 Created
{
  "resource": {
    "type": "document",
    "documentType": "lab_report",
    "connectaiId": "68f1c2...",
    "externalId": "LIS-RPT-55210",
    "patientConnectaiId": "68a9...",
    "status": "SENT",
    "sentAt": "2026-09-24T09:15:02.118Z",
    "action": "received"
  }
}

The patient receives the PDF as a real WhatsApp attachment they can keep, with label in the message text — send something a patient recognises ("Complete Blood Count"), not an internal code.

Prescription

POST /integration/v1/prescriptions
{
  "externalId": "EMR-RX-99871",
  "patientExternalId": "HMS-PT-88213",
  "doctorPhone": "+919812000111",
  "label": "Prescription — 24 Sep",
  "file": {
    "filename": "prescription.pdf",
    "url": "https://emr.example.com/rx/99871.pdf"
  }
}

201 Created
{
  "resource": {
    "type": "document",
    "documentType": "prescription",
    "externalId": "EMR-RX-99871",
    "status": "HELD",
    "statusReason": "Auto-send is off for this document type",
    "action": "received"
  }
}

HELD is the expected answer for a prescription on a clinic that has not opted in. It is stored and someone at the clinic releases it — treat it as success, not as an error.

Sending the file

FieldUse it when
file.base64You already hold the bytes. Simplest, one call
file.urlThe file is already on your storage. Must be https; we fetch it once
file.filenameAlways. This is what the patient sees
file.mimeTypeOptional. Inferred from the filename when omitted
  • PDF, JPEG and PNG only.
  • 15 MB maximum.
  • We store our own copy, so your URL does not have to stay reachable afterwards.

Identifying the patient

Send patientExternalId if you have used one with us before. Otherwise patientPhone plus patientName is enough — an unknown patient is created and linked to the clinic. A lab holds a name and a phone, not our patient ids, and a real report should never go undelivered over a bookkeeping detail.

Checking delivery

GET /integration/v1/documents/LIS-RPT-55210
{
  "resource": {
    "type": "document",
    "documentType": "lab_report",
    "externalId": "LIS-RPT-55210",
    "status": "HELD",
    "statusReason": "Inside the clinic's quiet hours",
    "releaseAfter": "2026-09-25T02:30:00.000Z",
    "action": "found"
  }
}

You can also subscribe to document.delivered and document.failed webhooks instead of polling. See Webhooks.

Re-sending the same externalId returns the first result and does NOT deliver again. That is deliberate: a retry after a network timeout must never put the same report in front of a patient twice.