Skip to main content
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": "https://storage.medisync.me/665e0b9d3f2a1c4d8e7f0a12_1719920400000_lab_results.pdf",
    "document_key": "665e0b9d3f2a1c4d8e7f0a12_1719920400000_lab_results.pdf",
    "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).
This endpoint is plan-gated by the documents.attach_additional feature. Accounts whose plan does not include it receive 403 FEATURE_NOT_AVAILABLE.

Authentication

Authorization
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

id
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 as multipart/form-data.
document
file
required
The document file. Allowed types: application/pdf, image/png, image/jpeg, image/jpg, image/webp.
title
string
Optional display title for the document. If omitted, the uploaded file’s original filename is used.

Response

success
boolean
Whether the upload was successful
data
object
The stored document record
error
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": "https://storage.medisync.me/665e0b9d3f2a1c4d8e7f0a12_1719920400000_lab_results.pdf",
    "document_key": "665e0b9d3f2a1c4d8e7f0a12_1719920400000_lab_results.pdf",
    "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": "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_id is set to the newly created document.
  • Upload/save failures are returned as 400 with { "success": false, "error": "Error uploading or saving document" }.
  • The Authorization errors above also cover revoked sessions, which return 401 with { "success": false, "message": "Session ended on this device because you signed in elsewhere.", "code": "SESSION_REVOKED" }.