curl -X PUT \
'https://app.medisync.me/api/documents/665e0b9d3f2a1c4d8e7f0a12' \
-H 'Authorization: Bearer your_jwt_token_here' \
-F 'document=@updated_report.pdf' \
-F 'title=Updated Report'
const formData = new FormData();
formData.append('document', file); // PDF or image file
formData.append('title', 'Updated Report'); // optional
const response = await fetch(
'https://app.medisync.me/api/documents/665e0b9d3f2a1c4d8e7f0a12',
{
method: 'PUT',
headers: { Authorization: 'Bearer your_jwt_token_here' },
body: formData,
}
);
const result = await response.json();
import requests
files = {'document': open('updated_report.pdf', 'rb')}
data = {'title': 'Updated Report'} # optional
response = requests.put(
'https://app.medisync.me/api/documents/665e0b9d3f2a1c4d8e7f0a12',
headers={'Authorization': 'Bearer your_jwt_token_here'},
files=files,
data=data,
)
result = response.json()
{
"success": true,
"data": {
"_id": "66a3f1c2b8e4d21f9c0a7b40",
"appointment_id": "665e0b9d3f2a1c4d8e7f0a12",
"document_url": "<internal storage reference>",
"document_key": "<internal storage reference>",
"doctor_id": "6512a7c9e4b0a1f2d3c45678",
"file_name": "updated_report.pdf",
"title": "updated_report.pdf",
"file_type": "pdf",
"mime_type": "application/pdf",
"source": "upload",
"extraction_status": "pending",
"include_in_context": true,
"createdAt": "2026-07-02T15:20:00.000Z",
"updatedAt": "2026-07-02T15:20:00.000Z",
"__v": 0
}
}
Documents
Update Medical Document
Replace or add a document on an appointment
PUT
/
documents
/
{id}
curl -X PUT \
'https://app.medisync.me/api/documents/665e0b9d3f2a1c4d8e7f0a12' \
-H 'Authorization: Bearer your_jwt_token_here' \
-F 'document=@updated_report.pdf' \
-F 'title=Updated Report'
const formData = new FormData();
formData.append('document', file); // PDF or image file
formData.append('title', 'Updated Report'); // optional
const response = await fetch(
'https://app.medisync.me/api/documents/665e0b9d3f2a1c4d8e7f0a12',
{
method: 'PUT',
headers: { Authorization: 'Bearer your_jwt_token_here' },
body: formData,
}
);
const result = await response.json();
import requests
files = {'document': open('updated_report.pdf', 'rb')}
data = {'title': 'Updated Report'} # optional
response = requests.put(
'https://app.medisync.me/api/documents/665e0b9d3f2a1c4d8e7f0a12',
headers={'Authorization': 'Bearer your_jwt_token_here'},
files=files,
data=data,
)
result = response.json()
{
"success": true,
"data": {
"_id": "66a3f1c2b8e4d21f9c0a7b40",
"appointment_id": "665e0b9d3f2a1c4d8e7f0a12",
"document_url": "<internal storage reference>",
"document_key": "<internal storage reference>",
"doctor_id": "6512a7c9e4b0a1f2d3c45678",
"file_name": "updated_report.pdf",
"title": "updated_report.pdf",
"file_type": "pdf",
"mime_type": "application/pdf",
"source": "upload",
"extraction_status": "pending",
"include_in_context": true,
"createdAt": "2026-07-02T15:20:00.000Z",
"updatedAt": "2026-07-02T15:20:00.000Z",
"__v": 0
}
}
Overview
Uploads a new document file for an appointment. Depending on what is already attached, the endpoint either replaces an existing document or adds a new one:- If the appointment has a consent document, that consent document is replaced.
- Otherwise, if the appointment has exactly one document, that document is replaced.
- Otherwise (multiple documents and none is a consent document), the new file is simply added.
_id is created on every call. Accepted file types are PDF, PNG, JPEG, JPG and WEBP, with a maximum file size of 25 MB.
This operation is not atomic. When a document is replaced, the old file is deleted from storage and the database first, and the new file is uploaded afterward. If the new upload fails, the old document is already gone.
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 doctor’s ID is extracted from the JWT token.
Authorization: Bearer your_jwt_token_here
Path Parameters
string
required
The appointment ID (ObjectId) whose document should be replaced or created. 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 replacement 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 operation was successful
object
The newly stored document record
Show Document Object
Show Document Object
string
Unique document identifier (a new ObjectId is generated on each call)
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 uploading doctor (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. New 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 PUT \
'https://app.medisync.me/api/documents/665e0b9d3f2a1c4d8e7f0a12' \
-H 'Authorization: Bearer your_jwt_token_here' \
-F 'document=@updated_report.pdf' \
-F 'title=Updated Report'
const formData = new FormData();
formData.append('document', file); // PDF or image file
formData.append('title', 'Updated Report'); // optional
const response = await fetch(
'https://app.medisync.me/api/documents/665e0b9d3f2a1c4d8e7f0a12',
{
method: 'PUT',
headers: { Authorization: 'Bearer your_jwt_token_here' },
body: formData,
}
);
const result = await response.json();
import requests
files = {'document': open('updated_report.pdf', 'rb')}
data = {'title': 'Updated Report'} # optional
response = requests.put(
'https://app.medisync.me/api/documents/665e0b9d3f2a1c4d8e7f0a12',
headers={'Authorization': 'Bearer your_jwt_token_here'},
files=files,
data=data,
)
result = response.json()
Example Response
{
"success": true,
"data": {
"_id": "66a3f1c2b8e4d21f9c0a7b40",
"appointment_id": "665e0b9d3f2a1c4d8e7f0a12",
"document_url": "<internal storage reference>",
"document_key": "<internal storage reference>",
"doctor_id": "6512a7c9e4b0a1f2d3c45678",
"file_name": "updated_report.pdf",
"title": "updated_report.pdf",
"file_type": "pdf",
"mime_type": "application/pdf",
"source": "upload",
"extraction_status": "pending",
"include_in_context": true,
"createdAt": "2026-07-02T15:20:00.000Z",
"updatedAt": "2026-07-02T15:20:00.000Z",
"__v": 0
}
}
Error Responses
{
"success": false,
"error": "Error deleting old document"
}
{
"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": "No file uploaded"
}
{
"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"
}