---
title: "Attach a Document"
description: "Upload files such as lab results or consent forms and attach them to a patient's record."
canonical_url: "http://localhost/api/quickstart/attach-document"
---
# Attach a Document
> Upload files such as lab results or consent forms and attach them to a patient's record.
Learn how to upload files to patient records. Documents are files like lab results, imaging reports, consent forms, or any other files that need to be attached to a patient's medical record.
This guide requires `care_unit_id` and `resource_id` from [Show Doctor's Availability](http://localhost/api/quickstart/show-availability), and a valid `patient_id` from [Find or Get Patient](http://localhost/api/quickstart/find-patient) or [Create Patient](http://localhost/api/quickstart/create-patient). If the patient does not exist yet, create them first.
## Flow Overview

## Understanding Documents
- **Documents**: Files attached to patient records (PDFs, images, lab results, scans)
- **vs Medical Notes**: Documents are binary files; medical notes are text-based clinical records
- **Base64 Encoding**: Binary files must be encoded to text for JSON transmission
- **MIME Types**: Specify file type (e.g., `application/pdf`, `image/jpeg`)
- **Common Use Cases**: Lab reports, imaging results, consent forms, referral letters
Documents vs Medical Notes
Documents are different from medical notes. Documents are files (PDFs, images), while medical notes are text-based clinical records. See [Write a Medical Note](http://localhost/api/quickstart/write-medical-note) for clinical documentation.
## Code Example
```python
import requests
import base64
import mimetypes
CLIENT_ID = "your-client-id"
CLIENT_SECRET = "your-client-secret"
BASE_URL = "https://api.leyr.io/api"
EMR = "webdoc"
headers = {
"x-leyr-client-id": CLIENT_ID,
"x-leyr-client-secret": CLIENT_SECRET,
"Content-Type": "application/json"
}
care_unit_id = "care-unit-123"
patient_id = "se_personal_number:191212121212"
resource_id = "resource-123"
file_path = "lab_results.pdf"
# 1. Read file and encode to base64
with open(file_path, "rb") as file:
file_content = file.read()
base64_content = base64.b64encode(file_content).decode("utf-8")
# 2. Determine MIME type
file_format, _ = mimetypes.guess_type(file_path)
if not file_format:
file_format = "application/octet-stream"
# 3. Prepare document payload
document_data = {
"content": base64_content,
"format": file_format,
"title": "Blood Test Results",
"type": "Lab Result",
"created_by_id": resource_id
}
# 4. Upload the document
response = requests.post(
f"{BASE_URL}/emrs/{EMR}/care-units/{care_unit_id}/patients/{patient_id}/documents",
headers=headers,
json=document_data
)
document = response.json()
# 5. Read key values from the response
print("✓ Document uploaded successfully!")
print(f" Document ID: {document['id']}")
print(f" Title: {document['title']}")
print(f" Type: {document.get('type')}")
print(f" Format: {document['format']}")
print(f" Size: {len(file_content)} bytes")
```
```javascript
const CLIENT_ID = "your-client-id";
const CLIENT_SECRET = "your-client-secret";
const BASE_URL = "https://api.leyr.io/api";
const EMR = "webdoc";
const headers = {
"x-leyr-client-id": CLIENT_ID,
"x-leyr-client-secret": CLIENT_SECRET,
"Content-Type": "application/json"
};
const careUnitId = "care-unit-123";
const patientId = "se_personal_number:191212121212";
const resourceId = "resource-123";
const fs = require("fs").promises;
const path = require("path");
const filePath = "lab_results.pdf";
// 1. Read file and encode to base64
const fileContent = await fs.readFile(filePath);
const base64Content = fileContent.toString("base64");
// 2. Determine MIME type
const getMimeType = (filename) => {
const ext = path.extname(filename).toLowerCase();
const mimeTypes = {
".pdf": "application/pdf",
".jpg": "image/jpeg",
".jpeg": "image/jpeg",
".png": "image/png",
".doc": "application/msword",
".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
};
return mimeTypes[ext] || "application/octet-stream";
};
const fileFormat = getMimeType(filePath);
// 3. Prepare document payload
const documentData = {
content: base64Content,
format: fileFormat,
title: "Blood Test Results",
type: "Lab Result",
created_by_id: resourceId
};
// 4. Upload the document
const response = await fetch(
`${BASE_URL}/emrs/${EMR}/care-units/${careUnitId}/patients/${patientId}/documents`,
{
method: "POST",
headers,
body: JSON.stringify(documentData)
}
);
const document = await response.json();
// 5. Read key values from the response
console.log("✓ Document uploaded successfully!");
console.log(` Document ID: ${document.id}`);
console.log(` Title: ${document.title}`);
console.log(` Type: ${document.type}`);
console.log(` Format: ${document.format}`);
console.log(` Size: ${fileContent.length} bytes`);
```
### Shared setup
```python
import requests
import base64
import mimetypes
CLIENT_ID = "your-client-id"
CLIENT_SECRET = "your-client-secret"
BASE_URL = "https://api.leyr.io/api"
EMR = "webdoc"
headers = {
"x-leyr-client-id": CLIENT_ID,
"x-leyr-client-secret": CLIENT_SECRET,
"Content-Type": "application/json"
}
care_unit_id = "care-unit-123"
patient_id = "se_personal_number:191212121212"
resource_id = "resource-123"
file_path = "lab_results.pdf"
```
```javascript
const CLIENT_ID = "your-client-id";
const CLIENT_SECRET = "your-client-secret";
const BASE_URL = "https://api.leyr.io/api";
const EMR = "webdoc";
const headers = {
"x-leyr-client-id": CLIENT_ID,
"x-leyr-client-secret": CLIENT_SECRET,
"Content-Type": "application/json"
};
const careUnitId = "care-unit-123";
const patientId = "se_personal_number:191212121212";
const fs = require("fs").promises;
const path = require("path");
const filePath = "lab_results.pdf";
```
#### 1. Read file and encode to base64
```python
with open(file_path, "rb") as file:
file_content = file.read()
base64_content = base64.b64encode(file_content).decode("utf-8")
```
```javascript
const fileContent = await fs.readFile(filePath);
const base64Content = fileContent.toString("base64");
```
#### 2. Determine MIME type
You will very often know file format beforehand, e.g. if you know your system generates PDF summaries of the measurements, so you can as well provide it directly.
```python
file_format, _ = mimetypes.guess_type(file_path)
```
```javascript
const getMimeType = (filename) => {
const ext = path.extname(filename).toLowerCase();
const mimeTypes = {
".pdf": "application/pdf",
".jpg": "image/jpeg",
".jpeg": "image/jpeg",
".png": "image/png",
".doc": "application/msword",
".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
};
return mimeTypes[ext];
};
const fileFormat = getMimeType(filePath);
```
#### 3. Prepare document payload
```python
document_data = {
"content": base64_content,
"format": file_format,
"title": "Blood Test Results",
"type": "Lab Result",
"created_by_id": resource_id
}
```
```javascript
const documentData = {
content: base64Content,
format: fileFormat,
title: "Blood Test Results",
type: "Lab Result",
created_by_id: resourceId
};
```
#### 4. Upload the document
```python
response = requests.post(
f"{BASE_URL}/emrs/{EMR}/care-units/{care_unit_id}/patients/{patient_id}/documents",
headers=headers,
json=document_data
)
document = response.json()
```
```javascript
const response = await fetch(
`${BASE_URL}/emrs/${EMR}/care-units/${careUnitId}/patients/${patientId}/documents`,
{
method: "POST",
headers,
body: JSON.stringify(documentData)
}
);
const document = await response.json();
```
#### 5. Read key values from the response
```python
print("✓ Document uploaded successfully!")
print(f" Document ID: {document['id']}")
print(f" Title: {document['title']}")
print(f" Type: {document.get('type')}")
print(f" Format: {document['format']}")
print(f" Size: {len(file_content)} bytes")
```
```javascript
console.log("✓ Document uploaded successfully!");
console.log(` Document ID: ${document.id}`);
console.log(` Title: ${document.title}`);
console.log(` Type: ${document.type}`);
console.log(` Format: ${document.format}`);
console.log(` Size: ${fileContent.length} bytes`);
```
## patient_id usage
Use `patient_id` in path parameters with one of these formats:
- `abc_12345` (treated as `emr_id`)
- `emr_id:abc_12345`
- `se_personal_number:191212121212` (when supported by the EHR)
Use [Find or Get Patient](http://localhost/api/quickstart/find-patient) to discover identifiers and [Patient IDs](http://localhost/api/guides/patient-id) for full format support.
## Common MIME Types
Here are common MIME types for medical documents:
|
File Type
|
Extension
|
MIME Type
|
|
PDF
|
.pdf
|
application/pdf
|
|
JPEG Image
|
.jpg
,
.jpeg
|
image/jpeg
|
|
PNG Image
|
.png
|
image/png
|
|
Word Document
|
.doc
|
application/msword
|
|
Word Document (new)
|
.docx
|
application/vnd.openxmlformats-officedocument.wordprocessingml.document
|
|
DICOM Image
|
.dcm
|
application/dicom
|
|
Text File
|
.txt
|
text/plain
|
## File Size Limits
Be aware of file size limitations:
```python
import os
# Check file size before uploading
file_size = os.path.getsize(file_path)
max_size = 20 * 1024 * 1024 # 20 MB
if file_size > max_size:
print(f"Error: File too large ({file_size} bytes)")
print(f"Maximum allowed: {max_size} bytes")
else:
# Proceed with upload
with open(file_path, "rb") as file:
file_content = file.read()
# ... rest of upload code
```
```javascript
// Check file size before uploading
const fileStats = await fs.stat(filePath);
const maxSize = 20 * 1024 * 1024; // 20 MB
if (fileStats.size > maxSize) {
console.log(`Error: File too large (${fileStats.size} bytes)`);
console.log(`Maximum allowed: ${maxSize} bytes`);
} else {
// Proceed with upload
const fileContent = await fs.readFile(filePath);
// ... rest of upload code
}
```
File size limits vary by EHR. For larger files > 20 MB, consider splitting or compressing them.
## Retrieving Documents
#### 1. Get all documents for a patient
```python
response = requests.get(
f"{BASE_URL}/emrs/{EMR}/care-units/{care_unit_id}/patients/{patient_id}/documents",
headers=headers
)
documents_response = response.json()
documents = documents_response["items"]
print(f"Found {len(documents)} documents")
for doc in documents:
print(f" - {doc['id']}: {doc.get('title')} [{doc.get('format')}]")
```
```javascript
let response = await fetch(
`${BASE_URL}/emrs/${EMR}/care-units/${careUnitId}/patients/${patientId}/documents`,
{ headers }
);
const documentsResponse = await response.json();
const documents = documentsResponse.items;
console.log(`Found ${documents.length} documents`);
documents.forEach(doc => {
console.log(` - ${doc.id}: ${doc.title} [${doc.format}]`);
});
```
#### 2. Get one document and decode content
```python
document_id = documents[0]["id"]
response = requests.get(
f"{BASE_URL}/emrs/{EMR}/care-units/{care_unit_id}/patients/{patient_id}/documents/{document_id}",
headers=headers
)
document = response.json()
if "content" in document:
file_content = base64.b64decode(document["content"])
with open("downloaded_document.bin", "wb") as f:
f.write(file_content)
print("Downloaded: downloaded_document.bin")
```
```javascript
const documentId = documents[0].id;
response = await fetch(
`${BASE_URL}/emrs/${EMR}/care-units/${careUnitId}/patients/${patientId}/documents/${documentId}`,
{ headers }
);
const document = await response.json();
if (document.content) {
const fileContent = Buffer.from(document.content, "base64");
await fs.writeFile("downloaded_document.bin", fileContent);
console.log("Downloaded: downloaded_document.bin");
}
```
## Best Practices
- **Validate Files**: Check file size and type before uploading
- **Use Descriptive Titles**: Help users identify documents easily
- **Set Type When Useful**: Use `type` to categorize documents (e.g., Lab Result, Consent Form)
- **Compress Large Files**: Consider compressing large documents before upload
## Next steps
Look up a patient and choose the correct patient_id for your requests.
Advanced topics and best practices.
## API Reference
For detailed API documentation, see:
- [Documents API](https://api.leyr.io/docs#tag/Documents)
## Sitemap
See the full [sitemap](http://localhost/sitemap.md) for all pages.