---
title: "ABDM API — Documents"
description: "Nice HMS ABDM document endpoints that create FHIR compositions and push them to ABDM: discharge_summary, diagnostic_report, op_consultation, procedure_ot_notes, and health_document (multipart)."
date: 2026-08-26
lastModified: 2026-10-04
category: "developer"
author: "Dr. Umesh Bilagi"
beta: true
---

Document endpoints are **POST** and authenticated (`Authorization: Bearer <idToken>`).
Each creates a FHIR Composition and pushes it to ABDM. Each returns a `CompositionRes`
object (a `composition` FHIR resource). All use **"patientNeeds"** — at least one of
`abhaAddress` (string) or `patientId` (number); omitting both yields
`400 VALIDATION_ERROR`.

The five document endpoints share these error codes (plus each endpoint's own extras):

> `INVALID_DOCTOR_GCP_FHIR_ID` (400) · `PATIENT_NOT_FOUND` (404) ·
> `ENCOUNTER_NOT_FOUND` (404) · `NO_ACTIVE_ENCOUNTER` (409) ·
> `ABDM_GATEWAY_ERROR` (502) · `LINK_TOKEN_MISSING` (502) · `LINK_TOKEN_RATE_LIMITED` (429)

### Encounter resolution

Every document is filed against an encounter (the ABDM care-context reference). Each of
the five endpoints accepts an optional `encounterId`; resolution works the same way for
all of them:

1. **`encounterId` supplied** — that encounter is used. It must belong to the patient
   **and** to your organization, otherwise `404 ENCOUNTER_NOT_FOUND`.
2. **`encounterId` omitted** — the patient's **open** encounter is used (status
   `in-progress`, `arrived`, `planned`, `triaged`).
3. **No open encounter** — the patient's **most recent** encounter is used, whatever its
   status (**including `finished`**) — so a discharged patient's documents still upload.
4. **No encounter at all** — `409 NO_ACTIVE_ENCOUNTER`. Create a visit with
   `/opd_patient` or `/admit_patient` before pushing a document.

---

## File uploads

The four JSON document endpoints — `/discharge_summary`, `/diagnostic_report`,
`/op_consultation`, `/procedure_ot_notes` — accept **text/HTML only** via their `text` /
content fields. They cannot accept file attachments (no multipart upload).

Only `/health_document` accepts file uploads. It accepts **PDF, JPEG or PNG** files up to
**5 MB** each, across `page1`–`page4`, with **a PDF uploaded on its own** — a PDF cannot
be combined with images. A file's type is determined from the file's own bytes, not from
the `Content-Type` you send for that part, so a renamed or mislabelled file is rejected
rather than silently stored as something else. Scanned PDFs can be sent directly —
converting to images is no longer required.

---

## `/discharge_summary` — POST (auth)

Creates a DischargeSummary composition and pushes it to ABDM.

### Request fields

