# File Conversion API — convert and process files: PDF tools, image convert/optimize, document-to-markdown (for RAG), OCR, Office-to-PDF, audio extraction and data-format conversion

> Extract text from a PDF (per page). mode=layout preserves visual alignment (pdfplumber); mode=plain is fastest. Flags likely-scanned PDFs.
> ReefAPI engine `file-convert` · 31 endpoints · clean JSON, no scraping or browsers to manage.

## How to call
- **Endpoint:** `POST https://api.reefapi.com/file-convert/v1/<action>` with a JSON body.
- **Auth:** header `x-api-key: <YOUR_REEFAPI_KEY>` — create one free (1,000 credits, no card): https://reefapi.com/signup
- **Response (every call):** `{ ok: boolean, data: ..., meta: { record_count, credits, ... }, error: { code, message } }` — branch on `ok`. Failed or blocked calls are free.
- **One key + one shared credit pool** across every ReefAPI API. Per-call credits are listed on each endpoint below.
- **Use it from an AI agent (MCP):** connect `https://api.reefapi.com/mcp` (remote streamable-http, `Authorization: Bearer <key>`) and your assistant can call these actions directly.

## Endpoints

### POST /file-convert/v1/pdf_extract_text — 1 credit
Extract text from a PDF (per page). mode=layout preserves visual alignment (pdfplumber); mode=plain is fastest. Flags likely-scanned PDFs.

**Parameters:**
- `file_b64` (string, optional) — The input file as base64 (data-URI prefix tolerated). Max 25MB. Provide file_b64 OR file_url. Multipart upload also works: POST the file as the 'file' form field.
- `file_url` (string, optional) — https URL of the input file — fetched server-side through the proxy pool; private/internal/metadata addresses are SSRF-blocked. Max 25MB.
- `filename` (string, optional) — Optional original filename — used only as a hint (e.g. .md detection); the real format is always sniffed from magic bytes.
- `password` (string, optional) — Password for encrypted PDFs. Without it an encrypted input fails cleanly with INVALID_PARAM (we never crack/bypass).
- `pages` (string, optional) — Page selection, 1-based: '1-3,5,9-' (open ranges OK). Default: all pages.
- `mode` (enum, optional, default "plain") — plain = reading-order text; layout = whitespace-aligned text (tables stay readable). [one of: plain, layout]

**Returns:** pages[] (page, text), page_count, pages_extracted, characters, empty_pages, likely_scanned (true ⇒ use ocr_pdf), stop_reason

**Example request body:**
```json
{
  "file_b64": "JVBERi0xLjQKMSAwIG9iajw8L1R5cGUvQ2F0YWxvZy9QYWdlcyAyIDAgUj4+ZW5kb2JqCjIgMCBvYmo8PC9UeXBlL1BhZ2VzL0tpZHNbMyAwIFJdL0NvdW50IDE+PmVuZG9iagozIDAgb2JqPDwvVHlwZS9QYWdlL1BhcmVudCAyIDAgUi9NZWRpYUJveFswIDAgNjEyIDc5Ml0vQ29udGVudHMgNCAwIFIvUmVzb3VyY2VzPDwvRm9udDw8L0YxIDUgMCBSPj4+Pj4+ZW5kb2JqCjQgMCBvYmo8PC9MZW5ndGggNTQ+PnN0cmVhbQpCVCAvRjEgMTggVGYgNzIgNzIwIFRkIChSZWVmQVBJIGdvbGRlbiB0ZXN0IFBERikgVGogRVQKZW5kc3RyZWFtZW5kb2JqCjUgMCBvYmo8PC9UeXBlL0ZvbnQvU3VidHlwZS9UeXBlMS9CYXNlRm9udC9IZWx2ZXRpY2E+PmVuZG9iagp4cmVmCjAgNgowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDAwMDkgMDAwMDAgbiAKMDAwMDAwMDA1MiAwMDAwMCBuIAowMDAwMDAwMTAxIDAwMDAwIG4gCjAwMDAwMDAyMTEgMDAwMDAgbiAKMDAwMDAwMDMxMCAwMDAwMCBuIAp0cmFpbGVyPDwvU2l6ZSA2L1Jvb3QgMSAwIFI+PgpzdGFydHhyZWYKMzcxCiUlRU9GCg=="
}
```

### POST /file-convert/v1/pdf_metadata — 1 credit
PDF document properties: title/author/dates/producer, page count & size, encryption flag, AcroForm field count.

**Parameters:**
- `file_b64` (string, optional) — The input file as base64 (data-URI prefix tolerated). Max 25MB. Provide file_b64 OR file_url. Multipart upload also works: POST the file as the 'file' form field.
- `file_url` (string, optional) — https URL of the input file — fetched server-side through the proxy pool; private/internal/metadata addresses are SSRF-blocked. Max 25MB.
- `filename` (string, optional) — Optional original filename — used only as a hint (e.g. .md detection); the real format is always sniffed from magic bytes.
- `password` (string, optional) — Password for encrypted PDFs. Without it an encrypted input fails cleanly with INVALID_PARAM (we never crack/bypass).

**Returns:** encrypted, page_count, title, author, subject, creator, producer, creation_date, modification_date, page_size_points, has_form, form_field_count

**Example request body:**
```json
{
  "file_b64": "JVBERi0xLjQKMSAwIG9iajw8L1R5cGUvQ2F0YWxvZy9QYWdlcyAyIDAgUj4+ZW5kb2JqCjIgMCBvYmo8PC9UeXBlL1BhZ2VzL0tpZHNbMyAwIFJdL0NvdW50IDE+PmVuZG9iagozIDAgb2JqPDwvVHlwZS9QYWdlL1BhcmVudCAyIDAgUi9NZWRpYUJveFswIDAgNjEyIDc5Ml0vQ29udGVudHMgNCAwIFIvUmVzb3VyY2VzPDwvRm9udDw8L0YxIDUgMCBSPj4+Pj4+ZW5kb2JqCjQgMCBvYmo8PC9MZW5ndGggNTQ+PnN0cmVhbQpCVCAvRjEgMTggVGYgNzIgNzIwIFRkIChSZWVmQVBJIGdvbGRlbiB0ZXN0IFBERikgVGogRVQKZW5kc3RyZWFtZW5kb2JqCjUgMCBvYmo8PC9UeXBlL0ZvbnQvU3VidHlwZS9UeXBlMS9CYXNlRm9udC9IZWx2ZXRpY2E+PmVuZG9iagp4cmVmCjAgNgowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDAwMDkgMDAwMDAgbiAKMDAwMDAwMDA1MiAwMDAwMCBuIAowMDAwMDAwMTAxIDAwMDAwIG4gCjAwMDAwMDAyMTEgMDAwMDAgbiAKMDAwMDAwMDMxMCAwMDAwMCBuIAp0cmFpbGVyPDwvU2l6ZSA2L1Jvb3QgMSAwIFI+PgpzdGFydHhyZWYKMzcxCiUlRU9GCg=="
}
```

### POST /file-convert/v1/pdf_merge — 1 credit
Merge 2-20 PDFs into one (input order preserved). Output delivery: each produced file ≤10MB comes inline as base64 (files[].file_b64); 10-50MB comes as a one-time download token (files[].download_path, 30min TTL); >50MB total is rejected.

**Parameters:**
- `files_b64` (array, optional) — Array of base64 files (max 20 total inputs). Combine freely with file_urls; base64 entries come first in the processing order.
- `file_urls` (array, optional) — Array of https URLs (each SSRF-guarded and fetched server-side).
- `password` (string, optional) — Password for encrypted PDFs. Without it an encrypted input fails cleanly with INVALID_PARAM (we never crack/bypass).

**Returns:** input_files, page_count, files[] (merged.pdf)

