PDF Conversion API

Frontend Integration Guide

API Version 1.0.0

Overview

How It Works

The PDF Conversion API uses an asynchronous task processing model. Unlike standard synchronous requests, you submit a job, get a task_id, and poll for completion.

Processing Time: Most conversions complete in 2-10 seconds depending on file size.

Base URL

Production: http://YOUR_SERVER_IP:8002
Local Dev:  http://localhost:8002

Interactive API Docs: http://YOUR_SERVER_IP:8002/docs

Authentication

The API is currently open — no authentication required.

Future versions will support API keys and OAuth2.

Conversion Flow

1

Upload File

POST /api/v1/convert

Returns: task_id

2

Check Status

GET /api/v1/status/{id}

Poll every 1-2 seconds

3

Download Result

GET /api/v1/download/{id}

When status = completed

Status Values

Status Description Action
pending Task queued, waiting to start Keep polling
processing Conversion in progress Keep polling
completed Conversion successful Download file
failed Conversion error occurred Check error message

Available Conversions

📥 Conversions TO PDF

jpg_to_pdf → .pdf
png_to_pdf → .pdf
word_to_pdf → .pdf
powerpoint_to_pdf → .pdf
excel_to_pdf → .pdf
html_to_pdf → .pdf

📤 Conversions FROM PDF

pdf_to_jpg → .jpg
pdf_to_png → .png
pdf_to_word → .docx
pdf_to_powerpoint → .pptx
pdf_to_excel → .xlsx
pdf_to_pdfa → .pdf

API Endpoints

GET /health

Check if the API is running and services are connected.

{
  "status": "healthy",
  "redis": "connected",
  "celery": "running"
}
GET /api/v1/formats

Retrieve all available conversion types with descriptions.

Use this to populate dropdown menus in your UI.

GET /api/v1/stats

Get the total number of conversions performed by the system.

{
  "total_conversions": 1234,
  "message": "Total conversions since system deployment"
}
POST /api/v1/convert

Upload file and start background conversion task.

Content-Type: multipart/form-data

Field Type Required Description
file File ✅ Yes File to convert (max 50MB)
conversion_type String ✅ Yes Type of conversion
quality Integer ❌ No Output quality 1-100 (default: 95)
dpi Integer ❌ No DPI for image conversions (default: 300)
compress Boolean ❌ No Apply compression (default: false)
{
  "task_id": "abc-123-def-456",
  "status": "pending",
  "message": "Conversion task created successfully",
  "created_at": "2026-01-09T12:00:00"
}
{
  "detail": "File size exceeds maximum limit of 50MB"
}
GET /api/v1/status/{task_id}

Check progress and current status of a specific task.

{
  "task_id": "abc-123-def-456",
  "status": "pending",
  "progress": 0,
  "message": "Task is queued...",
  "download_url": null,
  "error": null
}
{
  "task_id": "abc-123-def-456",
  "status": "processing",
  "progress": 50,
  "message": "Converting file...",
  "download_url": null,
  "error": null
}
{
  "task_id": "abc-123-def-456",
  "status": "completed",
  "progress": 100,
  "message": "Conversion completed successfully",
  "download_url": "/api/v1/download/abc-123-def-456",
  "error": null
}
{
  "task_id": "abc-123-def-456",
  "status": "failed",
  "progress": 0,
  "message": "Conversion failed",
  "download_url": null,
  "error": "Invalid file format"
}
GET /api/v1/download/{task_id}

Download the final converted binary file.

Response: Binary file data with appropriate Content-Type

Request Examples

async function convertFile(file, conversionType) {
  // 1. Upload file
  const formData = new FormData();
  formData.append('file', file);
  formData.append('conversion_type', conversionType);
  formData.append('quality', 95);

  const uploadResponse = await fetch('http://localhost:8002/api/v1/convert', {
    method: 'POST',
    body: formData
  });

  const { task_id } = await uploadResponse.json();
  console.log('Task created:', task_id);

  // 2. Poll for status
  let status = 'pending';
  while (status === 'pending' || status === 'processing') {
    await new Promise(resolve => setTimeout(resolve, 2000)); // Wait 2 seconds

    const statusResponse = await fetch(
      `http://localhost:8002/api/v1/status/${task_id}`
    );
    const statusData = await statusResponse.json();
    status = statusData.status;

    console.log('Status:', status, 'Progress:', statusData.progress + '%');

    if (status === 'failed') {
      throw new Error(statusData.error);
    }
  }

  // 3. Download result
  if (status === 'completed') {
    const downloadUrl = `http://localhost:8002/api/v1/download/${task_id}`;
    window.location.href = downloadUrl; // Trigger download
    return task_id;
  }
}