| Name | Type | Required | Description |
|---|---|---|---|
| `doctorDetails` | array | Yes | Array of `{ doctorName, doctorGcpId }`, min 1. |
| `text` | string | Yes | Summary content (HTML allowed). |
| `status` | string | Yes | Use `"final"` — only `final` is pushed to ABDM. |
| `date` | string | Yes | ISO date. |
| `compositionId` | string | No | Optional composition id. |
| `encounterId` | string | No | Attach to a specific encounter (must belong to the patient and your org). When omitted, see [Encounter resolution](#encounter-resolution). |
| `abhaAddress` | string | —* | Patient's ABHA address. |
| `patientId` | number | —* | Nice HMS patient id. |

\* At least one of `abhaAddress` / `patientId` is required.

### Example request

```json
{
  "abhaAddress": "savitribilagi@sbx",
  "text": "<div>Cough with APD</div><div>cough</div><div>BP 140/80 PR 87/min RR 20/min</div>",
  "doctorDetails": [
    { "doctorName": "Dr Umesh Bilagi", "doctorGcpId": "cf4a6ab1-3f32-4b92-adc5-89489da6ca14" }
  ],
  "status": "final",
  "date": "2023-05-08T19:21:23.918Z"
}
```

### Example response

```json
{
  "composition": {
    "id": "e721069a-cc8c-4e5e-a437-b4cfcaee11a4",
    "resourceType": "Composition",
    "status": "final",
    "title": "DischargeSummary",
    "date": "2023-05-08T19:21:23.918Z",
    "subject": { "reference": "Patient/9b4ec056-991d-4237-b1fd-a65770349610" }
  }
}
```

### Error codes

- Shared document codes + shared auth codes.
- `ENCOUNTER_NOT_FOUND` (404) — a supplied `encounterId` does not belong to this patient and org.
- `NO_ACTIVE_ENCOUNTER` (409) — the patient has no encounter at all; create a visit first.

---

## `/diagnostic_report` — POST (auth)

Creates a DiagnosticReport composition and pushes it to ABDM.

### Request fields

| Name | Type | Required | Description |
|---|---|---|---|
| `performer` | array | Yes | Array of `{ doctorName, doctorGcpId }`, min 1. The performer is who signs the report. |
| `testName` | string | Yes | Non-empty, e.g. `"CT Abdomen"`. |
| `category` | string | Yes | `"Hematology"` \| `"Biochemistry"` \| `"Microbiology"` \| `"Radiology"` \| `"Others"`. |
| `text` | string | Yes | Non-empty report content (HTML allowed). |
| `status` | string | Yes | Use `"final"` — only `final` is pushed to ABDM. |
| `requester` | object | No | `{ doctorName, doctorGcpId }`. If omitted, the requester is assumed to be the patient. |
| `conclusion` | string | No | e.g. `"Normal Study"`. |
| `compositionId` | string | No | Optional. |
| `encounterId` | string | No | Attach to a specific encounter (must belong to the patient and your org). When omitted, see [Encounter resolution](#encounter-resolution). |
| `date` | string | No | ISO date; defaults to the request timestamp when omitted. |
| `abhaAddress` | string | —* | Patient's ABHA address. |
| `patientId` | number | —* | Nice HMS patient id. |

\* At least one of `abhaAddress` / `patientId` is required.

### Example request

```json
{
  "abhaAddress": "savitribilagi@sbx",
  "performer": [
    { "doctorName": "Dr Umesh Bilagi", "doctorGcpId": "cf4a6ab1-3f32-4b92-adc5-89489da6ca14" }
  ],
  "testName": "CT Abdomen",
  "category": "Radiology",
  "text": "<div>Ultrasound Report ...</div>",
  "status": "final",
  "conclusion": "Normal Study"
}
```

### Example response

Returns a `CompositionRes` object.

### Error codes

- `INVALID_DOCTOR_GCP_FHIR_ID` (400) — validates `performer` **and** `requester`.
- `PATIENT_NOT_FOUND` (404) · `ENCOUNTER_NOT_FOUND` (404) · `NO_ACTIVE_ENCOUNTER` (409)
- `ABDM_GATEWAY_ERROR` (502) · `LINK_TOKEN_MISSING` (502) · `LINK_TOKEN_RATE_LIMITED` (429)
- shared codes

---

## `/op_consultation` — POST (auth)

Creates an OP Consultation composition and pushes it to ABDM.

### Request fields

| Name | Type | Required | Description |
|---|---|---|---|
| `doctorDetails` | array | Yes | Array of `{ doctorName, doctorGcpId }`, min 1. |
| `date` | string | Yes | ISO date of the consultation. |
| `status` | string | Yes | Current status of the consultation. |
| `chiefComplaints` | string | No | Primary complaints reported by the patient. |
| `medicalHistory` | string | No | Patient's past medical history. |
| `physicalExamination` | string | No | Findings from the physical examination. |
| `medicines` | array | No | Array of `{ drug, frequency, instruction, duration, route }`. |
| `opdProcedure` | object | No | `{ procedureName, procedureDescription, date? }`. |
| `followUp` | object | No | `{ startDate, endDate?, comment }`. |
| `compositionId` | string | No | Optional. |
| `encounterId` | string | No | Attach to a specific encounter (must belong to the patient and your org). When omitted, see [Encounter resolution](#encounter-resolution). |
| `abhaAddress` | string | —* | Patient's ABHA address. |
| `patientId` | number | —* | Nice HMS patient id. |

\* At least one of `abhaAddress` / `patientId` is required.

### Example request

```json
{
  "abhaAddress": "savitribilagi@sbx",
  "doctorDetails": [
    { "doctorName": "Dr Umesh Bilagi", "doctorGcpId": "cf4a6ab1-3f32-4b92-adc5-89489da6ca14" }
  ],
  "date": "2023-05-08T19:21:23.918Z",
  "status": "final",
  "chiefComplaints": "Cough and fever",
  "medicines": [
    { "drug": "Paracetamol", "frequency": "BD", "instruction": "After food", "duration": "5 days", "route": "Oral" }
  ]
}
```

### Example response

Returns a `CompositionRes` object.

### Error codes

- `INVALID_DOCTOR_GCP_FHIR_ID` (400)
- `PATIENT_NOT_FOUND` (404) · `ENCOUNTER_NOT_FOUND` (404) · `NO_ACTIVE_ENCOUNTER` (409)
- `ABDM_GATEWAY_ERROR` (502) · `LINK_TOKEN_MISSING` (502) · `LINK_TOKEN_RATE_LIMITED` (429)
- shared codes

---

## `/procedure_ot_notes` — POST (auth)

Creates a procedure / OT-notes composition and pushes it to ABDM.

### Request fields

| Name | Type | Required | Description |
|---|---|---|---|
| `doctorDetails` | array | Yes | Array of `{ doctorName, doctorGcpId }`, min 1. |
| `date` | string | Yes | ISO date of the procedure. |
| `status` | string | Yes | Current status of the procedure. |
| `opdProcedure` | object | No | `{ procedureName, procedureDescription, date? }`. |
| `followUp` | object | No | `{ startDate, endDate?, comment }`. |
| `compositionId` | string | No | Optional. |
| `encounterId` | string | No | Attach to a specific encounter (must belong to the patient and your org). When omitted, see [Encounter resolution](#encounter-resolution). |
| `abhaAddress` | string | —* | Patient's ABHA address. |
| `patientId` | number | —* | Nice HMS patient id. |

\* At least one of `abhaAddress` / `patientId` is required.

### Example request

```json
{
  "abhaAddress": "savitribilagi@sbx",
  "doctorDetails": [
    { "doctorName": "Dr Umesh Bilagi", "doctorGcpId": "cf4a6ab1-3f32-4b92-adc5-89489da6ca14" }
  ],
  "date": "2023-05-08T19:21:23.918Z",
  "status": "final",
  "opdProcedure": {
    "procedureName": "Appendectomy",
    "procedureDescription": "Laparoscopic appendectomy"
  }
}
```

### Example response

Returns a `CompositionRes` object.

### Error codes

- `INVALID_DOCTOR_GCP_FHIR_ID` (400)
- `PATIENT_NOT_FOUND` (404) · `ENCOUNTER_NOT_FOUND` (404) · `NO_ACTIVE_ENCOUNTER` (409)
- `ABDM_GATEWAY_ERROR` (502) · `LINK_TOKEN_MISSING` (502) · `LINK_TOKEN_RATE_LIMITED` (429)
- shared codes

---

## `/health_document` — POST (multipart/form-data, auth)

Uploads a scanned health document (PDF, JPEG or PNG) and creates a HealthDocumentRecord
composition. Each file must be under 5 MB.

### Request fields (form fields)

| Name | Type | Required | Description |
|---|---|---|---|
| `doctorDetails` | string | Yes | **JSON string**, e.g. `"[{\"doctorName\":\"Dr Umesh\",\"doctorGcpId\":\"...\"}]"`. |
| `text` | string | Yes | Title, e.g. `"Prescription"` or `"Lab report"`. |
| `status` | string | Yes | One of `preliminary`, `final`, `amended`, `entered-in-error`. Only `final` is pushed to ABDM. |
| `date` | string | No | ISO date. |
| `compositionId` | string | No | Optional. |
| `encounterId` | string | No | Attach to a specific encounter (must belong to the patient and your org). When omitted, see [Encounter resolution](#encounter-resolution). |
| `abhaAddress` | string | —* | Patient's ABHA address. |
| `patientId` | number | —* | Nice HMS patient id. |

\* At least one of `abhaAddress` / `patientId` is required.

### Files

| Name | Required | Description |
|---|---|---|
| `page1` | Yes | PDF, JPEG or PNG, ≤ 5 MB. |
| `page2` | No | PDF, JPEG or PNG, ≤ 5 MB. |
| `page3` | No | PDF, JPEG or PNG, ≤ 5 MB. |
| `page4` | No | PDF, JPEG or PNG, ≤ 5 MB. |

If one of `page1`–`page4` is a PDF, it must be the only file in the request. Send the
request as `multipart/form-data` using your client's multipart mode — do not set a
`Content-Type` header by hand, or the multipart boundary is lost and the request is
rejected.

### Example response

Returns a `CompositionRes` object, plus:

| Name | Description |
|---|---|
| `abdmNotified` | `true` if the document was pushed to ABDM. `false` when `status` is not `final`. |
| `abdmNotifiedReason` | Present only when `abdmNotified` is `false` — why it was not pushed. |

### Error codes

- `INVALID_REQUEST_METHOD` (400) — non-POST method.
- `DOCTOR_DETAILS_REQUIRED` (400) — `doctorDetails` form field missing.
- `VALIDATION_ERROR` (400) — invalid form fields; unsupported file type; no file sent; a PDF combined with images.
- `VALIDATION_ERROR` (**413**) — a file exceeds the 5 MB limit.
- `INVALID_DOCTOR_GCP_FHIR_ID` (400)
- `PATIENT_NOT_FOUND` (404) · `ENCOUNTER_NOT_FOUND` (404) · `NO_ACTIVE_ENCOUNTER` (409)
- `ABDM_GATEWAY_ERROR` (502) · `LINK_TOKEN_MISSING` (502) · `LINK_TOKEN_RATE_LIMITED` (429)
- shared codes