**Example request body:**
```json
{
  "files_b64": [
    "JVBERi0xLjQKMSAwIG9iajw8L1R5cGUvQ2F0YWxvZy9QYWdlcyAyIDAgUj4+ZW5kb2JqCjIgMCBvYmo8PC9UeXBlL1BhZ2VzL0tpZHNbMyAwIFJdL0NvdW50IDE+PmVuZG9iagozIDAgb2JqPDwvVHlwZS9QYWdlL1BhcmVudCAyIDAgUi9NZWRpYUJveFswIDAgNjEyIDc5Ml0vQ29udGVudHMgNCAwIFIvUmVzb3VyY2VzPDwvRm9udDw8L0YxIDUgMCBSPj4+Pj4+ZW5kb2JqCjQgMCBvYmo8PC9MZW5ndGggNTQ+PnN0cmVhbQpCVCAvRjEgMTggVGYgNzIgNzIwIFRkIChSZWVmQVBJIGdvbGRlbiB0ZXN0IFBERikgVGogRVQKZW5kc3RyZWFtZW5kb2JqCjUgMCBvYmo8PC9UeXBlL0ZvbnQvU3VidHlwZS9UeXBlMS9CYXNlRm9udC9IZWx2ZXRpY2E+PmVuZG9iagp4cmVmCjAgNgowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDAwMDkgMDAwMDAgbiAKMDAwMDAwMDA1MiAwMDAwMCBuIAowMDAwMDAwMTAxIDAwMDAwIG4gCjAwMDAwMDAyMTEgMDAwMDAgbiAKMDAwMDAwMDMxMCAwMDAwMCBuIAp0cmFpbGVyPDwvU2l6ZSA2L1Jvb3QgMSAwIFI+PgpzdGFydHhyZWYKMzcxCiUlRU9GCg==",
    "JVBERi0xLjQKMSAwIG9iajw8L1R5cGUvQ2F0YWxvZy9QYWdlcyAyIDAgUj4+ZW5kb2JqCjIgMCBvYmo8PC9UeXBlL1BhZ2VzL0tpZHNbMyAwIFJdL0NvdW50IDE+PmVuZG9iagozIDAgb2JqPDwvVHlwZS9QYWdlL1BhcmVudCAyIDAgUi9NZWRpYUJveFswIDAgNjEyIDc5Ml0vQ29udGVudHMgNCAwIFIvUmVzb3VyY2VzPDwvRm9udDw8L0YxIDUgMCBSPj4+Pj4+ZW5kb2JqCjQgMCBvYmo8PC9MZW5ndGggNTQ+PnN0cmVhbQpCVCAvRjEgMTggVGYgNzIgNzIwIFRkIChSZWVmQVBJIGdvbGRlbiB0ZXN0IFBERikgVGogRVQKZW5kc3RyZWFtZW5kb2JqCjUgMCBvYmo8PC9UeXBlL0ZvbnQvU3VidHlwZS9UeXBlMS9CYXNlRm9udC9IZWx2ZXRpY2E+PmVuZG9iagp4cmVmCjAgNgowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDAwMDkgMDAwMDAgbiAKMDAwMDAwMDA1MiAwMDAwMCBuIAowMDAwMDAwMTAxIDAwMDAwIG4gCjAwMDAwMDAyMTEgMDAwMDAgbiAKMDAwMDAwMDMxMCAwMDAwMCBuIAp0cmFpbGVyPDwvU2l6ZSA2L1Jvb3QgMSAwIFI+PgpzdGFydHhyZWYKMzcxCiUlRU9GCg=="
  ]
}
```

### POST /file-convert/v1/pdf_split — 1 credit
Split a PDF: pages='2-5,8' extracts those pages into one PDF; chunk_size=N splits the whole document into N-page parts (max 100 parts). Output delivery: each produced file ≤10MB comes inline as base64 (files[].file_b64); 10-50MB comes as a one-time download token (files[].download_path, 30min TTL); >50MB total is rejected.

**Parameters:**
- `file_b64` (string, optional) — The input file as base64 (data-URI prefix tolerated). Max 25MB. Provide file_b64 OR file_url. Multipart upload also works: POST the file as the 'file' form field.
- `file_url` (string, optional) — https URL of the input file — fetched server-side through the proxy pool; private/internal/metadata addresses are SSRF-blocked. Max 25MB.
- `filename` (string, optional) — Optional original filename — used only as a hint (e.g. .md detection); the real format is always sniffed from magic bytes.
- `password` (string, optional) — Password for encrypted PDFs. Without it an encrypted input fails cleanly with INVALID_PARAM (we never crack/bypass).
- `pages` (string, optional) — Pages to EXTRACT into a single PDF (mutually exclusive with chunk_size).
- `chunk_size` (integer, optional) — Split into parts of N pages each (1 = one PDF per page). Ignored when 'pages' is given.

**Returns:** page_count, parts, files[] (part_NNN.pdf or extracted.pdf)

**Example request body:**
```json
{
  "file_b64": "JVBERi0xLjQKMSAwIG9iajw8L1R5cGUvQ2F0YWxvZy9QYWdlcyAyIDAgUj4+ZW5kb2JqCjIgMCBvYmo8PC9UeXBlL1BhZ2VzL0tpZHNbMyAwIFJdL0NvdW50IDE+PmVuZG9iagozIDAgb2JqPDwvVHlwZS9QYWdlL1BhcmVudCAyIDAgUi9NZWRpYUJveFswIDAgNjEyIDc5Ml0vQ29udGVudHMgNCAwIFIvUmVzb3VyY2VzPDwvRm9udDw8L0YxIDUgMCBSPj4+Pj4+ZW5kb2JqCjQgMCBvYmo8PC9MZW5ndGggNTQ+PnN0cmVhbQpCVCAvRjEgMTggVGYgNzIgNzIwIFRkIChSZWVmQVBJIGdvbGRlbiB0ZXN0IFBERikgVGogRVQKZW5kc3RyZWFtZW5kb2JqCjUgMCBvYmo8PC9UeXBlL0ZvbnQvU3VidHlwZS9UeXBlMS9CYXNlRm9udC9IZWx2ZXRpY2E+PmVuZG9iagp4cmVmCjAgNgowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDAwMDkgMDAwMDAgbiAKMDAwMDAwMDA1MiAwMDAwMCBuIAowMDAwMDAwMTAxIDAwMDAwIG4gCjAwMDAwMDAyMTEgMDAwMDAgbiAKMDAwMDAwMDMxMCAwMDAwMCBuIAp0cmFpbGVyPDwvU2l6ZSA2L1Jvb3QgMSAwIFI+PgpzdGFydHhyZWYKMzcxCiUlRU9GCg==",
  "chunk_size": 1
}
```

### POST /file-convert/v1/pdf_rotate — 1 credit
Rotate pages clockwise by 90/180/270° (all pages or a range). Output delivery: each produced file ≤10MB comes inline as base64 (files[].file_b64); 10-50MB comes as a one-time download token (files[].download_path, 30min TTL); >50MB total is rejected.

**Parameters:**
- `file_b64` (string, optional) — The input file as base64 (data-URI prefix tolerated). Max 25MB. Provide file_b64 OR file_url. Multipart upload also works: POST the file as the 'file' form field.
- `file_url` (string, optional) — https URL of the input file — fetched server-side through the proxy pool; private/internal/metadata addresses are SSRF-blocked. Max 25MB.
- `filename` (string, optional) — Optional original filename — used only as a hint (e.g. .md detection); the real format is always sniffed from magic bytes.
- `password` (string, optional) — Password for encrypted PDFs. Without it an encrypted input fails cleanly with INVALID_PARAM (we never crack/bypass).
- `pages` (string, optional) — Page selection, 1-based: '1-3,5,9-' (open ranges OK). Default: all pages.
- `angle` (enum, optional, default 90) — Clockwise rotation angle. [one of: 90, 180, 270]

**Returns:** page_count, rotated_pages, angle, files[] (rotated.pdf)

**Example request body:**
```json
{
  "file_b64": "JVBERi0xLjQKMSAwIG9iajw8L1R5cGUvQ2F0YWxvZy9QYWdlcyAyIDAgUj4+ZW5kb2JqCjIgMCBvYmo8PC9UeXBlL1BhZ2VzL0tpZHNbMyAwIFJdL0NvdW50IDE+PmVuZG9iagozIDAgb2JqPDwvVHlwZS9QYWdlL1BhcmVudCAyIDAgUi9NZWRpYUJveFswIDAgNjEyIDc5Ml0vQ29udGVudHMgNCAwIFIvUmVzb3VyY2VzPDwvRm9udDw8L0YxIDUgMCBSPj4+Pj4+ZW5kb2JqCjQgMCBvYmo8PC9MZW5ndGggNTQ+PnN0cmVhbQpCVCAvRjEgMTggVGYgNzIgNzIwIFRkIChSZWVmQVBJIGdvbGRlbiB0ZXN0IFBERikgVGogRVQKZW5kc3RyZWFtZW5kb2JqCjUgMCBvYmo8PC9UeXBlL0ZvbnQvU3VidHlwZS9UeXBlMS9CYXNlRm9udC9IZWx2ZXRpY2E+PmVuZG9iagp4cmVmCjAgNgowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDAwMDkgMDAwMDAgbiAKMDAwMDAwMDA1MiAwMDAwMCBuIAowMDAwMDAwMTAxIDAwMDAwIG4gCjAwMDAwMDAyMTEgMDAwMDAgbiAKMDAwMDAwMDMxMCAwMDAwMCBuIAp0cmFpbGVyPDwvU2l6ZSA2L1Jvb3QgMSAwIFI+PgpzdGFydHhyZWYKMzcxCiUlRU9GCg==",
  "angle": 90
}
```

### POST /file-convert/v1/pdf_to_images — 1 credit
Render PDF pages to PNG/JPG/WebP (pypdfium2). Max 20 pages per call, dpi ≤ 300. Output delivery: each produced file ≤10MB comes inline as base64 (files[].file_b64); 10-50MB comes as a one-time download token (files[].download_path, 30min TTL); >50MB total is rejected.

