100% Private
100% Local
No Signups

ExactPDF API v1

Headless PDF tools for AI agents. Same product as exactpdf.com — metered by API credits. New API users get 20 free test credits; create keys from the Max area. All JSON errors include support@exactpdf.com.

ChatGPT and custom GPT builders can import the OpenAPI spec at https://exactpdf.com/openapi.json. The hosted read-only MCP endpoint is live at https://exactpdf.com/mcp for ChatGPT Developer Mode testing. Public ChatGPT Apps directory distribution still requires OAuth/file handling and OpenAI review.

Get 20 free creditsOpenAPICurl examples

First successful API or MCP run

1. Create a key in Max Account, then call GET /api/v1/account or exactpdf_account.

2. Probe the PDF with POST /api/v1/pdf-info or exactpdf_pdf_info before extraction, conversion, or audio.

3. For RAG, use pdf-structured-markdown. For narration planning, use voice-preview and estimate_speech_cost.

4. Do not submit paid background audio jobs until the dedicated worker passes queue and completion smoke.

Credits & pricing

20 free test credits
Starter — 5,000 credits / $5
Pro — 25,000 credits / $20
Scale — 100,000 credits / $70
1 credit per successful standard operation (merge, split, compress, target-size compress, rotate, images-to-pdf, extract-text, pdf-to-json, pdf-structured-markdown). Launch portal-ready workflows like merge-compress and images-to-pdf-compress also cost 1 credit on successful output. voice-preview is free and capped for short samples. Background speech endpoints (pdf-to-audiobook, pdf-to-speech, generate-audiobook,translate-and-speak, and presentation-narration) are in production hardening and should not be used for paid workloads yet. pdf-info, account, and job polling are 0 credits. Credits never expire. Top-ups: India — INR via Razorpay (UPI, cards) on Max → Account; international — USD via Polar.sh (Merchant of Record).

Agent workflows

Invoice intake: merge vendor PDFs, extract text, then export structured Markdown for RAG indexing.

Portal packet builder: merge PDFs or convert photos into one PDF, then best-effort repack for a 1MB/2MB/5MB upload limit.

Target-size compression: pass target_bytes to compress for 100KB, 200KB, 500KB, or 1MB style upload checks, then read X-Target-Reached.

Audit extraction: run pdf-structured-markdown in academic mode to preserve page breaks for citations.

PDF JSON: run pdf-to-json for metadata, per-page text, full text, and extraction notes for agent pipelines.

Audio generation: use voice-preview and credit estimation today; full background PDF-to-speech/audiobook jobs are in production hardening.

Multilingual distribution: planned for the background audio worker after production reliability is proven.

Presentation narration: planned for the same hardened background worker path.

Internal workflow bots: use the MCP server from Cursor, Claude Desktop, or Codex with the same API key and credit balance.

Quickstart

1. Test your key

curl https://exactpdf.com/api/v1/account \
  -H "Authorization: Bearer sk_live_..."
# {"ok":true,"credits_remaining":20,"credits_lifetime_used":0,"free_tier_resets_at":"2026-06-01T00:00:00.000Z","api_key":{"id":"...","label":"Agent workspace"}}

2. Merge PDFs (curl)

curl https://exactpdf.com/api/v1/merge \
  -H "Authorization: Bearer sk_live_..." \
  -F "file=@a.pdf" -F "file=@b.pdf" \
  -o merged.pdf

2b. Portal-ready merge under a limit

curl https://exactpdf.com/api/v1/merge-compress \
  -H "Authorization: Bearer sk_live_..." \
  -F "file=@cover.pdf" -F "file=@application.pdf" \
  -F "target_bytes=2097152" \
  -D headers.txt \
  -o portal-ready.pdf

# Check X-Output-Bytes and X-Target-Reached in headers.txt.
# API compression is best-effort repack; strict image-heavy targets may need Max/browser exact-size compression.

2c. Photos to PDF under a limit

curl https://exactpdf.com/api/v1/images-to-pdf-compress \
  -H "Authorization: Bearer sk_live_..." \
  -F "file=@photo-1.jpg" -F "file=@photo-2.jpg" \
  -F "target_bytes=1048576" \
  -D headers.txt \
  -o photos-upload-ready.pdf

3. Compress PDF (Node / TypeScript)

