PDF document conversion

PDF to Word
API Documentation

Convert PDF documents into editable Microsoft Word (.docx) files with optional OCR for scanned and image-based pages โ€” synchronously or through async jobs โ€” over a simple REST API. Built for developers.

Try it now Back to API Hub

Overview

The PDF to Word API converts PDF documents into editable Word (.docx) files while preserving text, tables, and layout. For scanned or image-based PDFs, enable OCR to extract text automatically. Synchronous conversion is ideal for small files; the async endpoints are designed for larger documents or batch workflows. Multiprocessing is used on the server to keep conversions fast.

Base URL & Authentication

Base URL

Base URL

https://api.chemhub.com/api/v1

Authentication

Include your API credentials in every request header.

Headers

X-API-Key: your_api_key
X-API-Secret: your_secret
Content-Type: application/json

Get API Keys

Follow these steps to obtain your API credentials:

1

Log In to Your Account

Existing Users: Go to /login to access your dashboard

New Users: Visit /register to create your free account first

2

Access Your Profile

Once you log in, click on your profile picture in the top-right corner, then click on "Your profile" from the dropdown menu.

3

Create API Key

From your profile page, proceed to the "API Keys" section and create a key by filling in a name you prefer.

Example name

"PDF converter bot" or "My Document Pipeline"

4

Save Your Credentials

Click on "Create API Key" to generate your credentials, then immediately copy and save both the API Key and Secret.

Critical Warning

Your secret key will only be displayed once! Copy it immediately and store it securely. You won't be able to see it again.

Security Notice

Never share your API keys publicly or commit them to version control. Treat them like passwords โ€” regenerate immediately if compromised.

Rate Limits

15 requests per minute per API key. Check your dashboard for current usage and limits.

Endpoints

๐Ÿ’š Health CheckGET /pdf2word/health
๐Ÿ”„ Convert PDF to WordPOST /pdf2word/convert
โณ Convert (Async)POST /pdf2word/convert/async
๐Ÿ“‹ Job StatusGET /pdf2word/jobs/{job_id}
โฌ‡๏ธ Download ResultGET /pdf2word/jobs/{job_id}/download

Health Check

GET/pdf2word/health

Health check endpoint to verify the PDF to Word service status, available backends, and supported formats.

Response

Success Response

{
  "success": true,
  "status": "healthy",
  "pdf2w_backends": {
    "pdfplumber": true,
    "tesseract": true,
    "ftfy": true,
    "docx": true
  },
  "supported_formats": [".pdf"],
  "max_file_size_mb": 20,
  "database_available": true,
  "timestamp": "2026-08-07T12:00:00"
}

Code Examples

Python

import requests

url = "https://api.chemhub.com/api/v1/pdf2word/health"

headers = {
    "X-API-Key": "your_api_key",
    "X-API-Secret": "your_secret"
}

res = requests.get(url, headers=headers)
print(res.json())

cURL

curl -X GET https://api.chemhub.com/api/v1/pdf2word/health \
-H "X-API-Key: your_api_key" \
-H "X-API-Secret: your_secret"

JavaScript

fetch('https://api.chemhub.com/api/v1/pdf2word/health', {
  method: 'GET',
  headers: {
    'X-API-Key': 'your_api_key',
    'X-API-Secret': 'your_secret'
  }
})
.then(res => res.json())
.then(console.log);

Convert PDF to Word

POST/pdf2word/convert

Convert a PDF file to a Word document synchronously. Upload the file as multipart/form-data.

Form Parameters

FieldTypeDefaultDescription
fileFileโ€”PDF file (required) โ€” up to 20MB
use_ocrboolfalseSet to true to run OCR on scanned / image-based pages
Response

On success the endpoint returns the converted Word document bytes directly with Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document.

cURL Example

cURL

curl -X POST "https://api.chemhub.com/api/v1/pdf2word/convert" \
  -H "X-API-Key: your_api_key" \
  -H "X-API-Secret: your_secret" \
  -F "file=@document.pdf" \
  -F "use_ocr=false" \
  --output document.docx

Code Examples