**Parameters:**
- `file_b64` (string, optional) — The input file as base64 (data-URI prefix tolerated). Max 25MB. Provide file_b64 OR file_url. Multipart upload also works: POST the file as the 'file' form field.
- `file_url` (string, optional) — https URL of the input file — fetched server-side through the proxy pool; private/internal/metadata addresses are SSRF-blocked. Max 25MB.
- `filename` (string, optional) — Optional original filename — used only as a hint (e.g. .md detection); the real format is always sniffed from magic bytes.
- `password` (string, optional) — Password for encrypted PDFs. Without it an encrypted input fails cleanly with INVALID_PARAM (we never crack/bypass).
- `pages` (string, optional) — Page selection, 1-based: '1-3,5,9-' (open ranges OK). Default: all pages.
- `to` (enum, optional, default "png") — Image format for the rendered pages (alias: format). [one of: png, jpg, webp]
- `dpi` (integer, optional, default 150) — Render resolution (36-300).

**Returns:** page_count, rendered, dpi, stop_reason, files[] (page_NNN.png, each with width/height)

**Example request body:**
```json
{
  "file_b64": "JVBERi0xLjQKMSAwIG9iajw8L1R5cGUvQ2F0YWxvZy9QYWdlcyAyIDAgUj4+ZW5kb2JqCjIgMCBvYmo8PC9UeXBlL1BhZ2VzL0tpZHNbMyAwIFJdL0NvdW50IDE+PmVuZG9iagozIDAgb2JqPDwvVHlwZS9QYWdlL1BhcmVudCAyIDAgUi9NZWRpYUJveFswIDAgNjEyIDc5Ml0vQ29udGVudHMgNCAwIFIvUmVzb3VyY2VzPDwvRm9udDw8L0YxIDUgMCBSPj4+Pj4+ZW5kb2JqCjQgMCBvYmo8PC9MZW5ndGggNTQ+PnN0cmVhbQpCVCAvRjEgMTggVGYgNzIgNzIwIFRkIChSZWVmQVBJIGdvbGRlbiB0ZXN0IFBERikgVGogRVQKZW5kc3RyZWFtZW5kb2JqCjUgMCBvYmo8PC9UeXBlL0ZvbnQvU3VidHlwZS9UeXBlMS9CYXNlRm9udC9IZWx2ZXRpY2E+PmVuZG9iagp4cmVmCjAgNgowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDAwMDkgMDAwMDAgbiAKMDAwMDAwMDA1MiAwMDAwMCBuIAowMDAwMDAwMTAxIDAwMDAwIG4gCjAwMDAwMDAyMTEgMDAwMDAgbiAKMDAwMDAwMDMxMCAwMDAwMCBuIAp0cmFpbGVyPDwvU2l6ZSA2L1Jvb3QgMSAwIFI+PgpzdGFydHhyZWYKMzcxCiUlRU9GCg==",
  "dpi": 72
}
```

### POST /file-convert/v1/images_to_pdf — 2 credits
Combine 1-20 images into a single PDF (one page per image; page_size=a4/letter centers each image on a standard page). Output delivery: each produced file ≤10MB comes inline as base64 (files[].file_b64); 10-50MB comes as a one-time download token (files[].download_path, 30min TTL); >50MB total is rejected.

**Parameters:**
- `files_b64` (array, optional) — Array of base64 files (max 20 total inputs). Combine freely with file_urls; base64 entries come first in the processing order.
- `file_urls` (array, optional) — Array of https URLs (each SSRF-guarded and fetched server-side).
- `file_b64` (string, optional) — Single image as base64 (or use files_b64).
- `file_url` (string, optional) — https URL of the input file — fetched server-side through the proxy pool; private/internal/metadata addresses are SSRF-blocked. Max 25MB.
- `page_size` (enum, optional, default "auto") — auto = page matches each image; a4/letter = white page, image fitted+centred. [one of: auto, a4, letter]

**Returns:** image_count, page_size, files[] (images.pdf)

**Example request body:**
```json
{
  "files_b64": [
    "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAIAAABvFaqvAAAAH0lEQVR42mN4l+VFFcQwatCoQaMGjRo0atCoQQNvEAB6hKyuf+L5NQAAAABJRU5ErkJggg=="
  ]
}
```

### POST /file-convert/v1/pdf_watermark — 1 credit
Stamp a text or image watermark over pages (true alpha overlay; diagonal or centred). Output delivery: each produced file ≤10MB comes inline as base64 (files[].file_b64); 10-50MB comes as a one-time download token (files[].download_path, 30min TTL); >50MB total is rejected.

**Parameters:**
- `file_b64` (string, optional) — The input file as base64 (data-URI prefix tolerated). Max 25MB. Provide file_b64 OR file_url. Multipart upload also works: POST the file as the 'file' form field.
- `file_url` (string, optional) — https URL of the input file — fetched server-side through the proxy pool; private/internal/metadata addresses are SSRF-blocked. Max 25MB.
- `filename` (string, optional) — Optional original filename — used only as a hint (e.g. .md detection); the real format is always sniffed from magic bytes.
- `password` (string, optional) — Password for encrypted PDFs. Without it an encrypted input fails cleanly with INVALID_PARAM (we never crack/bypass).
- `pages` (string, optional) — Page selection, 1-based: '1-3,5,9-' (open ranges OK). Default: all pages.
- `text` (string, optional) — Watermark text (UTF-8, DejaVu font). Provide text OR image_b64/image_url.
- `image_b64` (string, optional) — Watermark image as base64 (PNG with alpha recommended; scaled to ~40% page width).
- `image_url` (string, optional) — Watermark image URL (SSRF-guarded fetch).
- `opacity` (number, optional, default 0.25) — Watermark opacity 0.02-1.0.
- `position` (enum, optional, default "diagonal") — Text placement. [one of: diagonal, center]
- `color` (enum, optional, default "gray") — Text colour. [one of: gray, red, black, blue]
- `font_size` (integer, optional) — Text size in pixels at 2× page scale (default: auto ≈ page/10).

**Returns:** page_count, watermarked_pages, kind (text|image), files[] (watermarked.pdf)

**Example request body:**
```json
{
  "file_b64": "JVBERi0xLjQKMSAwIG9iajw8L1R5cGUvQ2F0YWxvZy9QYWdlcyAyIDAgUj4+ZW5kb2JqCjIgMCBvYmo8PC9UeXBlL1BhZ2VzL0tpZHNbMyAwIFJdL0NvdW50IDE+PmVuZG9iagozIDAgb2JqPDwvVHlwZS9QYWdlL1BhcmVudCAyIDAgUi9NZWRpYUJveFswIDAgNjEyIDc5Ml0vQ29udGVudHMgNCAwIFIvUmVzb3VyY2VzPDwvRm9udDw8L0YxIDUgMCBSPj4+Pj4+ZW5kb2JqCjQgMCBvYmo8PC9MZW5ndGggNTQ+PnN0cmVhbQpCVCAvRjEgMTggVGYgNzIgNzIwIFRkIChSZWVmQVBJIGdvbGRlbiB0ZXN0IFBERikgVGogRVQKZW5kc3RyZWFtZW5kb2JqCjUgMCBvYmo8PC9UeXBlL0ZvbnQvU3VidHlwZS9UeXBlMS9CYXNlRm9udC9IZWx2ZXRpY2E+PmVuZG9iagp4cmVmCjAgNgowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDAwMDkgMDAwMDAgbiAKMDAwMDAwMDA1MiAwMDAwMCBuIAowMDAwMDAwMTAxIDAwMDAwIG4gCjAwMDAwMDAyMTEgMDAwMDAgbiAKMDAwMDAwMDMxMCAwMDAwMCBuIAp0cmFpbGVyPDwvU2l6ZSA2L1Jvb3QgMSAwIFI+PgpzdGFydHhyZWYKMzcxCiUlRU9GCg==",
  "text": "CANARY"
}
```

### POST /file-convert/v1/pdf_fill_form — 1 credit
AcroForm filling. Without 'fields' → lists the form fields (discovery). With 'fields' → fills and returns the PDF (NeedAppearances set). Output delivery: each produced file ≤10MB comes inline as base64 (files[].file_b64); 10-50MB comes as a one-time download token (files[].download_path, 30min TTL); >50MB total is rejected.

**Parameters:**
- `file_b64` (string, optional) — The input file as base64 (data-URI prefix tolerated). Max 25MB. Provide file_b64 OR file_url. Multipart upload also works: POST the file as the 'file' form field.
- `file_url` (string, optional) — https URL of the input file — fetched server-side through the proxy pool; private/internal/metadata addresses are SSRF-blocked. Max 25MB.
- `filename` (string, optional) — Optional original filename — used only as a hint (e.g. .md detection); the real format is always sniffed from magic bytes.
- `password` (string, optional) — Password for encrypted PDFs. Without it an encrypted input fails cleanly with INVALID_PARAM (we never crack/bypass).
- `fields` (object, optional) — {field_name: value} map. Checkbox values are usually /Yes — run discovery mode first.