import { readFile, writeFile } from 'fs/promises'

const fd = new FormData()
fd.append('file', new Blob([await readFile('big.pdf')]), 'big.pdf')
fd.append('target_bytes', '512000')

const res = await fetch('https://exactpdf.com/api/v1/compress', {
    method: 'POST',
    headers: { Authorization: `Bearer ${process.env.EXACTPDF_API_KEY}` },
    body: fd,
})

if (!res.ok) throw new Error(await res.text())
console.log(res.headers.get('x-output-bytes'), res.headers.get('x-target-reached'))
await writeFile('small.pdf', Buffer.from(await res.arrayBuffer()))

4. Extract text (Python)

import os, requests

with open('contract.pdf', 'rb') as f:
    r = requests.post(
        'https://exactpdf.com/api/v1/extract-text',
        headers={'Authorization': f"Bearer {os.environ['EXACTPDF_API_KEY']}"},
        files={'file': f},
    )
r.raise_for_status()
data = r.json()
print(f"{data['page_count']} pages, {len(data['text'])} chars")

4b. PDF to JSON

curl https://exactpdf.com/api/v1/pdf-to-json \
  -H "Authorization: Bearer sk_live_..." \
  -F "file=@contract.pdf"

5. Preview a voice

curl https://exactpdf.com/api/v1/voice-preview \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{"text":"ExactPDF turns PDFs into natural audio.","voice_style":"audiobook","language":"en"}' \
  -o preview.mp3

6. PDF to speech / audiobook (async)

7. Translate and speak (async)

curl https://exactpdf.com/api/v1/translate-and-speak \
  -H "Authorization: Bearer sk_live_..." \
  -F "file=@training.pdf" \
  -F "source_language=en" \
  -F "target_language=hi" \
  -F "voice_style=educational" \
  -F "output_format=mp3"

OpenAPI for ChatGPT Actions

Use https://exactpdf.com/openapi.json when wiring ExactPDF into custom GPTs, ChatGPT Actions, or enterprise agent platforms that import OpenAPI. The first stable spec intentionally covers JSON-friendly document intelligence endpoints: account, PDF info, text extraction, and structured Markdown. Binary file-returning operations and the public ChatGPT Apps MCP endpoint are separate surfaces so review, auth, and file-handling stay clean.

curl https://exactpdf.com/openapi.json | jq '.info.title, .paths | keys'

Auth

Authorization: Bearer sk_live_…
or X-API-Key: sk_live_…

GET /api/v1/account

Returns credits remaining and key metadata. Does not consume a credit.

POST /api/v1/merge

multipart/form-data with two or more parts named file (PDF). Returns application/pdf on success. Consumes 1 credit only after a successful merge. Max total upload 20MB; max output 16MB.

POST /api/v1/split

One file (PDF). Default: application/zip with page-001.pdf, … (one PDF per page). Optional at_pages (split after those 1-based pages, e.g. 3,7) or ranges JSON ([[1,3],[4,10]]) for custom segments. 1 credit. Max 150 pages (per-page mode); max 25 segments (range modes); ZIP capped at 48MB.

POST /api/v1/rotate

file (PDF) plus form field angle: 90, 180, 270, -90, -180, or -270 (degrees, applied to every page). Returns application/pdf. 1 credit.

POST /api/v1/compress

One file (PDF). MVP rebuild with object streams — may reduce size for some PDFs; scanned files may not shrink much. Optional target_bytes reports measured fit through X-Target-Bytes, X-Output-Bytes, and X-Target-Reached. Returns application/pdf. 1 credit.

POST /api/v1/images-to-pdf

One or more file parts (PNG or JPEG only), order preserved. Returns application/pdf. 1 credit. Up to 25 images, 30MB total.

POST /api/v1/extract-text

One file (PDF). Returns JSON with text and page_count. 1 credit on success. Max upload 12MB for this endpoint.

POST /api/v1/pdf-to-json

One file (PDF). Returns metadata, pages with per-page text and character counts, full text, page_count, and extraction_mode. 1 crediton success. This is text-layer JSON; scanned PDFs need OCR first and table cell reconstruction is not guaranteed.

POST /api/v1/pdf-structured-markdown

