---
seo_title: Anything to PDF API — Any File to PDF | EnConvert
meta_desc: Convert Word, Excel, PowerPoint, HTML, Markdown, EPUB, and images to PDF with POST /v1/convert/anything-to-pdf — one REST API endpoint for any file to PDF.
keywords: anything to pdf api, convert any file to pdf api, docx to pdf api, word to pdf api, image to pdf api, html to pdf api, markdown to pdf api, convert documents to pdf rest api
---

# Anything to PDF API

The `POST /v1/convert/anything-to-pdf` endpoint converts almost any uploaded file — Word, Excel, PowerPoint, OpenDocument, Apple Pages and Numbers, HTML, Markdown, plain text, EPUB, images, and SVG — into a PDF. It auto-detects the format from the file you send, dispatches to the right rendering engine, and returns a single PDF. One endpoint replaces the whole per-format PDF stack: you upload a file, you get a PDF back, whatever the source type.

It is the single-call superset of the format-specific PDF endpoints ([html-to-pdf](/docs/endpoints/documents-to-pdf/html-to-pdf), doc-to-pdf, excel-to-pdf, and the rest) — reach for those when you already know the input type and want fine-grained page control, and reach for this one when the input could be anything. This endpoint is file-based only; to render a live web page to PDF, use [url-to-pdf](/docs/endpoints/web-pages/url-to-pdf). For the Markdown counterpart that turns any file into clean Markdown, see [anything-to-markdown](/docs/anything-to-markdown).

---

## Endpoint

```
POST /v1/convert/anything-to-pdf
```

**Content-Type:** `multipart/form-data`

**Output format:** PDF (`.pdf`, `application/pdf`). The input type is auto-detected from the uploaded filename's extension and its magic bytes — you do not specify an input format.

---

## Supported input formats