**Returns:** mode (list|fill), has_form, field_count, fields[]/fields_filled, fields_unknown[], files[] (filled.pdf, fill mode only)

**Example request body:**
```json
{
  "file_b64": "JVBERi0xLjQKMSAwIG9iajw8L1R5cGUvQ2F0YWxvZy9QYWdlcyAyIDAgUj4+ZW5kb2JqCjIgMCBvYmo8PC9UeXBlL1BhZ2VzL0tpZHNbMyAwIFJdL0NvdW50IDE+PmVuZG9iagozIDAgb2JqPDwvVHlwZS9QYWdlL1BhcmVudCAyIDAgUi9NZWRpYUJveFswIDAgNjEyIDc5Ml0vQ29udGVudHMgNCAwIFIvUmVzb3VyY2VzPDwvRm9udDw8L0YxIDUgMCBSPj4+Pj4+ZW5kb2JqCjQgMCBvYmo8PC9MZW5ndGggNTQ+PnN0cmVhbQpCVCAvRjEgMTggVGYgNzIgNzIwIFRkIChSZWVmQVBJIGdvbGRlbiB0ZXN0IFBERikgVGogRVQKZW5kc3RyZWFtZW5kb2JqCjUgMCBvYmo8PC9UeXBlL0ZvbnQvU3VidHlwZS9UeXBlMS9CYXNlRm9udC9IZWx2ZXRpY2E+PmVuZG9iagp4cmVmCjAgNgowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDAwMDkgMDAwMDAgbiAKMDAwMDAwMDA1MiAwMDAwMCBuIAowMDAwMDAwMTAxIDAwMDAwIG4gCjAwMDAwMDAyMTEgMDAwMDAgbiAKMDAwMDAwMDMxMCAwMDAwMCBuIAp0cmFpbGVyPDwvU2l6ZSA2L1Jvb3QgMSAwIFI+PgpzdGFydHhyZWYKMzcxCiUlRU9GCg=="
}
```

### POST /file-convert/v1/pdf_redact — 1 credit
TRUE redaction: target pages are re-rendered with the matches blacked out and REBUILT — original text/fonts/layers destroyed, then verified by re-extraction (output withheld if any remnant). Redacted pages lose selectable text. Find by 'terms' and/or explicit 'areas'. Output delivery: each produced file ≤10MB comes inline as base64 (files[].file_b64); 10-50MB comes as a one-time download token (files[].download_path, 30min TTL); >50MB total is rejected.

**Parameters:**
- `file_b64` (string, optional) — The input file as base64 (data-URI prefix tolerated). Max 25MB. Provide file_b64 OR file_url. Multipart upload also works: POST the file as the 'file' form field.
- `file_url` (string, optional) — https URL of the input file — fetched server-side through the proxy pool; private/internal/metadata addresses are SSRF-blocked. Max 25MB.
- `filename` (string, optional) — Optional original filename — used only as a hint (e.g. .md detection); the real format is always sniffed from magic bytes.
- `password` (string, optional) — Password for encrypted PDFs. Without it an encrypted input fails cleanly with INVALID_PARAM (we never crack/bypass).
- `terms` (array, optional) — Text terms to find & redact (case-insensitive, matched across words on a line).
- `areas` (array, optional) — Explicit boxes: {page, x0, y0, x1, y1} in PDF points, origin TOP-left.
- `dpi` (integer, optional, default 200) — Rebuild resolution for redacted pages.

**Returns:** page_count, redacted_pages, pages[], matches, verified_removed (always true on success), method, files[] (redacted.pdf)

**Example request body:**
```json
{
  "file_b64": "JVBERi0xLjQKMSAwIG9iajw8L1R5cGUvQ2F0YWxvZy9QYWdlcyAyIDAgUj4+ZW5kb2JqCjIgMCBvYmo8PC9UeXBlL1BhZ2VzL0tpZHNbMyAwIFJdL0NvdW50IDE+PmVuZG9iagozIDAgb2JqPDwvVHlwZS9QYWdlL1BhcmVudCAyIDAgUi9NZWRpYUJveFswIDAgNjEyIDc5Ml0vQ29udGVudHMgNCAwIFIvUmVzb3VyY2VzPDwvRm9udDw8L0YxIDUgMCBSPj4+Pj4+ZW5kb2JqCjQgMCBvYmo8PC9MZW5ndGggNTQ+PnN0cmVhbQpCVCAvRjEgMTggVGYgNzIgNzIwIFRkIChSZWVmQVBJIGdvbGRlbiB0ZXN0IFBERikgVGogRVQKZW5kc3RyZWFtZW5kb2JqCjUgMCBvYmo8PC9UeXBlL0ZvbnQvU3VidHlwZS9UeXBlMS9CYXNlRm9udC9IZWx2ZXRpY2E+PmVuZG9iagp4cmVmCjAgNgowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDAwMDkgMDAwMDAgbiAKMDAwMDAwMDA1MiAwMDAwMCBuIAowMDAwMDAwMTAxIDAwMDAwIG4gCjAwMDAwMDAyMTEgMDAwMDAgbiAKMDAwMDAwMDMxMCAwMDAwMCBuIAp0cmFpbGVyPDwvU2l6ZSA2L1Jvb3QgMSAwIFI+PgpzdGFydHhyZWYKMzcxCiUlRU9GCg==",
  "terms": [
    "golden"
  ]
}
```

### POST /file-convert/v1/pdf_compress — 1 credit
Shrink a PDF: stream recompression + embedded-image re-encode (level=low/balanced/strong; strong also caps image resolution). Output delivery: each produced file ≤10MB comes inline as base64 (files[].file_b64); 10-50MB comes as a one-time download token (files[].download_path, 30min TTL); >50MB total is rejected.

**Parameters:**
- `file_b64` (string, optional) — The input file as base64 (data-URI prefix tolerated). Max 25MB. Provide file_b64 OR file_url. Multipart upload also works: POST the file as the 'file' form field.
- `file_url` (string, optional) — https URL of the input file — fetched server-side through the proxy pool; private/internal/metadata addresses are SSRF-blocked. Max 25MB.
- `filename` (string, optional) — Optional original filename — used only as a hint (e.g. .md detection); the real format is always sniffed from magic bytes.
- `password` (string, optional) — Password for encrypted PDFs. Without it an encrypted input fails cleanly with INVALID_PARAM (we never crack/bypass).
- `level` (enum, optional, default "balanced") — Compression aggressiveness. [one of: low, balanced, strong]

**Returns:** bytes_before, bytes_after, saved_pct, images_recoded, level, files[] (compressed.pdf)

**Example request body:**
```json
{
  "file_b64": "JVBERi0xLjQKMSAwIG9iajw8L1R5cGUvQ2F0YWxvZy9QYWdlcyAyIDAgUj4+ZW5kb2JqCjIgMCBvYmo8PC9UeXBlL1BhZ2VzL0tpZHNbMyAwIFJdL0NvdW50IDE+PmVuZG9iagozIDAgb2JqPDwvVHlwZS9QYWdlL1BhcmVudCAyIDAgUi9NZWRpYUJveFswIDAgNjEyIDc5Ml0vQ29udGVudHMgNCAwIFIvUmVzb3VyY2VzPDwvRm9udDw8L0YxIDUgMCBSPj4+Pj4+ZW5kb2JqCjQgMCBvYmo8PC9MZW5ndGggNTQ+PnN0cmVhbQpCVCAvRjEgMTggVGYgNzIgNzIwIFRkIChSZWVmQVBJIGdvbGRlbiB0ZXN0IFBERikgVGogRVQKZW5kc3RyZWFtZW5kb2JqCjUgMCBvYmo8PC9UeXBlL0ZvbnQvU3VidHlwZS9UeXBlMS9CYXNlRm9udC9IZWx2ZXRpY2E+PmVuZG9iagp4cmVmCjAgNgowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDAwMDkgMDAwMDAgbiAKMDAwMDAwMDA1MiAwMDAwMCBuIAowMDAwMDAwMTAxIDAwMDAwIG4gCjAwMDAwMDAyMTEgMDAwMDAgbiAKMDAwMDAwMDMxMCAwMDAwMCBuIAp0cmFpbGVyPDwvU2l6ZSA2L1Jvb3QgMSAwIFI+PgpzdGFydHhyZWYKMzcxCiUlRU9GCg=="
}
```

### POST /file-convert/v1/pdf_protect — 1 credit
Encrypt a PDF with AES-256 (user password to open; optional owner password). Output delivery: each produced file ≤10MB comes inline as base64 (files[].file_b64); 10-50MB comes as a one-time download token (files[].download_path, 30min TTL); >50MB total is rejected.