One file (PDF). Optional field mode set to developer, academic, or rag (defaults to developer). Academic inserts --- between pages — ideal for auditors crawling long PDF audits. Rag collapses hyphen breaks + short-line fragments — ideal for embeddings. Successful JSON payloads include full markdown. 1 credit on success. Max upload 12MB — same safeguard as plain text extraction (CPU bound).

curl (Bearer key)

curl https://exactpdf.com/api/v1/pdf-structured-markdown \
  -H "Authorization: Bearer sk_live_..." \
  -F "mode=rag" \
  -F "file=@paper.pdf"

RAG ingestion pattern

For retrieval pipelines, prefer pdf-structured-markdown with mode=rag. Keep the Markdown headings as chunk boundaries, store the source PDF path and page hints in metadata, and keep table blocks together instead of slicing them into tiny token windows.

Node: fetch Markdown, then split on headings

import { readFile } from 'node:fs/promises'

const form = new FormData()
form.append('mode', 'rag')
form.append('file', new Blob([await readFile('manual.pdf')]), 'manual.pdf')

const res = await fetch('https://exactpdf.com/api/v1/pdf-structured-markdown', {
  method: 'POST',
  headers: { Authorization: `Bearer ${process.env.EXACTPDF_API_KEY}` },
  body: form,
})
if (!res.ok) throw new Error(await res.text())

