This is the backend server for the ConvertingPDF web app — a tool that lets you merge, split, compress, edit, and convert PDF files to other formats.
The server is built with Flask, provides a REST API for PDF processing, and handles user authentication, email verification, and conversion history tracking.
-
🔐 User authentication with JWT
-
📧 Email verification with expiration handling
-
🗂 Track user conversions in the database
-
📑 PDF operations:
- Merge PDFs
- Split PDFs
- Compress PDFs
- Convert PDF → Word (
.docx) - Convert PDF → JPG (zipped images)
- Edit PDFs (add text or images)
-
⏱ Rate limiting for security (
10 requests/minute)
- Backend Framework:
- Database:
- Auth: JWT + bcrypt
- Email: Flask-Mail (SMTP)
- File Handling: PyPDF2 / pdf2docx / Pillow
- Clone the repo
git clone https://github.com/itachi-555/convertingpdf-server.git
cd convertingpdf-server- Install dependencies
pip install -r requirements.txt- Configure environment variables
Create a .env file:
SECRET_KEY=your_secret_key
MAIL_SERVER=smtp.yourmail.com
MAIL_PORT=587
MAIL_USERNAME=your_email@example.com
MAIL_PASSWORD=your_password- Run the server
python app.pyThe server will start at:
http://localhost:10000
- Build the Docker image
docker build -t convertingpdf-server .- Run the container
docker run -d -p 10000:10000 --env-file .env convertingpdf-server- The server will be accessible at:
http://localhost:10000
Most routes require a JWT Bearer Token.
- Signup:
POST /signup→ creates account & sends verification email - Verify Email:
GET /verify-email/<token> - Login:
POST /login→ returns JWT token - Delete Account:
DELETE /delete
Send the token in the Authorization header:
Authorization: Bearer <your_token>
Also include X-User-ID in headers for PDF routes:
X-User-ID: <user_id>
curl -X POST http://localhost:10000/merge-pdf \
-H "Authorization: Bearer <token>" \
-H "X-User-ID: <user_id>" \
-F "files=@file1.pdf" \
-F "files=@file2.pdf"Response:
{
"conversion_id": "uuid",
"converted_filename": "file1.pdf_merged.pdf",
"converted_file_size": 12345,
"downloadUrl": "/downloads/file1.pdf_merged.pdf",
"status": "completed",
"message": "Conversion completed successfully"
}curl -X POST http://localhost:10000/split-pdf \
-H "Authorization: Bearer <token>" \
-H "X-User-ID: <user_id>" \
-F "file=@document.pdf" \
-F "splitType=pages" \
-F "splitValue=2"Notes:
-
splitTypeaccepted values:"pages"→ split the PDF every N pages"ranges"→ split the PDF using specific page ranges
-
splitValuedepends onsplitType:- If
splitType="pages", provide a number of pages per split, e.g.,2. - If
splitType="ranges", provide ranges as comma-separatedstart-endpairs, e.g.,"1-3,5-6".
- If
Response:
{
"conversion_id": "uuid",
"converted_filename": "document_split.zip",
"converted_file_size": 54321,
"downloadUrl": "/downloads/document_split.zip",
"status": "completed",
"message": "Conversion completed successfully"
}curl -X POST http://localhost:10000/compress-pdf \
-H "Authorization: Bearer <token>" \
-H "X-User-ID: <user_id>" \
-F "file=@document.pdf" \
-F "compressionLevel=high"Response:
{
"conversion_id": "uuid",
"converted_filename": "document_compressed.pdf",
"converted_file_size": 12345,
"downloadUrl": "/downloads/document_compressed.pdf",
"status": "completed",
"message": "Conversion completed successfully"
}Notes:
compressionLevelaccepted values:"low"→ minimal compression, preserves quality"medium"→ balanced compression and file size"high"→ maximum compression, smaller file size but lower quality
curl -X POST http://localhost:10000/pdf-to-word \
-H "Authorization: Bearer <token>" \
-H "X-User-ID: <user_id>" \
-F "file=@document.pdf"Response:
{
"conversion_id": "uuid",
"converted_filename": "document.docx",
"converted_file_size": 23456,
"downloadUrl": "/downloads/document.docx",
"status": "completed",
"message": "Conversion completed successfully"
}curl -X POST http://localhost:10000/pdf-to-jpg \
-H "Authorization: Bearer <token>" \
-H "X-User-ID: <user_id>" \
-F "file=@document.pdf"Response:
{
"conversion_id": "uuid",
"converted_filename": "document_jpg.zip",
"converted_file_size": 34567,
"downloadUrl": "/downloads/document_jpg.zip",
"status": "completed",
"message": "Conversion completed successfully"
}curl -X POST http://localhost:10000/edit \
-H "Authorization: Bearer <token>" \
-H "X-User-ID: <user_id>" \
-F "file=@document.pdf" \
-F 'editData={"content":"Hello World","x":50,"y":100}' \
-F "editType=add-text"Notes:
-
editTypeaccepted values:"add-text"→ add plain text to the PDF"add-signature"→ add a signature (image path or content)"add-annotation"→ add a text annotation"add-image"→ add an image (provide as file inimageFile)
-
editDatafields:content→ text content for"add-text"/"add-signature"/"add-annotation"; ignored for"add-image"x,y→ coordinates (in points) on the page for placementpage_number(optional) → 1-indexed page to edit (default:1)
Response:
{
"conversion_id": "uuid",
"converted_filename": "document_edited.pdf",
"converted_file_size": 23456,
"downloadUrl": "/downloads/document_edited.pdf",
"status": "completed",
"message": "Conversion completed successfully"
}curl -X GET http://localhost:10000/conversions \
-H "Authorization: Bearer <token>" \
-H "X-User-ID: <user_id>"Response:
{
"data": [
{
"conversion_id": "uuid",
"converted_filename": "document_edited.pdf",
"conversion_type": "edit",
"file_size": 23456,
"downloadUrl": "/downloads/document_edited.pdf",
"status": "completed"
}
]
}convertingpdf/
├── app.py # Main Flask server with endpoints
├── auth.py # Email verification helpers
├── database.py # Supabase integration
├── tools.py # PDF processing functions (merge, split, compress, convert)
├── pages.py # HTML templates & verification messages
├── Dockerfile # Container deployment
├── requirements.txt # Python dependencies
└── README.md # This file