Uploading and Downloading Documents
The Nymbl Customer API supports attaching documents to patient records. This guide explains how to upload documents to a patient, retrieve document metadata, and download document content.
Overview
Documents are associated with a specific patient and stored securely in Nymbl's document store. Each document has:
- A unique document ID
- Metadata — file name, content type, size, upload date, uploader
- Binary content — the actual file bytes
The document endpoints use standard HTTP multipart upload for sending files and respond with binary streams for downloads.
Authentication
All document requests require both a valid OAuth 2.0 Bearer token and an API key. See the Authentication Guide for details.
Uploading a Document
Endpoint
Request Format
Documents are uploaded using multipart/form-data. The request must include:
| Field | Type | Required | Description |
|---|---|---|---|
file |
File | Yes | The file to upload |
document_type |
String | No | Category or type label for the document |
description |
String | No | Human-readable description |
Example — cURL
curl -X POST "https://api.nymblqa.com/Patients(12345)/Documents" \
-H "Authorization: Bearer eyJraWQiOiJ..." \
-H "x-api-key: YOUR_API_KEY" \
-F "file=@/path/to/document.pdf" \
-F "document_type=Referral" \
-F "description=Referral from Dr. Smith"
Example — Python
import requests
token = "eyJraWQiOiJ..."
patient_id = 12345
with open("/path/to/document.pdf", "rb") as f:
response = requests.post(
f"https://api.nymblqa.com/Patients({patient_id})/Documents",
headers={
"Authorization": f"Bearer {token}",
"x-api-key": API_KEY
},
files={"file": ("document.pdf", f, "application/pdf")},
data={
"document_type": "Referral",
"description": "Referral from Dr. Smith"
}
)
response.raise_for_status()
document = response.json()
print(f"Uploaded document ID: {document['id']}")
Example — Node.js
const fs = require("fs");
const FormData = require("form-data");
const axios = require("axios");
const token = "eyJraWQiOiJ...";
const patientId = 12345;
const form = new FormData();
form.append("file", fs.createReadStream("/path/to/document.pdf"), "document.pdf");
form.append("document_type", "Referral");
form.append("description", "Referral from Dr. Smith");
const response = await axios.post(
`https://api.nymblqa.com/Patients(${patientId})/Documents`,
form,
{
headers: {
Authorization: `Bearer ${token}`,
'x-api-key': API_KEY,
...form.getHeaders(),
},
}
);
console.log("Uploaded document ID:", response.data.id);
Success Response
{
"id": "doc-abc123",
"patient_id": "12345",
"file_name": "document.pdf",
"content_type": "application/pdf",
"file_size_bytes": 204800,
"document_type": "Referral",
"description": "Referral from Dr. Smith",
"uploaded_by_id": "user-456",
"uploaded_at": "2026-02-21T14:30:00Z"
}
Listing Documents for a Patient
Endpoint
Returns document metadata for all documents attached to the specified patient. Standard OData query parameters ($filter, $select, $orderby, $top, $skip, $count) are supported.
Example Request
curl -X GET "https://api.nymblqa.com/Patients(12345)/Documents" \
-H "Authorization: Bearer eyJraWQiOiJ..." \
-H "x-api-key: YOUR_API_KEY"
Example Response
{
"@odata.context": "https://api.nymblqa.com/$metadata#Documents",
"@odata.count": 2,
"value": [
{
"id": "doc-abc123",
"patient_id": "12345",
"file_name": "referral.pdf",
"content_type": "application/pdf",
"file_size_bytes": 204800,
"document_type": "Referral",
"uploaded_at": "2026-02-21T14:30:00Z"
},
{
"id": "doc-def456",
"patient_id": "12345",
"file_name": "insurance-card.png",
"content_type": "image/png",
"file_size_bytes": 51200,
"document_type": "Insurance",
"uploaded_at": "2026-01-15T09:00:00Z"
}
]
}
Retrieving a Single Document's Metadata
Endpoint
Example Request
curl -X GET "https://api.nymblqa.com/Patients(12345)/Documents(doc-abc123)" \
-H "Authorization: Bearer eyJraWQiOiJ..." \
-H "x-api-key: YOUR_API_KEY"
Downloading a Document
Endpoint
The /$value segment returns the raw binary content of the document, with the appropriate Content-Type header set.
Example — cURL
curl -X GET "https://api.nymblqa.com/Patients(12345)/Documents(doc-abc123)/\$value" \
-H "Authorization: Bearer eyJraWQiOiJ..." \
-H "x-api-key: YOUR_API_KEY" \
-o downloaded-document.pdf
Example — Python
import requests
token = "eyJraWQiOiJ..."
patient_id = 12345
document_id = "doc-abc123"
response = requests.get(
f"https://api.nymblqa.com/Patients({patient_id})/Documents({document_id})/$value",
headers={
"Authorization": f"Bearer {token}",
"x-api-key": API_KEY
},
stream=True
)
response.raise_for_status()
with open("downloaded-document.pdf", "wb") as f:
for chunk in response.iter_content(chunk_size=8192):
f.write(chunk)
print("Download complete")
Example — Node.js
const fs = require("fs");
const axios = require("axios");
const token = "eyJraWQiOiJ...";
const patientId = 12345;
const documentId = "doc-abc123";
const response = await axios.get(
`https://api.nymblqa.com/Patients(${patientId})/Documents(${documentId})/$value`,
{
headers: {
Authorization: `Bearer ${token}`,
'x-api-key': API_KEY
},
responseType: "stream",
}
);
const writer = fs.createWriteStream("downloaded-document.pdf");
response.data.pipe(writer);
await new Promise((resolve, reject) => {
writer.on("finish", resolve);
writer.on("error", reject);
});
console.log("Download complete");
Deleting a Document
Endpoint
Example Request
curl -X DELETE "https://api.nymblqa.com/Patients(12345)/Documents(doc-abc123)" \
-H "Authorization: Bearer eyJraWQiOiJ..." \
-H "x-api-key: YOUR_API_KEY"
A successful deletion returns 204 No Content.
Supported File Types
The following file types are accepted:
| Type | MIME Type | Notes |
|---|---|---|
application/pdf |
Preferred for clinical documents | |
| PNG | image/png |
Insurance cards, scanned images |
| JPEG | image/jpeg |
Photographs |
| TIFF | image/tiff |
High-resolution scans |
| DOCX | application/vnd.openxmlformats-officedocument.wordprocessingml.document |
Word documents |
File Size Limit
Individual document uploads are limited to 25 MB. Contact support for larger file requirements.
Error Responses
| Status | Meaning |
|---|---|
400 Bad Request |
Missing required field or unsupported file type |
401 Unauthorized |
Invalid or expired access token |
404 Not Found |
Patient or document not found |
413 Payload Too Large |
File exceeds the 25 MB size limit |
500 Internal Server Error |
Unexpected server error |
Best Practices
Performance Tips
- Stream large downloads rather than loading the entire file into memory
- Store the returned document
idafter upload — you will need it for retrieval and deletion - Use
$filteron the document list endpoint to narrow results bydocument_typeoruploaded_atdate
Security
Documents may contain Protected Health Information (PHI). Ensure your application handles document data in compliance with HIPAA requirements:
- Transmit documents only over HTTPS
- Do not log document content or URLs that expose document IDs in cleartext
- Apply least-privilege access — only request documents when necessary