// Usage
const fileInput = document.getElementById('fileInput');
const file = fileInput.files[0];
convertFile(file, 'word_to_pdf');
import { useState } from 'react';

function useFileConverter() {
  const [loading, setLoading] = useState(false);
  const [progress, setProgress] = useState(0);
  const [error, setError] = useState(null);

  const convertFile = async (file, conversionType) => {
    setLoading(true);
    setError(null);
    setProgress(0);

    try {
      // Upload
      const formData = new FormData();
      formData.append('file', file);
      formData.append('conversion_type', conversionType);

      const response = await fetch('http://localhost:8002/api/v1/convert', {
        method: 'POST',
        body: formData
      });

      if (!response.ok) {
        throw new Error('Upload failed');
      }

      const { task_id } = await response.json();

      // Poll status
      const checkStatus = async () => {
        const statusResponse = await fetch(
          `http://localhost:8002/api/v1/status/${task_id}`
        );
        const data = await statusResponse.json();

        setProgress(data.progress);

        if (data.status === 'completed') {
          // Download
          const downloadUrl = `http://localhost:8002/api/v1/download/${task_id}`;
          const link = document.createElement('a');
          link.href = downloadUrl;
          link.download = `converted_file.pdf`;
          link.click();
          setLoading(false);
          return;
        }

        if (data.status === 'failed') {
          throw new Error(data.error || 'Conversion failed');
        }

        // Continue polling
        setTimeout(checkStatus, 2000);
      };

      await checkStatus();
    } catch (err) {
      setError(err.message);
      setLoading(false);
    }
  };

  return { convertFile, loading, progress, error };
}
import requests
import time

def convert_file(file_path, conversion_type):
    # 1. Upload file
    with open(file_path, 'rb') as f:
        files = {'file': f}
        data = {
            'conversion_type': conversion_type,
            'quality': 95
        }
        response = requests.post(
            'http://localhost:8002/api/v1/convert',
            files=files,
            data=data
        )
    
    task_id = response.json()['task_id']
    print(f"Task created: {task_id}")
    
    # 2. Poll for status
    while True:
        status_response = requests.get(
            f'http://localhost:8002/api/v1/status/{task_id}'
        )
        status_data = status_response.json()
        
        print(f"Status: {status_data['status']}, Progress: {status_data['progress']}%")
        
        if status_data['status'] == 'completed':
            break
        elif status_data['status'] == 'failed':
            raise Exception(status_data['error'])
        
        time.sleep(2)
    
    # 3. Download result
    download_response = requests.get(
        f'http://localhost:8002/api/v1/download/{task_id}'
    )
    
    with open('converted_file.pdf', 'wb') as f:
        f.write(download_response.content)
    
    print("Download complete!")

# Usage
convert_file('document.docx', 'word_to_pdf')
# 1. Convert Word to PDF
TASK_ID=$(curl -X POST "http://localhost:8002/api/v1/convert" \
  -F "file=@document.docx" \
  -F "conversion_type=word_to_pdf" \
  | jq -r '.task_id')

echo "Task ID: $TASK_ID"

# 2. Check status (poll until completed)
while true; do
  STATUS=$(curl -s "http://localhost:8002/api/v1/status/$TASK_ID" | jq -r '.status')
  echo "Status: $STATUS"
  
  if [ "$STATUS" = "completed" ]; then
    break
  elif [ "$STATUS" = "failed" ]; then
    echo "Conversion failed!"
    exit 1
  fi
  
  sleep 2
done

# 3. Download result
curl "http://localhost:8002/api/v1/download/$TASK_ID" -o converted.pdf
echo "Download complete: converted.pdf"

Error Handling

Common Errors

Status Code Error Solution
400 Invalid file format Check that file matches conversion type
400 Missing required fields Ensure file and conversion_type are provided
404 Task not found Task may have expired (24hr lifetime)
413 File too large Maximum file size is 50MB
500 Internal server error Contact API administrator

Best Practices

  • Always validate files client-side before uploading
  • Implement retry logic for network errors
  • Show progress indicators to users during polling
  • Handle timeouts - stop polling after 2-3 minutes
  • Store task_id in case user refreshes page

Rate Limits & File Size

50 MB
Max File Size
24h
Task Retention
1-2s
Polling Interval
Concurrent Tasks

Quick Start Checklist

  • Get the API base URL from your backend team
  • Test the /health endpoint to verify connectivity
  • Fetch available formats from /api/v1/formats
  • Implement file upload with multipart/form-data
  • Add status polling with 2-second intervals
  • Handle download trigger when status is completed
  • Add error handling for all failure cases
  • Implement progress indicators for better UX
  • Add file size validation (max 50MB)
  • Test with various file types and sizes