Skip to content

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.

Authorization: Bearer <access_token>
x-api-key: YOUR_API_KEY

Uploading a Document

Endpoint

POST /Patients({id})/Documents

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

GET /Patients({id})/Documents

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

GET /Patients({patientId})/Documents({documentId})

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

GET /Patients({patientId})/Documents({documentId})/$value

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

DELETE /Patients({patientId})/Documents({documentId})

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
PDF 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 id after upload — you will need it for retrieval and deletion
  • Use $filter on the document list endpoint to narrow results by document_type or uploaded_at date

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