Python

import requests

url = "https://api.chemhub.com/api/v1/pdf2word/convert"

headers = {
    "X-API-Key": "your_api_key",
    "X-API-Secret": "your_secret"
}

with open("document.pdf", "rb") as f:
    files = {"file": f}
    data = {"use_ocr": "true"}
    response = requests.post(url, headers=headers, files=files, data=data)

if response.status_code == 200:
    with open("document.docx", "wb") as out:
        out.write(response.content)
    print("Conversion successful!")
else:
    print(response.json())

JavaScript

const form = new FormData();
form.append('file', fileInput.files[0]);
form.append('use_ocr', 'true');

fetch('https://api.chemhub.com/api/v1/pdf2word/convert', {
  method: 'POST',
  headers: {
    'X-API-Key': 'your_api_key',
    'X-API-Secret': 'your_secret'
  },
  body: form
})
.then(async res => {
  if (res.ok) {
    const blob = await res.blob();
    const url = URL.createObjectURL(blob);
    console.log('Word document URL:', url);
  } else {
    console.log(await res.json());
  }
});

Convert PDF to Word (Async)

POST/pdf2word/convert/async

Submit a conversion job and receive a job_id immediately. Use the job endpoints to poll for progress and download the result. Ideal for large files or batch workflows.

Form Parameters

Same parameters as the synchronous endpoint.

FieldTypeDefaultDescription
fileFileโ€”PDF file (required) โ€” up to 20MB
use_ocrboolfalseSet to true to run OCR on scanned / image-based pages

Response

Success Response

{
  "success": true,
  "job_id": "8f3a6b2c9d1e4a5f",
  "status": "queued",
  "message": "Document conversion started. Use the job ID to check status."
}

Code Examples

Python

import requests

url = "https://api.chemhub.com/api/v1/pdf2word/convert/async"

headers = {
    "X-API-Key": "your_api_key",
    "X-API-Secret": "your_secret"
}

with open("document.pdf", "rb") as f:
    response = requests.post(url, headers=headers, files={"file": f}, data={"use_ocr": "false"})

result = response.json()
job_id = result.get("job_id")
print("Job ID:", job_id)

cURL

curl -X POST "https://api.chemhub.com/api/v1/pdf2word/convert/async" \
  -H "X-API-Key: your_api_key" \
  -H "X-API-Secret: your_secret" \
  -F "file=@document.pdf" \
  -F "use_ocr=false"

Get Job Status

GET/pdf2word/jobs/{job_id}

Poll the status of an asynchronous conversion job. Job statuses are queued, processing, done, and failed.

Path Parameters

FieldTypeDescription
job_idstringJob ID returned by the async submit endpoint (required)

Response

Success Response

{
  "success": true,
  "job_id": "8f3a6b2c9d1e4a5f",
  "status": "done",
  "filename": "document.pdf",
  "created_at": "2026-08-07 12:00:01",
  "updated_at": "2026-08-07 12:00:05",
  "result_url": "/api/v1/pdf2word/jobs/8f3a6b2c9d1e4a5f/download"
}
Ownership

Jobs are bound to the API key that created them. Accessing another key's job returns 403 Access denied.

Code Examples

Python

import requests

job_id = "8f3a6b2c9d1e4a5f"
url = f"https://api.chemhub.com/api/v1/pdf2word/jobs/{job_id}"

headers = {
    "X-API-Key": "your_api_key",
    "X-API-Secret": "your_secret"
}

res = requests.get(url, headers=headers)
print(res.json())

cURL

curl -X GET "https://api.chemhub.com/api/v1/pdf2word/jobs/8f3a6b2c9d1e4a5f" \
  -H "X-API-Key: your_api_key" \
  -H "X-API-Secret: your_secret"

Download Conversion Result

GET/pdf2word/jobs/{job_id}/download

Download the Word document produced by a completed async job.

Path Parameters

FieldTypeDescription
job_idstringJob ID of a completed (done) job (required)
Response

On success the endpoint returns the converted Word document as an attachment. If the job has not finished, it returns 400 Job not completed.