**Parameters:**
- `file_b64` (string, optional) — The input file as base64 (data-URI prefix tolerated). Max 25MB. Provide file_b64 OR file_url. Multipart upload also works: POST the file as the 'file' form field.
- `file_url` (string, optional) — https URL of the input file — fetched server-side through the proxy pool; private/internal/metadata addresses are SSRF-blocked. Max 25MB.
- `filename` (string, optional) — Optional original filename — used only as a hint (e.g. .md detection); the real format is always sniffed from magic bytes.
- `password` (string, optional) — Password for encrypted PDFs. Without it an encrypted input fails cleanly with INVALID_PARAM (we never crack/bypass).
- `user_password` (string, required) — Password required to OPEN the PDF (min 4 chars).
- `owner_password` (string, optional) — Optional owner/permissions password (defaults to the user password.

**Returns:** page_count, algorithm (AES-256), files[] (protected.pdf)

**Example request body:**
```json
{
  "file_b64": "JVBERi0xLjQKMSAwIG9iajw8L1R5cGUvQ2F0YWxvZy9QYWdlcyAyIDAgUj4+ZW5kb2JqCjIgMCBvYmo8PC9UeXBlL1BhZ2VzL0tpZHNbMyAwIFJdL0NvdW50IDE+PmVuZG9iagozIDAgb2JqPDwvVHlwZS9QYWdlL1BhcmVudCAyIDAgUi9NZWRpYUJveFswIDAgNjEyIDc5Ml0vQ29udGVudHMgNCAwIFIvUmVzb3VyY2VzPDwvRm9udDw8L0YxIDUgMCBSPj4+Pj4+ZW5kb2JqCjQgMCBvYmo8PC9MZW5ndGggNTQ+PnN0cmVhbQpCVCAvRjEgMTggVGYgNzIgNzIwIFRkIChSZWVmQVBJIGdvbGRlbiB0ZXN0IFBERikgVGogRVQKZW5kc3RyZWFtZW5kb2JqCjUgMCBvYmo8PC9UeXBlL0ZvbnQvU3VidHlwZS9UeXBlMS9CYXNlRm9udC9IZWx2ZXRpY2E+PmVuZG9iagp4cmVmCjAgNgowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDAwMDkgMDAwMDAgbiAKMDAwMDAwMDA1MiAwMDAwMCBuIAowMDAwMDAwMTAxIDAwMDAwIG4gCjAwMDAwMDAyMTEgMDAwMDAgbiAKMDAwMDAwMDMxMCAwMDAwMCBuIAp0cmFpbGVyPDwvU2l6ZSA2L1Jvb3QgMSAwIFI+PgpzdGFydHhyZWYKMzcxCiUlRU9GCg==",
  "user_password": "canary123"
}
```

### POST /file-convert/v1/pdf_unlock — 1 credit
Remove encryption from a PDF — REQUIRES the correct password (we never crack or bypass protection). Output delivery: each produced file ≤10MB comes inline as base64 (files[].file_b64); 10-50MB comes as a one-time download token (files[].download_path, 30min TTL); >50MB total is rejected.

**Parameters:**
- `file_b64` (string, optional) — The input file as base64 (data-URI prefix tolerated). Max 25MB. Provide file_b64 OR file_url. Multipart upload also works: POST the file as the 'file' form field.
- `file_url` (string, optional) — https URL of the input file — fetched server-side through the proxy pool; private/internal/metadata addresses are SSRF-blocked. Max 25MB.
- `filename` (string, optional) — Optional original filename — used only as a hint (e.g. .md detection); the real format is always sniffed from magic bytes.
- `password` (string, required) — The PDF's legitimate password.

**Returns:** page_count, was_encrypted, files[] (unlocked.pdf)

**Example request body:**
```json
{
  "file_b64": "JVBERi0xLjQKMSAwIG9iajw8L1R5cGUvQ2F0YWxvZy9QYWdlcyAyIDAgUj4+ZW5kb2JqCjIgMCBvYmo8PC9UeXBlL1BhZ2VzL0tpZHNbMyAwIFJdL0NvdW50IDE+PmVuZG9iagozIDAgb2JqPDwvVHlwZS9QYWdlL1BhcmVudCAyIDAgUi9NZWRpYUJveFswIDAgNjEyIDc5Ml0vQ29udGVudHMgNCAwIFIvUmVzb3VyY2VzPDwvRm9udDw8L0YxIDUgMCBSPj4+Pj4+ZW5kb2JqCjQgMCBvYmo8PC9MZW5ndGggNTQ+PnN0cmVhbQpCVCAvRjEgMTggVGYgNzIgNzIwIFRkIChSZWVmQVBJIGdvbGRlbiB0ZXN0IFBERikgVGogRVQKZW5kc3RyZWFtZW5kb2JqCjUgMCBvYmo8PC9UeXBlL0ZvbnQvU3VidHlwZS9UeXBlMS9CYXNlRm9udC9IZWx2ZXRpY2E+PmVuZG9iagp4cmVmCjAgNgowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDAwMDkgMDAwMDAgbiAKMDAwMDAwMDA1MiAwMDAwMCBuIAowMDAwMDAwMTAxIDAwMDAwIG4gCjAwMDAwMDAyMTEgMDAwMDAgbiAKMDAwMDAwMDMxMCAwMDAwMCBuIAp0cmFpbGVyPDwvU2l6ZSA2L1Jvb3QgMSAwIFI+PgpzdGFydHhyZWYKMzcxCiUlRU9GCg==",
  "password": "x"
}
```

### POST /file-convert/v1/pdf_repair — 1 credit
Best-effort structural repair (broken xref/trailer/stream lengths) via a tolerant qpdf parse + clean rewrite. Output delivery: each produced file ≤10MB comes inline as base64 (files[].file_b64); 10-50MB comes as a one-time download token (files[].download_path, 30min TTL); >50MB total is rejected.

**Parameters:**
- `file_b64` (string, optional) — The input file as base64 (data-URI prefix tolerated). Max 25MB. Provide file_b64 OR file_url. Multipart upload also works: POST the file as the 'file' form field.
- `file_url` (string, optional) — https URL of the input file — fetched server-side through the proxy pool; private/internal/metadata addresses are SSRF-blocked. Max 25MB.
- `filename` (string, optional) — Optional original filename — used only as a hint (e.g. .md detection); the real format is always sniffed from magic bytes.
- `password` (string, optional) — Password for encrypted PDFs. Without it an encrypted input fails cleanly with INVALID_PARAM (we never crack/bypass).

**Returns:** page_count, readable_after_repair, note, files[] (repaired.pdf)

**Example request body:**
```json
{
  "file_b64": "JVBERi0xLjQKMSAwIG9iajw8L1R5cGUvQ2F0YWxvZy9QYWdlcyAyIDAgUj4+ZW5kb2JqCjIgMCBvYmo8PC9UeXBlL1BhZ2VzL0tpZHNbMyAwIFJdL0NvdW50IDE+PmVuZG9iagozIDAgb2JqPDwvVHlwZS9QYWdlL1BhcmVudCAyIDAgUi9NZWRpYUJveFswIDAgNjEyIDc5Ml0vQ29udGVudHMgNCAwIFIvUmVzb3VyY2VzPDwvRm9udDw8L0YxIDUgMCBSPj4+Pj4+ZW5kb2JqCjQgMCBvYmo8PC9MZW5ndGggNTQ+PnN0cmVhbQpCVCAvRjEgMTggVGYgNzIgNzIwIFRkIChSZWVmQVBJIGdvbGRlbiB0ZXN0IFBERikgVGogRVQKZW5kc3RyZWFtZW5kb2JqCjUgMCBvYmo8PC9UeXBlL0ZvbnQvU3VidHlwZS9UeXBlMS9CYXNlRm9udC9IZWx2ZXRpY2E+PmVuZG9iagp4cmVmCjAgNgowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDAwMDkgMDAwMDAgbiAKMDAwMDAwMDA1MiAwMDAwMCBuIAowMDAwMDAwMTAxIDAwMDAwIG4gCjAwMDAwMDAyMTEgMDAwMDAgbiAKMDAwMDAwMDMxMCAwMDAwMCBuIAp0cmFpbGVyPDwvU2l6ZSA2L1Jvb3QgMSAwIFI+PgpzdGFydHhyZWYKMzcxCiUlRU9GCg=="
}
```

### POST /file-convert/v1/image_convert — 1 credit
Convert between raster formats (jpg/png/webp/tiff/bmp/gif/avif; animated gif/webp preserved where the target supports it). Output delivery: each produced file ≤10MB comes inline as base64 (files[].file_b64); 10-50MB comes as a one-time download token (files[].download_path, 30min TTL); >50MB total is rejected.

**Parameters:**
- `file_b64` (string, optional) — The input file as base64 (data-URI prefix tolerated). Max 25MB. Provide file_b64 OR file_url. Multipart upload also works: POST the file as the 'file' form field.
- `file_url` (string, optional) — https URL of the input file — fetched server-side through the proxy pool; private/internal/metadata addresses are SSRF-blocked. Max 25MB.
- `filename` (string, optional) — Optional original filename — used only as a hint (e.g. .md detection); the real format is always sniffed from magic bytes.
- `to` (enum, required) — Target format: jpg, png, webp, tiff, bmp, gif, avif. [one of: jpg, png, webp, tiff, bmp, gif, avif]
- `quality` (integer, optional, default 85) — Encode quality 1-100 (jpg/webp/avif).

**Returns:** from, to, width, height, frames, files[]

**Example request body:**
```json
{
  "file_b64": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAIAAABvFaqvAAAAH0lEQVR42mN4l+VFFcQwatCoQaMGjRo0atCoQQNvEAB6hKyuf+L5NQAAAABJRU5ErkJggg==",
  "to": "webp"
}
```

### POST /file-convert/v1/image_resize — 1 credit
Resize with fit=contain (aspect kept, fits inside box) / cover (fills+crops) / stretch. No upscaling unless upscale=true. Output delivery: each produced file ≤10MB comes inline as base64 (files[].file_b64); 10-50MB comes as a one-time download token (files[].download_path, 30min TTL); >50MB total is rejected.

**Parameters:**
- `file_b64` (string, optional) — The input file as base64 (data-URI prefix tolerated). Max 25MB. Provide file_b64 OR file_url. Multipart upload also works: POST the file as the 'file' form field.
- `file_url` (string, optional) — https URL of the input file — fetched server-side through the proxy pool; private/internal/metadata addresses are SSRF-blocked. Max 25MB.
- `filename` (string, optional) — Optional original filename — used only as a hint (e.g. .md detection); the real format is always sniffed from magic bytes.
- `width` (integer, optional) — Target width px (give width and/or height).
- `height` (integer, optional) — Target height px.
- `fit` (enum, optional, default "contain") — Resize strategy. [one of: contain, cover, stretch]
- `upscale` (boolean, optional, default false) — Allow enlarging beyond the source size.
- `to` (enum, optional) — Optional output format (default: keep source). [one of: jpg, png, webp, tiff, bmp, gif, avif]
- `quality` (integer, optional, default 85) — Encode quality 1-100 (jpg/webp/avif).

**Returns:** from_size, to_size, fit, files[]

**Example request body:**
```json
{
  "file_b64": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAIAAABvFaqvAAAAH0lEQVR42mN4l+VFFcQwatCoQaMGjRo0atCoQQNvEAB6hKyuf+L5NQAAAABJRU5ErkJggg==",
  "width": 64
}
```

### POST /file-convert/v1/image_optimize — 1 credit
Smart perceptual compression (TinyPNG-style): binary-searches the lowest quality whose decoded result stays visually equal to the source, per a per-channel error budget (effort=low/balanced/strong). Optionally convert to webp/avif while optimizing. Never returns a bigger file. Output delivery: each produced file ≤10MB comes inline as base64 (files[].file_b64); 10-50MB comes as a one-time download token (files[].download_path, 30min TTL); >50MB total is rejected.

**Parameters:**
- `file_b64` (string, optional) — The input file as base64 (data-URI prefix tolerated). Max 25MB. Provide file_b64 OR file_url. Multipart upload also works: POST the file as the 'file' form field.
- `file_url` (string, optional) — https URL of the input file — fetched server-side through the proxy pool; private/internal/metadata addresses are SSRF-blocked. Max 25MB.
- `filename` (string, optional) — Optional original filename — used only as a hint (e.g. .md detection); the real format is always sniffed from magic bytes.
- `to` (enum, optional, default "auto") — auto = keep format (exotic sources → webp). [one of: auto, jpg, png, webp, avif]
- `effort` (enum, optional, default "balanced") — How much visual error to allow. [one of: low, balanced, strong]

**Returns:** from, to, bytes_before, bytes_after, saved_pct, quality, method, files[]

**Example request body:**
```json
{
  "file_b64": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAIAAABvFaqvAAAAH0lEQVR42mN4l+VFFcQwatCoQaMGjRo0atCoQQNvEAB6hKyuf+L5NQAAAABJRU5ErkJggg=="
}
```

### POST /file-convert/v1/image_thumbnail — 1 credit
Fast thumbnail (16-2048px box; square=true centre-crops to a square). Output delivery: each produced file ≤10MB comes inline as base64 (files[].file_b64); 10-50MB comes as a one-time download token (files[].download_path, 30min TTL); >50MB total is rejected.

**Parameters:**
- `file_b64` (string, optional) — The input file as base64 (data-URI prefix tolerated). Max 25MB. Provide file_b64 OR file_url. Multipart upload also works: POST the file as the 'file' form field.
- `file_url` (string, optional) — https URL of the input file — fetched server-side through the proxy pool; private/internal/metadata addresses are SSRF-blocked. Max 25MB.
- `filename` (string, optional) — Optional original filename — used only as a hint (e.g. .md detection); the real format is always sniffed from magic bytes.
- `size` (integer, optional, default 256) — Bounding-box size in px.
- `square` (boolean, optional, default false) — Centre-crop to square.
- `to` (enum, optional, default "webp") — Thumbnail format. [one of: webp, jpg, png]

**Returns:** from_size, to_size, files[] (thumb.webp)

**Example request body:**
```json
{
  "file_b64": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAIAAABvFaqvAAAAH0lEQVR42mN4l+VFFcQwatCoQaMGjRo0atCoQQNvEAB6hKyuf+L5NQAAAABJRU5ErkJggg==",
  "size": 64
}
```

### POST /file-convert/v1/image_metadata — 1 credit
Read image facts + EXIF (+GPS) — and with strip=true return a copy with ALL metadata removed (EXIF/GPS/XMP/ICC).

**Parameters:**
- `file_b64` (string, optional) — The input file as base64 (data-URI prefix tolerated). Max 25MB. Provide file_b64 OR file_url. Multipart upload also works: POST the file as the 'file' form field.
- `file_url` (string, optional) — https URL of the input file — fetched server-side through the proxy pool; private/internal/metadata addresses are SSRF-blocked. Max 25MB.
- `filename` (string, optional) — Optional original filename — used only as a hint (e.g. .md detection); the real format is always sniffed from magic bytes.
- `strip` (boolean, optional, default false) — Also return a metadata-stripped copy.

**Returns:** format, mode, width, height, frames, bytes, exif{}, gps{}, has_gps, stripped, files[] (stripped.jpg/png when strip=true)

**Example request body:**
```json
{
  "file_b64": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAIAAABvFaqvAAAAH0lEQVR42mN4l+VFFcQwatCoQaMGjRo0atCoQQNvEAB6hKyuf+L5NQAAAABJRU5ErkJggg=="
}
```

### POST /file-convert/v1/image_rotate — 1 credit
Rotate (90/180/270 clockwise) and/or flip (horizontal/vertical). Output delivery: each produced file ≤10MB comes inline as base64 (files[].file_b64); 10-50MB comes as a one-time download token (files[].download_path, 30min TTL); >50MB total is rejected.

**Parameters:**
- `file_b64` (string, optional) — The input file as base64 (data-URI prefix tolerated). Max 25MB. Provide file_b64 OR file_url. Multipart upload also works: POST the file as the 'file' form field.
- `file_url` (string, optional) — https URL of the input file — fetched server-side through the proxy pool; private/internal/metadata addresses are SSRF-blocked. Max 25MB.
- `filename` (string, optional) — Optional original filename — used only as a hint (e.g. .md detection); the real format is always sniffed from magic bytes.
- `angle` (enum, optional, default 0) — Clockwise rotation. [one of: 0, 90, 180, 270]
- `flip` (enum, optional) — Optional mirror. [one of: horizontal, vertical]

**Returns:** angle, flip, size, files[]

**Example request body:**
```json
{
  "file_b64": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAIAAABvFaqvAAAAH0lEQVR42mN4l+VFFcQwatCoQaMGjRo0atCoQQNvEAB6hKyuf+L5NQAAAABJRU5ErkJggg==",
  "angle": 90
}
```

### POST /file-convert/v1/image_crop — 1 credit
Crop a pixel box (x, y from top-left + width × height). Output delivery: each produced file ≤10MB comes inline as base64 (files[].file_b64); 10-50MB comes as a one-time download token (files[].download_path, 30min TTL); >50MB total is rejected.

**Parameters:**
- `file_b64` (string, optional) — The input file as base64 (data-URI prefix tolerated). Max 25MB. Provide file_b64 OR file_url. Multipart upload also works: POST the file as the 'file' form field.
- `file_url` (string, optional) — https URL of the input file — fetched server-side through the proxy pool; private/internal/metadata addresses are SSRF-blocked. Max 25MB.
- `filename` (string, optional) — Optional original filename — used only as a hint (e.g. .md detection); the real format is always sniffed from magic bytes.
- `x` (integer, optional, default 0) — Left edge px.
- `y` (integer, optional, default 0) — Top edge px.
- `width` (integer, required) — Crop width px.
- `height` (integer, required) — Crop height px.

**Returns:** from_size, box, files[]

**Example request body:**
```json
{
  "file_b64": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAIAAABvFaqvAAAAH0lEQVR42mN4l+VFFcQwatCoQaMGjRo0atCoQQNvEAB6hKyuf+L5NQAAAABJRU5ErkJggg==",
  "width": 8,
  "height": 8
}
```

### POST /file-convert/v1/doc_to_markdown — 4 credits
Document → clean markdown for RAG/agents. PDF uses a layout engine (headings from font sizes, real pipe-tables, reading order); docx/pptx/xlsx/html via MarkItDown. mode=fast trades structure for speed. Output delivery: each produced file ≤10MB comes inline as base64 (files[].file_b64); 10-50MB comes as a one-time download token (files[].download_path, 30min TTL); >50MB total is rejected.

**Parameters:**
- `file_b64` (string, optional) — The input file as base64 (data-URI prefix tolerated). Max 25MB. Provide file_b64 OR file_url. Multipart upload also works: POST the file as the 'file' form field.
- `file_url` (string, optional) — https URL of the input file — fetched server-side through the proxy pool; private/internal/metadata addresses are SSRF-blocked. Max 25MB.
- `filename` (string, optional) — Optional original filename — used only as a hint (e.g. .md detection); the real format is always sniffed from magic bytes.
- `password` (string, optional) — Password for encrypted PDFs. Without it an encrypted input fails cleanly with INVALID_PARAM (we never crack/bypass).
- `pages` (string, optional) — Page selection, 1-based: '1-3,5,9-' (open ranges OK). Default: all pages.
- `mode` (enum, optional, default "layout") — PDF only: layout = headings+tables; fast = plain text spine. [one of: layout, fast]

**Returns:** markdown_preview (first 2000 chars), characters, page_count, tables, likely_scanned, files[] (document.md — full markdown)

**Example request body:**
```json
{
  "file_b64": "PCFET0NUWVBFIGh0bWw+PGh0bWw+PGhlYWQ+PG1ldGEgY2hhcnNldD0ndXRmLTgnPjx0aXRsZT5Hb2xkZW48L3RpdGxlPjwvaGVhZD48Ym9keT48aDE+UmVlZkFQSSBnb2xkZW4gdGVzdCBwYWdlPC9oMT48cD5BIHRpbnkgZG9jdW1lbnQgZm9yIGNhbmFyeSBydW5zLjwvcD48dGFibGU+PHRyPjx0aD5lbmdpbmU8L3RoPjx0aD50aWVyPC90aD48L3RyPjx0cj48dGQ+ZmlsZS1jb252ZXJ0PC90ZD48dGQ+dXRpbGl0aWVzPC90ZD48L3RyPjx0cj48dGQ+d2ViLWV4dHJhY3Q8L3RkPjx0ZD5kYXRhPC90ZD48L3RyPjwvdGFibGU+PC9ib2R5PjwvaHRtbD4="
}
```

### POST /file-convert/v1/extract_tables — 3 credits
Pull every table out of a PDF / xlsx / docx / html as JSON rows (+optional CSV files). Max 50 tables.

**Parameters:**
- `file_b64` (string, optional) — The input file as base64 (data-URI prefix tolerated). Max 25MB. Provide file_b64 OR file_url. Multipart upload also works: POST the file as the 'file' form field.
- `file_url` (string, optional) — https URL of the input file — fetched server-side through the proxy pool; private/internal/metadata addresses are SSRF-blocked. Max 25MB.
- `filename` (string, optional) — Optional original filename — used only as a hint (e.g. .md detection); the real format is always sniffed from magic bytes.
- `password` (string, optional) — Password for encrypted PDFs. Without it an encrypted input fails cleanly with INVALID_PARAM (we never crack/bypass).
- `pages` (string, optional) — Page selection, 1-based: '1-3,5,9-' (open ranges OK). Default: all pages.
- `as_csv` (boolean, optional, default false) — Also return each table as a CSV file.

**Returns:** table_count, tables[] (source, rows, columns, data[][]), stop_reason, files[] (table_N.csv when as_csv)

**Example request body:**
```json
{
  "file_b64": "PCFET0NUWVBFIGh0bWw+PGh0bWw+PGhlYWQ+PG1ldGEgY2hhcnNldD0ndXRmLTgnPjx0aXRsZT5Hb2xkZW48L3RpdGxlPjwvaGVhZD48Ym9keT48aDE+UmVlZkFQSSBnb2xkZW4gdGVzdCBwYWdlPC9oMT48cD5BIHRpbnkgZG9jdW1lbnQgZm9yIGNhbmFyeSBydW5zLjwvcD48dGFibGU+PHRyPjx0aD5lbmdpbmU8L3RoPjx0aD50aWVyPC90aD48L3RyPjx0cj48dGQ+ZmlsZS1jb252ZXJ0PC90ZD48dGQ+dXRpbGl0aWVzPC90ZD48L3RyPjx0cj48dGQ+d2ViLWV4dHJhY3Q8L3RkPjx0ZD5kYXRhPC90ZD48L3RyPjwvdGFibGU+PC9ib2R5PjwvaHRtbD4="
}
```

### POST /file-convert/v1/ocr_image — 2 credits
OCR an image → text + word count + confidence (tesseract 5, printed text; languages: eng/deu/fra/spa/tur, combinable).

**Parameters:**
- `file_b64` (string, optional) — The input file as base64 (data-URI prefix tolerated). Max 25MB. Provide file_b64 OR file_url. Multipart upload also works: POST the file as the 'file' form field.
- `file_url` (string, optional) — https URL of the input file — fetched server-side through the proxy pool; private/internal/metadata addresses are SSRF-blocked. Max 25MB.
- `filename` (string, optional) — Optional original filename — used only as a hint (e.g. .md detection); the real format is always sniffed from magic bytes.
- `language` (array, optional, default "eng") — OCR language(s): eng, deu, fra, spa, tur — array or comma-joined.

**Returns:** text, words, mean_confidence (0-100), language, width, height, note

**Example request body:**
```json
{
  "file_b64": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAIAAABvFaqvAAAAH0lEQVR42mN4l+VFFcQwatCoQaMGjRo0atCoQQNvEAB6hKyuf+L5NQAAAABJRU5ErkJggg=="
}
```

### POST /file-convert/v1/ocr_pdf — 2 credits
OCR a scanned PDF: output=text → per-page text+confidence; output=searchable_pdf → image+invisible-text-layer PDF. OCR-light: max 10 pages per call (use 'pages' to window). Output delivery: each produced file ≤10MB comes inline as base64 (files[].file_b64); 10-50MB comes as a one-time download token (files[].download_path, 30min TTL); >50MB total is rejected.

**Parameters:**
- `file_b64` (string, optional) — The input file as base64 (data-URI prefix tolerated). Max 25MB. Provide file_b64 OR file_url. Multipart upload also works: POST the file as the 'file' form field.
- `file_url` (string, optional) — https URL of the input file — fetched server-side through the proxy pool; private/internal/metadata addresses are SSRF-blocked. Max 25MB.
- `filename` (string, optional) — Optional original filename — used only as a hint (e.g. .md detection); the real format is always sniffed from magic bytes.
- `password` (string, optional) — Password for encrypted PDFs. Without it an encrypted input fails cleanly with INVALID_PARAM (we never crack/bypass).
- `pages` (string, optional) — Page selection, 1-based: '1-3,5,9-' (open ranges OK). Default: all pages.
- `language` (array, optional, default "eng") — OCR language(s): eng, deu, fra, spa, tur.
- `output` (enum, optional, default "text") — Result kind. [one of: text, searchable_pdf]

**Returns:** page_count, pages_ocr, language, stop_reason; text mode: pages[] (page, text, words, mean_confidence), text, mean_confidence; searchable_pdf mode: files[] (searchable.pdf)

**Example request body:**
```json
{
  "file_b64": "JVBERi0xLjQKMSAwIG9iajw8L1R5cGUvQ2F0YWxvZy9QYWdlcyAyIDAgUj4+ZW5kb2JqCjIgMCBvYmo8PC9UeXBlL1BhZ2VzL0tpZHNbMyAwIFJdL0NvdW50IDE+PmVuZG9iagozIDAgb2JqPDwvVHlwZS9QYWdlL1BhcmVudCAyIDAgUi9NZWRpYUJveFswIDAgNjEyIDc5Ml0vQ29udGVudHMgNCAwIFIvUmVzb3VyY2VzPDwvRm9udDw8L0YxIDUgMCBSPj4+Pj4+ZW5kb2JqCjQgMCBvYmo8PC9MZW5ndGggNTQ+PnN0cmVhbQpCVCAvRjEgMTggVGYgNzIgNzIwIFRkIChSZWVmQVBJIGdvbGRlbiB0ZXN0IFBERikgVGogRVQKZW5kc3RyZWFtZW5kb2JqCjUgMCBvYmo8PC9UeXBlL0ZvbnQvU3VidHlwZS9UeXBlMS9CYXNlRm9udC9IZWx2ZXRpY2E+PmVuZG9iagp4cmVmCjAgNgowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDAwMDkgMDAwMDAgbiAKMDAwMDAwMDA1MiAwMDAwMCBuIAowMDAwMDAwMTAxIDAwMDAwIG4gCjAwMDAwMDAyMTEgMDAwMDAgbiAKMDAwMDAwMDMxMCAwMDAwMCBuIAp0cmFpbGVyPDwvU2l6ZSA2L1Jvb3QgMSAwIFI+PgpzdGFydHhyZWYKMzcxCiUlRU9GCg==",
  "pages": "1"
}
```

### POST /file-convert/v1/office_convert — 3 credits
Office → PDF (and html/txt; spreadsheets also → csv; text docs also → docx) via LibreOffice headless — docx/doc/odt/rtf/pptx/ppt/odp/xlsx/xls/ods/html/markdown/txt/csv in. Fonts: Noto (CJK/RTL) + Liberation (Arial/Times metrics). Output delivery: each produced file ≤10MB comes inline as base64 (files[].file_b64); 10-50MB comes as a one-time download token (files[].download_path, 30min TTL); >50MB total is rejected.

**Parameters:**
- `file_b64` (string, optional) — The input file as base64 (data-URI prefix tolerated). Max 25MB. Provide file_b64 OR file_url. Multipart upload also works: POST the file as the 'file' form field.
- `file_url` (string, optional) — https URL of the input file — fetched server-side through the proxy pool; private/internal/metadata addresses are SSRF-blocked. Max 25MB.
- `filename` (string, optional) — Optional original filename — used only as a hint (e.g. .md detection); the real format is always sniffed from magic bytes.
- `to` (enum, optional, default "pdf") — Target: pdf (default) | html | txt | csv (spreadsheets only) | docx (text documents only). [one of: pdf, html, txt, csv, docx]
- `from` (enum, optional) — Set from=md when sending markdown (it has no magic bytes; .md filename also works). [one of: md]

**Returns:** from, to, engine, files, fidelity_note, files[] (converted.pdf …)

**Example request body:**
```json
{
  "file_b64": "PCFET0NUWVBFIGh0bWw+PGh0bWw+PGhlYWQ+PG1ldGEgY2hhcnNldD0ndXRmLTgnPjx0aXRsZT5Hb2xkZW48L3RpdGxlPjwvaGVhZD48Ym9keT48aDE+UmVlZkFQSSBnb2xkZW4gdGVzdCBwYWdlPC9oMT48cD5BIHRpbnkgZG9jdW1lbnQgZm9yIGNhbmFyeSBydW5zLjwvcD48dGFibGU+PHRyPjx0aD5lbmdpbmU8L3RoPjx0aD50aWVyPC90aD48L3RyPjx0cj48dGQ+ZmlsZS1jb252ZXJ0PC90ZD48dGQ+dXRpbGl0aWVzPC90ZD48L3RyPjx0cj48dGQ+d2ViLWV4dHJhY3Q8L3RkPjx0ZD5kYXRhPC90ZD48L3RyPjwvdGFibGU+PC9ib2R5PjwvaHRtbD4=",
  "to": "pdf"
}
```

### POST /file-convert/v1/audio_extract — 2 credits
Extract the audio track from a video (mp4/webm/mkv/avi) → mp3 (default) / m4a / wav / flac / ogg / opus. Stream-copies losslessly when the codec already matches the target. NOT a video transcoder (phase-2). Output delivery: each produced file ≤10MB comes inline as base64 (files[].file_b64); 10-50MB comes as a one-time download token (files[].download_path, 30min TTL); >50MB total is rejected.

**Parameters:**
- `file_b64` (string, optional) — The input file as base64 (data-URI prefix tolerated). Max 25MB. Provide file_b64 OR file_url. Multipart upload also works: POST the file as the 'file' form field.
- `file_url` (string, optional) — https URL of the input file — fetched server-side through the proxy pool; private/internal/metadata addresses are SSRF-blocked. Max 25MB.
- `filename` (string, optional) — Optional original filename — used only as a hint (e.g. .md detection); the real format is always sniffed from magic bytes.
- `to` (enum, optional, default "mp3") — Audio output format. [one of: mp3, m4a, wav, flac, ogg, opus]
- `bitrate` (enum, optional) — Target bitrate (forces transcode; default 192k/encoder default). [one of: 64k, 96k, 128k, 160k, 192k, 256k, 320k]

**Returns:** from, to, method (stream-copy|transcode:enc), source_codec, duration_s, sample_rate, channels, files[] (audio.mp3)

**Example request body:**
```json
{
  "file_b64": "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"
}
```

### POST /file-convert/v1/audio_convert — 2 credits
Convert between audio formats (mp3/wav/flac/ogg/m4a in → mp3/m4a/wav/flac/ogg/opus out; ffmpeg LGPL build). Output delivery: each produced file ≤10MB comes inline as base64 (files[].file_b64); 10-50MB comes as a one-time download token (files[].download_path, 30min TTL); >50MB total is rejected.

**Parameters:**
- `file_b64` (string, optional) — The input file as base64 (data-URI prefix tolerated). Max 25MB. Provide file_b64 OR file_url. Multipart upload also works: POST the file as the 'file' form field.
- `file_url` (string, optional) — https URL of the input file — fetched server-side through the proxy pool; private/internal/metadata addresses are SSRF-blocked. Max 25MB.
- `filename` (string, optional) — Optional original filename — used only as a hint (e.g. .md detection); the real format is always sniffed from magic bytes.
- `to` (enum, required) — Target format: mp3, m4a, wav, flac, ogg, opus. [one of: mp3, m4a, wav, flac, ogg, opus]
- `bitrate` (enum, optional) — Target bitrate. [one of: 64k, 96k, 128k, 160k, 192k, 256k, 320k]

**Returns:** from, to, method, source_codec, duration_s, files[]

**Example request body:**
```json
{
  "file_b64": "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",
  "to": "mp3"
}
```

### POST /file-convert/v1/media_probe — 1 credit
ffprobe metadata for any audio/video file: container, duration, bitrate, per-stream codec/sample-rate/resolution, curated tags.

**Parameters:**
- `file_b64` (string, optional) — The input file as base64 (data-URI prefix tolerated). Max 25MB. Provide file_b64 OR file_url. Multipart upload also works: POST the file as the 'file' form field.
- `file_url` (string, optional) — https URL of the input file — fetched server-side through the proxy pool; private/internal/metadata addresses are SSRF-blocked. Max 25MB.
- `filename` (string, optional) — Optional original filename — used only as a hint (e.g. .md detection); the real format is always sniffed from magic bytes.

**Returns:** container, duration_s, bit_rate, size_bytes, stream_count, streams[] (type, codec, sample_rate/width/height…), tags{}

**Example request body:**
```json
{
  "file_b64": "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"
}
```

### POST /file-convert/v1/data_convert — 1 credit
Deterministic data-format conversion: CSV ↔ JSON ↔ XML ↔ YAML ↔ Excel(xlsx) (any direction; tabular targets need tabular-shaped input — clean error otherwise). 200k-row cap. Output delivery: each produced file ≤10MB comes inline as base64 (files[].file_b64); 10-50MB comes as a one-time download token (files[].download_path, 30min TTL); >50MB total is rejected.

**Parameters:**
- `file_b64` (string, optional) — The input file as base64 (data-URI prefix tolerated). Max 25MB. Provide file_b64 OR file_url. Multipart upload also works: POST the file as the 'file' form field.
- `file_url` (string, optional) — https URL of the input file — fetched server-side through the proxy pool; private/internal/metadata addresses are SSRF-blocked. Max 25MB.
- `filename` (string, optional) — Optional original filename — used only as a hint (e.g. .md detection); the real format is always sniffed from magic bytes.
- `to` (enum, required) — Target format: csv, json, xml, yaml, xlsx. [one of: csv, json, xml, yaml, xlsx]
- `from` (enum, optional) — Optional source override for ambiguous text (e.g. YAML without a leading ---); binary formats are always sniffed. [one of: csv, json, xml, yaml, xlsx]
- `delimiter` (string, optional) — CSV delimiter override (default: sniffed).
- `sheet` (string, optional) — Excel source: sheet name (default: first).

**Returns:** from, to, rows, files[] (converted.json …)

**Example request body:**
```json
{
  "file_b64": "bmFtZSxjcmVkaXRzLGNhdGVnb3J5CnBkZl9tZXJnZSwxLHBkZgppbWFnZV9vcHRpbWl6ZSwyLGltYWdlCm9jcl9wZGYsMixvY3IK",
  "to": "json"
}
```

### POST /file-convert/v1/formats — 0 credits
Capability matrix: every action with its accepted input formats, targets and caps — machine-readable (the Zamzar /formats equivalent).

**Parameters:** none

**Returns:** actions{action: {accepts[], targets[], caps{}}}, input_policy, output_policy

## More
- Try it live, no code: https://reefapi.com/playground?engine=file-convert
- Human docs page: https://reefapi.com/docs/file-convert
- Every ReefAPI API in one file (for your AI): https://reefapi.com/llms-full.txt