const { markdown, page_count } = await res.json()
const chunks = markdown
  .split(/\n(?=#{1,3} )/g)
  .map((text, index) => ({
    text: text.trim(),
    metadata: { source: 'manual.pdf', page_count, section_index: index },
  }))
  .filter((chunk) => chunk.text.length > 120)

Python: heading-aware chunks for vector databases

import os, re, requests

with open("manual.pdf", "rb") as f:
    r = requests.post(
        "https://exactpdf.com/api/v1/pdf-structured-markdown",
        headers={"Authorization": f"Bearer {os.environ['EXACTPDF_API_KEY']}"},
        files={"file": f},
        data={"mode": "rag"},
    )
r.raise_for_status()
payload = r.json()

chunks = []
for i, section in enumerate(re.split(r"\n(?=#{1,3} )", payload["markdown"])):
    text = section.strip()
    if len(text) < 120:
        continue
    chunks.append({
        "text": text,
        "metadata": {
            "source": "manual.pdf",
            "page_count": payload["page_count"],
            "section_index": i,
        },
    })
Use these chunks with LangChain, LlamaIndex, Haystack, or a custom vector pipeline. ExactPDF provides the document structure; your embedding layer should preserve the metadata and avoid splitting tables across unrelated chunks.

POST /api/v1/pdf-info

One file (PDF). Returns JSON with page_count and document metadata (title, author, subject, keywords, producer, creator). 0 credits (does not deduct; still requires a valid API key).

POST /api/v1/voice-preview

JSON or multipart/form-data. Generates a short MP3/WAV voice sample before a paid background speech job. Fields: text (server-capped at 600 characters), output_format (mp3 or wav), voice_style, voice_id, language, and speed. Requires an API key but costs 0 credits.

curl https://exactpdf.com/api/v1/voice-preview \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{"text":"Preview this narrator before generating the full audiobook.","voice_style":"professional","language":"en"}' \
  -o preview.mp3

POST /api/v1/pdf-to-audiobook

Compatibility aliases: POST /api/v1/pdf-to-speech and POST /api/v1/generate-audiobook. One file (PDF). When the worker is enabled, this creates a background PDF-to-speech/audiobook job and returns HTTP 202 with job_id and status_url. Optional fields: output_format (mp3, wav, zip), voice_style, voice_id, language, speed, page_range, normalize_pauses, preserve_chapters, pronunciation_fixes, callback_url, and webhook_secret. Credits are estimated from the selected PDF text layer before queueing: 1 credit per generated minute.

curl

curl https://exactpdf.com/api/v1/generate-audiobook \
  -H "Authorization: Bearer sk_live_..." \
  -F "file=@training.pdf" \
  -F "voice_style=professional" \
  -F "output_format=mp3"

GET /api/v1/jobs/:id

Speech compatibility aliases: GET /api/v1/speech-jobs/:id and GET /api/v1/speech-jobs/:id/download. Poll an async job created by pdf-to-speech, pdf-to-audiobook, generate-audiobook, translate-and-speak, or presentation-narration. Succeeded jobs include a temporary result_url for download. Failed jobs include error_code and error_message. Polling is free.

Webhooks are best-effort completion callbacks. If webhook_secret is supplied, ExactPDF sends x-exactpdf-timestamp, x-exactpdf-event, and x-exactpdf-signature. Verify the signature by computing HMAC-SHA256 over timestamp.body and comparing it with the header value after sha256=.

curl https://exactpdf.com/api/v1/speech-jobs/JOB_ID \
  -H "Authorization: Bearer sk_live_..."

curl -L https://exactpdf.com/api/v1/speech-jobs/JOB_ID/download \
  -H "Authorization: Bearer sk_live_..." \
  -o audiobook.mp3

POST /api/v1/translate-and-speak

One file (PDF) plus required target_language. When enabled, creates a background job that extracts PDF structure, translates the selected text, and generates native speech audio with chapter/page preservation. Sprint 4 live validation starts with hi, es, and fr; the worker is designed for additional Google Cloud TTS languages such as mr, de, ja, and ar. Pricing is 3 credits per estimated generated minute.

Optional fields: source_language, output_format, voice_style, speed, page_range, segmentation_mode (chapters or pages), translation_glossary, callback_url, and webhook_secret. Use segmentation_mode=pages when narrating presentation PDFs.

curl https://exactpdf.com/api/v1/translate-and-speak \
  -H "Authorization: Bearer sk_live_..." \
  -F "file=@report.pdf" \
  -F "target_language=es" \
  -F "voice_style=professional"

POST /api/v1/presentation-narration

One file (PDF). When enabled, creates an audio-first presentation narration job. Each PDF page is treated as a slide, and the default zip output contains one MP3 per page plus a manifest.json with page_start, page_end, and duration_seconds. MP4 export is intentionally reserved for a later sprint. Pricing is 1 credit per estimated generated minute.

Optional fields: output_format, voice_style, speed, page_range, callback_url, and webhook_secret.

curl https://exactpdf.com/api/v1/presentation-narration \
  -H "Authorization: Bearer sk_live_..." \
  -F "file=@slides.pdf" \
  -F "voice_style=presenter"

MCP (ChatGPT / Cursor / Claude / Codex)

Hosted MCP endpoint for ChatGPT Developer Mode: https://exactpdf.com/mcp. This first hosted surface is read-only: it helps ChatGPT choose ExactPDF workflows, set up OpenAPI actions, estimate audio credits, and understand the app roadmap without asking users to paste secrets in chat. Authenticated PDF processing remains available through OpenAPI/API-key actions while OAuth and file-reference handling are prepared for public ChatGPT Apps review.

Package @exactpdf/mcp is the ExactPDF stdio server for agent clients. Set EXACTPDF_API_KEY and wire stdio in your MCP client. Start with exactpdf_first_run_checklist, then exactpdf_account and exactpdf_pdf_info before paid work. Tools: exactpdf_account, exactpdf_pdf_info, exactpdf_merge_pdfs, exactpdf_split_pdf, exactpdf_rotate_pdf, exactpdf_compress_pdf, exactpdf_compress_pdf_to_target, exactpdf_compress_pdf_to_100kb, exactpdf_compress_pdf_to_200kb, exactpdf_compress_pdf_to_500kb, exactpdf_compress_pdf_to_1mb, exactpdf_pdf_to_images, exactpdf_images_to_pdf, exactpdf_extract_text, exactpdf_pdf_to_json, exactpdf_pdf_structured_markdown, exactpdf_ocr_pdf, exactpdf_estimate_speech_cost, exactpdf_voice_preview, exactpdf_pdf_to_speech, exactpdf_pdf_to_audiobook, exactpdf_generate_audiobook, exactpdf_translate_and_speak, exactpdf_presentation_narration, exactpdf_job_status, exactpdf_get_speech_job, exactpdf_download_audio. Optional: EXACTPDF_API_OUTPUT_DIR or EXACTPDF_MERGE_OUTPUT_DIR for saved PDF, ZIP, and audio outputs. The audio submission tools are compatibility placeholders and intentionally return a hardening/disabled message until the production worker is proven.

{
  "mcpServers": {
    "exactpdf": {
      "command": "npx",
      "args": ["-y", "@exactpdf/mcp"],
      "env": { "EXACTPDF_API_KEY": "sk_live_..." }
    }
  }
}