curl PDF to Markdown

Validated curl examples for URL, Base64 and raw PDF conversion.

Bash, curl and Python 3 (for response validation). Save each example as convert.sh and run bash convert.sh. Set PDFTOMARKDOWN_API_KEY and save a unique PDFTOMARKDOWN_IDEMPOTENCY_KEY before submission. Reuse that identity only with identical document bytes and options.

Allow up to 11 minutes for a synchronous request. Stopping the client or reaching its timeout stops waiting; processing and charging may continue. Measure elapsed time locally; optional provider timing headers do not measure total request time.

curl URL

curlUrl
#!/usr/bin/env bash
set -euo pipefail
: "${PDFTOMARKDOWN_API_KEY:?Set your API key}"
: "${PDFTOMARKDOWN_IDEMPOTENCY_KEY:?Set a saved conversion identity}"
key=$PDFTOMARKDOWN_API_KEY
identity=$PDFTOMARKDOWN_IDEMPOTENCY_KEY
work=$(mktemp -d)
trap 'rm -rf "$work"' EXIT
result=$work/result
status=$(curl --silent --show-error --max-time 660 -o "$result" -w '%{http_code}' \
  "https://pdftomarkdown.dev/v1/convert" \
  -H "Authorization: Bearer $key" -H "Idempotency-Key: $identity" \
  -H "Content-Type: application/json" \
  --data '{"input":{"pdf_url":"https://pdftomarkdown.dev/samples/invoice.pdf"}}')
if [ "$status" != 200 ]; then echo "HTTP $status; keep the identity for recovery" >&2; exit 1; fi
python3 - "$result" <<'PY'
import json, sys
with open(sys.argv[1]) as response:
    result = json.load(response)
if not (isinstance(result, dict) and result.get("complete") is True
        and isinstance(result.get("markdown"), str)
        and type(result.get("pages")) is int and result["pages"] >= 0
        and isinstance(result.get("request_id"), str) and result["request_id"].strip()):
    sys.exit("Incomplete or invalid conversion response")
sys.stdout.write(result["markdown"])
PY

Local PDF as Base64

curlBase64
#!/usr/bin/env bash
set -euo pipefail
: "${PDFTOMARKDOWN_API_KEY:?Set your API key}"
: "${PDFTOMARKDOWN_IDEMPOTENCY_KEY:?Set a saved conversion identity}"
key=$PDFTOMARKDOWN_API_KEY
identity=$PDFTOMARKDOWN_IDEMPOTENCY_KEY
work=$(mktemp -d)
trap 'rm -rf "$work"' EXIT
result=$work/result
python3 - > "$work/request.json" <<'PY'
import base64, json
from pathlib import Path
print(json.dumps({"input": {"pdf_base64": base64.b64encode(Path("document.pdf").read_bytes()).decode("ascii")}}))
PY
status=$(curl --silent --show-error --max-time 660 -o "$result" -w '%{http_code}' \
  "https://pdftomarkdown.dev/v1/convert" \
  -H "Authorization: Bearer $key" -H "Idempotency-Key: $identity" \
  -H "Content-Type: application/json" \
  --data-binary @"$work/request.json")
if [ "$status" != 200 ]; then echo "HTTP $status; keep the identity for recovery" >&2; exit 1; fi
python3 - "$result" <<'PY'
import json, sys
with open(sys.argv[1]) as response:
    result = json.load(response)
if not (isinstance(result, dict) and result.get("complete") is True
        and isinstance(result.get("markdown"), str)
        and type(result.get("pages")) is int and result["pages"] >= 0
        and isinstance(result.get("request_id"), str) and result["request_id"].strip()):
    sys.exit("Incomplete or invalid conversion response")
sys.stdout.write(result["markdown"])
PY

Raw PDF upload

curlRaw
#!/usr/bin/env bash
set -euo pipefail
: "${PDFTOMARKDOWN_API_KEY:?Set your API key}"
: "${PDFTOMARKDOWN_IDEMPOTENCY_KEY:?Set a saved conversion identity}"
key=$PDFTOMARKDOWN_API_KEY
identity=$PDFTOMARKDOWN_IDEMPOTENCY_KEY
work=$(mktemp -d)
trap 'rm -rf "$work"' EXIT
result=$work/result
status=$(curl --silent --show-error --max-time 660 -o "$result" -w '%{http_code}' \
  "https://pdftomarkdown.dev/v1/convert" \
  -H "Authorization: Bearer $key" -H "Idempotency-Key: $identity" \
  -H "Content-Type: application/pdf" \
  --data-binary @document.pdf)
if [ "$status" != 200 ]; then echo "HTTP $status; keep the identity for recovery" >&2; exit 1; fi
python3 - "$result" <<'PY'
import json, sys
with open(sys.argv[1]) as response:
    result = json.load(response)
if not (isinstance(result, dict) and result.get("complete") is True
        and isinstance(result.get("markdown"), str)
        and type(result.get("pages")) is int and result["pages"] >= 0
        and isinstance(result.get("request_id"), str) and result["request_id"].strip()):
    sys.exit("Incomplete or invalid conversion response")
sys.stdout.write(result["markdown"])
PY

Only a complete, typed success writes Markdown. For pending work, rate limits or an uncertain connection, follow the API’s retry guidance using the same saved identity and input. Never replace the identity automatically. Completed account results replay for 24 hours; demo requests have no paid replay guarantee.

API reference: limits, authentication and errors · Document processing and retention