The input type is detected from the file extension (validated against the file's magic bytes). These are every format the endpoint accepts:

| Category | Formats | Extensions | Notes |
|----------|---------|------------|-------|
| Word | DOCX, DOC | `.docx`, `.doc` | Rendered through LibreOffice, preserving styles, tables, and layout. |
| Excel | XLSX, XLS | `.xlsx`, `.xls` | Spreadsheets rendered to paginated PDF via LibreOffice. |
| PowerPoint | PPTX, PPT | `.pptx`, `.ppt` | One PDF page per slide, via LibreOffice. |
| OpenDocument | ODT, ODS, ODP, OTS | `.odt`, `.ods`, `.odp`, `.ots` | Text, spreadsheet, presentation, and spreadsheet-template documents, via LibreOffice. |
| Apple iWork | Pages, Numbers | `.pages`, `.numbers` | Apple Pages and Numbers documents, via LibreOffice. |
| Rich text / data | RTF, CSV | `.rtf`, `.csv` | RTF documents and CSV tables rendered via LibreOffice. |
| Web / markup | HTML, XHTML | `.html`, `.htm`, `.xhtml` | Rendered with WeasyPrint, honouring the document's own CSS. |
| Markdown | Markdown | `.md`, `.markdown`, `.mdown`, `.mkd` | Rendered to a styled PDF with headings, tables, and fenced code. |
| Plain text | Text | `.txt`, `.text` | Rendered in a monospace layout that preserves whitespace. |
| E-books | EPUB | `.epub` | Chapters converted in reading (spine) order to a text PDF. |
| Images | PNG, JPEG, GIF, BMP, TIFF, WebP, HEIC | `.png`, `.jpg`, `.jpeg`, `.gif`, `.bmp`, `.tiff`, `.tif`, `.webp`, `.heic`, `.heif` | Each image becomes a single-page PDF; transparency is flattened onto white. |
| Vector | SVG | `.svg` | Rendered as vector (not rasterised) with CairoSVG. |
| PDF | PDF | `.pdf` | Accepted and returned as-is — useful for grayscale normalisation (see `pdf_options`). |

<div class="alert alert-info">
<strong>Note:</strong> Unlike the format-specific PDF endpoints, page geometry (custom page size, margins, orientation, headers, and footers) is <em>not</em> applied here, because the input format is auto-detected and each type is rendered by a different engine. Only <code>grayscale</code> is honoured on this endpoint. For full page control, send HTML or Markdown to <a href="/docs/endpoints/documents-to-pdf/html-to-pdf">html-to-pdf</a> or markdown-to-pdf instead. To convert a live URL to PDF, use <a href="/docs/endpoints/web-pages/url-to-pdf">url-to-pdf</a>.
</div>

---

## Authentication

This endpoint supports both private and public key authentication.

### Private Key

Include your secret key in the `X-API-Key` header. Use this for server-to-server calls where the key is never exposed to the client.

```
X-API-Key: sk_live_your_private_key
```

### Public Key with JWT

For client-side usage, first generate a JWT token with your public key, then pass it as a Bearer token.

**Step 1 -- Get a token:**

```
POST /v1/auth/token
X-API-Key: pk_live_your_public_key
```

**Step 2 -- Use the token:**

```
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
```

The full flow, including domain locking and token refresh, is in [the authentication guide](/docs/authentication). Each API key carries an allowed-endpoints allowlist — if `/v1/convert/anything-to-pdf` is not on the key's list, the request is rejected with `403`.

---

## Request Parameters

Send the file as `multipart/form-data`. The document goes in the `file` field; the rest are optional form fields.

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `file` | file | Yes | -- | The document, image, or markup file to convert. Its extension must be one of the supported input formats above. |
| `output_filename` | `string` | No | Input name | Custom name for the output file. The `.pdf` extension is added automatically. |
| `direct_download` | `boolean` | No | `true` | Accepted for request-shape parity with the other conversion endpoints. |
| `job_id` | `string` | No | -- | Client-provided job ID for timeout recovery. When a sync conversion exceeds reverse-proxy timeout limits, poll `GET /v1/convert/status/{job_id}` to retrieve the result. |
| `pdf_options` | `string` | No | `null` | JSON string of PDF options. Only `grayscale` is honoured on this endpoint — see below. |

### PDF Options

Pass as a JSON string in the `pdf_options` form field. Because the input format is auto-detected and each format is rendered by a different engine, only `grayscale` is applied uniformly here.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `grayscale` | `boolean` | `false` | Convert the output PDF to grayscale via Ghostscript post-processing. Applies to every input type, including an already-PDF upload. |

For a custom page size, margins, orientation, headers, or footers, convert HTML or Markdown through the format-specific [html-to-pdf](/docs/endpoints/documents-to-pdf/html-to-pdf) or markdown-to-pdf endpoints, which accept the full `pdf_options` schema.

---

## Response

The conversion runs in-process and the resulting `.pdf` file is stored, then the endpoint returns a JSON body with a pre-signed download URL:

```json
{
    "presigned_url": "https://spaces.example.com/...signed...",
    "object_key": "env/files/{project_id}/anything-to-pdf/report_20260714_101530123.pdf",
    "filename": "report_20260714_101530123.pdf",
    "file_size": 51240,
    "conversion_time_seconds": 2.1,
    "job_id": null
}
```

The same values are echoed in response headers (`X-Object-Key`, `X-File-Size`, `X-Conversion-Time`, `X-Filename`) so you can read them without parsing the body. Download the PDF from `presigned_url` — the link is short-lived.

---

## How each format is converted

Every format is normalised into a PDF, so you get one consistent output regardless of the source type.

- **Word / Excel / PowerPoint** — Rendered with LibreOffice in headless mode, preserving styles, tables, and layout; presentations produce one page per slide. Legacy binary formats (`.doc`, `.xls`, `.ppt`) are handled by the same engine.
- **OpenDocument, Apple Pages / Numbers, RTF, CSV** — Also rendered through LibreOffice, so ODF documents, iWork exports, rich text, and CSV tables all paginate cleanly.
- **HTML / XHTML** — Rendered with WeasyPrint, which honours the document's own CSS. External resources referenced by URL may not resolve — inline your CSS and base64-encode images for best results.
- **Markdown** — Converted to HTML (headings, GitHub-Flavored tables, fenced code) and rendered with WeasyPrint into a clean, styled PDF.
- **Plain text** — Rendered in a monospace layout that preserves whitespace and wraps long lines, so logs and code stay readable.
- **EPUB** — Content documents are read in spine (reading) order and rendered chapter by chapter into a text PDF; the navigation document is skipped.
- **Images (PNG, JPEG, GIF, BMP, TIFF, WebP, HEIC)** — Each image becomes a single-page PDF via Pillow. Transparency is flattened onto a white background, and only the first frame of a multi-frame image (animated GIF, multi-page TIFF) is used.
- **SVG** — Rendered as true vector graphics with CairoSVG, so the result stays crisp at any zoom.
- **PDF** — An uploaded PDF is validated and returned unchanged, which makes this endpoint a convenient way to grayscale-normalise an existing PDF.

---

## Output format

The result is a standard PDF (`application/pdf`):

- **Documents** keep their pagination, headings, tables, and styling from the source rendering engine.
- **Images** produce a single page sized to the image; **SVG** stays vector.
- **Grayscale** — when `pdf_options.grayscale` is `true`, the finished PDF is desaturated via a Ghostscript post-processing pass.

If you need clean Markdown instead of a PDF — for example to feed an LLM or RAG pipeline — send the same file to [anything-to-markdown](/docs/anything-to-markdown) or [the ingest endpoint](/docs/v2-ingest) instead.

---

## Supported formats by endpoint

The file-upload endpoints share the same format auto-detection but target different outputs. This endpoint (`anything-to-pdf`) accepts the widest set — all 36 formats below. [`anything-to-markdown`](/docs/anything-to-markdown) and [`/v2/ingest`](/docs/v2-ingest) accept the same 22 document formats as each other (images, SVG, and the Apple/OTS formats are PDF-only), and `/v2/ingest` additionally accepts web sources — a URL list, a sitemap, or a crawl — not just files.

| Category | Extensions | anything-to-pdf | anything-to-markdown | /v2/ingest |
|----------|------------|:---:|:---:|:---:|
| PDF | `.pdf` | ✓ | ✓ | ✓ |
| Word | `.docx`, `.doc` | ✓ | ✓ | ✓ |
| Excel | `.xlsx`, `.xls` | ✓ | ✓ | ✓ |
| PowerPoint | `.pptx`, `.ppt` | ✓ | ✓ | ✓ |
| CSV | `.csv` | ✓ | ✓ | ✓ |
| Rich text | `.rtf` | ✓ | ✓ | ✓ |
| OpenDocument | `.odt`, `.ods`, `.odp` | ✓ | ✓ | ✓ |
| ODF template | `.ots` | ✓ | — | — |
| Apple iWork | `.pages`, `.numbers` | ✓ | — | — |
| Web / markup | `.html`, `.htm`, `.xhtml` | ✓ | ✓ | ✓ |
| Markdown / text | `.md`, `.markdown`, `.mdown`, `.mkd`, `.txt`, `.text` | ✓ | ✓ | ✓ |
| E-books | `.epub` | ✓ | ✓ | ✓ |
| Images | `.png`, `.jpg`, `.jpeg`, `.gif`, `.bmp`, `.tiff`, `.tif`, `.webp`, `.heic`, `.heif` | ✓ | — | — |
| Vector | `.svg` | ✓ | — | — |

A ✓ means the endpoint accepts that format as a file upload; a — means it does not. Images and SVG convert to PDF here but are rejected by the Markdown-output endpoints (image OCR is a separate pipeline). Per-file size limits are plan-dependent (Free: 5 MB) across all three endpoints.

---

## Code Examples

### curl (Private Key)

```bash
curl -X POST https://api.enconvert.com/v1/convert/anything-to-pdf \
  -H "X-API-Key: sk_live_your_private_key" \
  -F "file=@quarterly-report.docx"
```

### Python (Private Key)

```python
import requests

with open("quarterly-report.docx", "rb") as f:
    response = requests.post(
        "https://api.enconvert.com/v1/convert/anything-to-pdf",
        headers={"X-API-Key": "sk_live_your_private_key"},
        files={"file": ("quarterly-report.docx", f)},
    )

response.raise_for_status()
result = response.json()

# Download the PDF from the pre-signed URL.
pdf = requests.get(result["presigned_url"]).content
with open("quarterly-report.pdf", "wb") as out:
    out.write(pdf)
```

### Node.js (Private Key)

```javascript
import { readFile, writeFile } from "node:fs/promises";

const form = new FormData();
form.append(
    "file",
    new Blob([await readFile("quarterly-report.docx")]),
    "quarterly-report.docx"
);

const response = await fetch(
    "https://api.enconvert.com/v1/convert/anything-to-pdf",
    { method: "POST", headers: { "X-API-Key": "sk_live_your_private_key" }, body: form }
);

const result = await response.json();
const pdf = await fetch(result.presigned_url).then((r) => r.arrayBuffer());
await writeFile("quarterly-report.pdf", Buffer.from(pdf));
```

### PHP (Private Key)

```php
$ch = curl_init("https://api.enconvert.com/v1/convert/anything-to-pdf");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ["X-API-Key: sk_live_your_private_key"],
    CURLOPT_POSTFIELDS => [
        "file" => new CURLFile("quarterly-report.docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "quarterly-report.docx"),
    ],
]);

$data = json_decode(curl_exec($ch), true);
curl_close($ch);

echo $data["presigned_url"];
```

---

## Error Responses

| Status | Condition |
|--------|-----------|
| `400 Bad Request` | Unsupported file type, an empty file, or a corrupt/unreadable document (e.g. an invalid image or a malformed EPUB). |
| `400 Bad Request` | The file's bytes do not match its declared extension (magic-byte mismatch). |
| `400 Bad Request` | Invalid `pdf_options` JSON. |
| `401 Unauthorized` | Missing or invalid API key / JWT token. |
| `402 Payment Required` | Monthly conversion limit or storage limit reached. |
| `403 Forbidden` | `/v1/convert/anything-to-pdf` is not in the API key's allowed endpoints. |
| `413 Payload Too Large` | The upload exceeds your plan's per-file size limit. |
| `500 Internal Server Error` | Conversion failed unexpectedly. |

The full status-code reference is in [the error-codes guide](/docs/error-codes).

---

## Limits

| Limit | Value |
|-------|-------|
| Maximum upload size | Plan-dependent (Free: 5 MB) |
| Monthly conversions | Plan-dependent (Free: 100) |
| File retention | Plan-dependent (Free: 1 hour) |
| Page geometry options | Not applied on this endpoint (only `grayscale`) |
| Supported input formats | See the [supported input formats](#supported-input-formats) table |

---

## Frequently asked questions

### How do I convert any file to PDF with an API?

Send a `POST` request to `/v1/convert/anything-to-pdf` as `multipart/form-data` with your file in the `file` field and your key in the `X-API-Key` header. The endpoint auto-detects the format, renders it to PDF, and returns JSON with a `presigned_url` to the finished `.pdf`. You do not need to tell it the input type — the extension and magic bytes decide.

### Which file formats can I convert to PDF?

Word (`.docx`, `.doc`), Excel (`.xlsx`, `.xls`), PowerPoint (`.pptx`, `.ppt`), OpenDocument (`.odt`, `.ods`, `.odp`, `.ots`), Apple Pages and Numbers, RTF, CSV, HTML/XHTML, Markdown, plain text, EPUB, images (`.png`, `.jpg`, `.jpeg`, `.gif`, `.bmp`, `.tiff`, `.webp`, `.heic`), and SVG. An existing PDF is accepted and returned as-is. The full list with per-format notes is in the [supported input formats](#supported-input-formats) table.

### Can I convert Word, Excel, or PowerPoint to PDF via the API?

Yes. Office documents — modern (`.docx`, `.xlsx`, `.pptx`) and legacy (`.doc`, `.xls`, `.ppt`) — are rendered with LibreOffice, preserving styles, tables, and layout, with one page per slide for presentations. Upload the file and you get the PDF back.

### How do I convert an image such as PNG, JPEG, or HEIC to PDF?

Upload it to the same endpoint. Each image becomes a single-page PDF, with transparency flattened onto a white background; iPhone `.heic`/`.heif` photos and `.svg` vectors are supported too. For a multi-frame image (animated GIF or multi-page TIFF), the first frame is used.

### Can I set a custom page size, margins, or headers on the PDF?

Not on this endpoint — only `grayscale` is honoured, because the input format is auto-detected and each type uses a different rendering engine. For full page control (page size, margins, orientation, headers, footers), send HTML or Markdown to the [html-to-pdf](/docs/endpoints/documents-to-pdf/html-to-pdf) or markdown-to-pdf endpoints, which accept the complete `pdf_options` schema.

### How is this different from the doc-to-pdf or html-to-pdf endpoints?

The format-specific endpoints each accept one input type and expose full page-geometry options; `anything-to-pdf` accepts them all behind a single call and auto-detects the format, which is ideal when the input could be anything. Use a specific endpoint when you know the type and want page control; use this one when you want a single upload path for many formats.
