curl -X POST \
'https://app.medisync.me/api/documents/add/665e0b9d3f2a1c4d8e7f0a12' \
-H 'Authorization: Bearer your_jwt_token_here' \
-F 'document=@lab_results.pdf' \
-F 'title=Lab Results'
const formData = new FormData();
formData.append('document', file); // PDF or image file
formData.append('title', 'Lab Results'); // optional
const response = await fetch(
'https://app.medisync.me/api/documents/add/665e0b9d3f2a1c4d8e7f0a12',
{
method: 'POST',
headers: { Authorization: 'Bearer your_jwt_token_here' },
body: formData,
}
);
const result = await response.json();
import requests
files = {'document': open('lab_results.pdf', 'rb')}
data = {'title': 'Lab Results'} # optional
response = requests.post(
'https://app.medisync.me/api/documents/add/665e0b9d3f2a1c4d8e7f0a12',
headers={'Authorization': 'Bearer your_jwt_token_here'},
files=files,
data=data,
)
result = response.json()
{
"success": true,
"data": {
"_id": "66a3f1c2b8e4d21f9c0a7b31",
"appointment_id": "665e0b9d3f2a1c4d8e7f0a12",
"document_url": "<internal storage reference>",
"document_key": "<internal storage reference>",
"doctor_id": "6512a7c9e4b0a1f2d3c45678",
"file_name": "lab_results.pdf",
"title": "lab_results.pdf",
"file_type": "pdf",
"mime_type": "application/pdf",
"source": "upload",
"extraction_status": "pending",
"include_in_context": true,
"createdAt": "2026-07-02T14:30:00.000Z",
"updatedAt": "2026-07-02T14:30:00.000Z",
"__v": 0
}
}
Documents
Upload Medical Document
Upload a document file and attach it to an appointment
POST
/
documents
/
add
/
{id}
curl -X POST \
'https://app.medisync.me/api/documents/add/665e0b9d3f2a1c4d8e7f0a12' \
-H 'Authorization: Bearer your_jwt_token_here' \
-F 'document=@lab_results.pdf' \
-F 'title=Lab Results'
const formData = new FormData();
formData.append('document', file); // PDF or image file
formData.append('title', 'Lab Results'); // optional
const response = await fetch(
'https://app.medisync.me/api/documents/add/665e0b9d3f2a1c4d8e7f0a12',
{
method: 'POST',
headers: { Authorization: 'Bearer your_jwt_token_here' },
body: formData,
}
);
const result = await response.json();
import requests
files = {'document': open('lab_results.pdf', 'rb')}
data = {'title': 'Lab Results'} # optional
response = requests.post(
'https://app.medisync.me/api/documents/add/665e0b9d3f2a1c4d8e7f0a12',
headers={'Authorization': 'Bearer your_jwt_token_here'},
files=files,
data=data,
)
result = response.json()
{
"success": true,
"data": {
"_id": "66a3f1c2b8e4d21f9c0a7b31",
"appointment_id": "665e0b9d3f2a1c4d8e7f0a12",
"document_url": "<internal storage reference>",
"document_key": "<internal storage reference>",
"doctor_id": "6512a7c9e4b0a1f2d3c45678",
"file_name": "lab_results.pdf",
"title": "lab_results.pdf",
"file_type": "pdf",
"mime_type": "application/pdf",
"source": "upload",
"extraction_status": "pending",
"include_in_context": true,
"createdAt": "2026-07-02T14:30:00.000Z",
"updatedAt": "2026-07-02T14:30:00.000Z",
"__v": 0
}
}
Overview
Uploads a document file and attaches it to an existing appointment. The file is stored in secure object storage and a document record is created and linked to the appointment. The uploading doctor is taken from the JWT token. Accepted file types are PDF, PNG, JPEG, JPG and WEBP (application/pdf, image/png, image/jpeg, image/jpg, image/webp). The maximum file size is 25 MB.
This endpoint is plan-gated by the
documents.attach_additional feature. Accounts whose plan does not include it receive 403 FEATURE_NOT_AVAILABLE.Authentication
string
required
Bearer token for authenticated access. The uploading doctor’s ID is extracted from the JWT token.
Authorization: Bearer your_jwt_token_here
Path Parameters
string
required
The appointment ID (ObjectId) to attach the document to. The appointment must belong to the authenticated doctor, otherwise a
403 Forbidden is returned.Body Parameters
The request must be sent asmultipart/form-data.
file
required
The document file. Allowed types:
application/pdf, image/png, image/jpeg, image/jpg, image/webp. Maximum size 25 MB — larger files are rejected with 413.string
Optional display title for the document. If omitted, the uploaded file’s original filename is used.
Response
boolean
Whether the upload was successful
object
The stored document record
Show Document Object
Show Document Object
string
Unique document identifier (ObjectId)
string
The appointment this document is attached to
string
Internal storage reference. Not a fetchable link — retrieve the file with
GET /documents/get/{appointmentId}, which enforces ownership. Treat as opaque.string
Internal storage reference. Opaque — its format is not part of the API contract and may change without notice. Do not parse or construct it.
string
ObjectId of the doctor who uploaded the document (the authenticated user)
string
Original filename of the uploaded file
string
Display title (defaults to the original filename)
string
Inferred short file type (e.g.
pdf, png, jpeg, webp)string
MIME type of the stored file
string
Origin of the document.
upload for files uploaded through this endpointstring
Text-extraction state. Newly uploaded documents start as
pendingboolean
Whether the document is included when building context. Defaults to
truestring
Creation timestamp (ISO 8601)
string
Last-update timestamp (ISO 8601)
number
Internal record version
string
Error message (only present when
success is false)Additional fields may be present on the document object and should be treated as opaque.
Example Request
curl -X POST \
'https://app.medisync.me/api/documents/add/665e0b9d3f2a1c4d8e7f0a12' \
-H 'Authorization: Bearer your_jwt_token_here' \
-F 'document=@lab_results.pdf' \
-F 'title=Lab Results'
const formData = new FormData();
formData.append('document', file); // PDF or image file
formData.append('title', 'Lab Results'); // optional
const response = await fetch(
'https://app.medisync.me/api/documents/add/665e0b9d3f2a1c4d8e7f0a12',
{
method: 'POST',
headers: { Authorization: 'Bearer your_jwt_token_here' },
body: formData,
}
);
const result = await response.json();
import requests
files = {'document': open('lab_results.pdf', 'rb')}
data = {'title': 'Lab Results'} # optional
response = requests.post(
'https://app.medisync.me/api/documents/add/665e0b9d3f2a1c4d8e7f0a12',
headers={'Authorization': 'Bearer your_jwt_token_here'},
files=files,
data=data,
)
result = response.json()
Example Response
{
"success": true,
"data": {
"_id": "66a3f1c2b8e4d21f9c0a7b31",
"appointment_id": "665e0b9d3f2a1c4d8e7f0a12",
"document_url": "<internal storage reference>",
"document_key": "<internal storage reference>",
"doctor_id": "6512a7c9e4b0a1f2d3c45678",
"file_name": "lab_results.pdf",
"title": "lab_results.pdf",
"file_type": "pdf",
"mime_type": "application/pdf",
"source": "upload",
"extraction_status": "pending",
"include_in_context": true,
"createdAt": "2026-07-02T14:30:00.000Z",
"updatedAt": "2026-07-02T14:30:00.000Z",
"__v": 0
}
}
Error Responses
{
"success": false,
"error": "No file uploaded"
}
{
"success": false,
"error": "Unsupported file type. Allowed: PDF, PNG, JPEG, WEBP."
}
{
"success": false,
"error": "File too large. Maximum size is 25 MB."
}
{
"success": false,
"error": "Appointment not found"
}
{
"success": false,
"error": "Forbidden"
}
{
"success": false,
"code": "FEATURE_NOT_AVAILABLE",
"feature": "documents.attach_additional",
"message": "This feature is not included in your current plan."
}
{
"success": false,
"message": "Unauthorized"
}
Behavior
- Automatic appointment linking: on success, the appointment record’s
document_idis set to the newly created document. - Upload/save failures are returned as
400with{ "success": false, "error": "Error uploading or saving document" }. - The
Authorizationerrors above also cover revoked sessions, which return401with{ "success": false, "message": "Session ended on this device because you signed in elsewhere.", "code": "SESSION_REVOKED" }.