cURL Example

cURL

curl -X GET "https://api.chemhub.com/api/v1/pdf2word/jobs/8f3a6b2c9d1e4a5f/download" \
  -H "X-API-Key: your_api_key" \
  -H "X-API-Secret: your_secret" \
  --output converted.docx

Python SDK

Complete Python SDK covering health check, synchronous conversion, async job submission, polling, and download.

Complete SDK Class

import os
import requests

BASE_URL = "https://api.chemhub.com/api/v1"

# Your api key here
API_KEY = "your_api_key"
API_SECRET = "your_api_secret"

headers = {
    "X-API-Key": API_KEY,
    "X-API-Secret": API_SECRET
}

# --- Health Check ---
def check_health():
    return requests.get(f"{BASE_URL}/pdf2word/health", headers=headers).json()

# --- Synchronous conversion ---
def convert_sync(pdf_path, use_ocr=False):
    with open(pdf_path, "rb") as f:
        files = {"file": f}
        data = {"use_ocr": "true" if use_ocr else "false"}
        response = requests.post(
            f"{BASE_URL}/pdf2word/convert",
            headers=headers,
            files=files,
            data=data
        )
    if response.status_code == 200:
        output_path = pdf_path.rsplit(".", 1)[0] + ".docx"
        with open(output_path, "wb") as out:
            out.write(response.content)
        print(f"Saved: {output_path}")
        return output_path
    print(f"Error: {response.status_code} - {response.text}")
    return None

# --- Async conversion ---
def convert_async(pdf_path, use_ocr=False):
    with open(pdf_path, "rb") as f:
        files = {"file": f}
        data = {"use_ocr": "true" if use_ocr else "false"}
        response = requests.post(
            f"{BASE_URL}/pdf2word/convert/async",
            headers=headers,
            files=files,
            data=data
        )
    return response.json()

# --- Poll job status ---
def get_job_status(job_id):
    return requests.get(
        f"{BASE_URL}/pdf2word/jobs/{job_id}",
        headers=headers
    ).json()

# --- Download completed job ---
def download_job(job_id, output_path="converted.docx"):
    response = requests.get(
        f"{BASE_URL}/pdf2word/jobs/{job_id}/download",
        headers=headers
    )
    if response.status_code == 200:
        with open(output_path, "wb") as out:
            out.write(response.content)
        print(f"Downloaded: {output_path}")
    else:
        print(f"Error: {response.status_code} - {response.text}")

# --- Test all endpoints ---
if __name__ == "__main__":
    print("=== PDF TO WORD API TEST ===")

    health = check_health()
    print(f"Health: {health.get('status', 'unknown')}")

    # Replace with your own paths
    document_path = r"C:\path\to\your\document.pdf"
    output_path = r"C:\path\to\your\output\converted.docx"

    print("\nSubmitting PDF conversion job...")

    job = convert_async(document_path, use_ocr=False)

    job_id = job.get("job_id")

    if not job_id:
        print(f"Failed to submit job: {job}")
    else:
        print(f"Submitted job: {job_id}")

        print("\nWaiting for conversion to complete...")

        while True:
            status_response = get_job_status(job_id)
            status = status_response.get("status")

            print(f"Job status: {status}")

            if status == "done":
                print("\nConversion completed. Downloading Word document...")
                download_job(job_id, output_path)
                break

            if status == "failed":
                print(f"\nConversion failed: {status_response}")
                break

Errors & Status Codes

Error Response Format

Error Response

{
  "success": false,
  "error": "Invalid file",
  "message": "File too large. Max size is 20MB"
}

Status Codes

CodeMeaning
200Success
400Bad request / invalid parameters / unsupported file format
401Invalid or missing API key/secret
403Access denied (job belongs to another API key)
404Job not found or result unavailable
429Rate limit exceeded
500Internal server error / conversion failed

Limitations

Maximum file size: 20MB
Supported formats: PDF (.pdf) only
Rate limit: 15 requests per minute
Backends: pdfplumber, tesseract, ftfy, docx
OCR: Optional, enables text extraction from scanned PDFs