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
#!/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"])
PYLocal PDF as Base64
#!/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"])
PYRaw PDF upload
#!/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"])
PYOnly 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