PDF to Markdown API for AI agents. Send any PDF URL, get clean structured markdown back. Pay $0.001 USDC per page via x402 v2 — no accounts, no API keys, no subscriptions.
🟢 Live at docpull.ai · Indexed in the CDP Bazaar · Base mainnet
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/health |
None | Service health check |
GET |
/probe?url=<pdf_url> |
None | Page count + cost estimate (free) |
POST |
/extract |
x402 payment | PDF → Markdown |
Check page count and cost before paying:
curl "https://docpull.ai/probe?url=https://example.com/doc.pdf"{
"pageCount": 12,
"costUSDC": "0.012000",
"pricePerPage": "0.001 USDC"
}Without a payment header, the server returns a standard 402 with payment instructions in the PAYMENT-REQUIRED header (base64-encoded x402 v2 envelope).
Use any x402-compatible client to pay automatically:
import { x402Client, wrapFetchWithPayment } from "@x402/fetch";
import { ExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";
const signer = privateKeyToAccount(process.env.EVM_PRIVATE_KEY);
const client = new x402Client()
.register("eip155:*", new ExactEvmScheme(signer));
const fetchWithPayment = wrapFetchWithPayment(fetch, client);
const res = await fetchWithPayment("https://docpull.ai/extract", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ url: "https://example.com/doc.pdf" }),
});
const { markdown, pageCount, charCount } = await res.json();Response:
{
"success": true,
"pageCount": 12,
"charCount": 18432,
"markdown": "# Title\n\n## Section 1\n\nBody text..."
}| Pages | Cost |
|---|---|
| 1 | $0.001 USDC |
| 10 | $0.010 USDC |
| 50 | $0.050 USDC |
| 100 | $0.100 USDC |
Payments settle on Base mainnet via USDC. Use /probe to check cost before committing.
docpull is indexed in the CDP Bazaar — the discovery layer for x402-enabled APIs. AI agents can find and call docpull autonomously without any pre-configuration:
curl "https://api.cdp.coinbase.com/platform/v2/x402/discovery/search?query=pdf+markdown"- Runtime: Node.js 20, Express
- PDF extraction: pdfjs-dist (heading detection, list parsing, per-page separators)
- Payments: x402 v2, CDP facilitator, USDC on Base (
eip155:8453) - Deployment: Railway + Docker
git clone https://github.com/docpull/docpull
cd docpull
npm install
# Set environment variables
railway variables set WALLET_ADDRESS=0xYourAddress
railway variables set BASE_URL=https://your-domain.com
railway variables set CDP_API_KEY_ID=your-cdp-key-id
railway variables set CDP_API_KEY_SECRET=your-cdp-key-secret
railway up| Variable | Required | Description |
|---|---|---|
WALLET_ADDRESS |
✅ | USDC-receiving wallet on Base |
BASE_URL |
✅ | Public HTTPS URL of this service |
CDP_API_KEY_ID |
✅ | CDP API key ID for x402 facilitator |
CDP_API_KEY_SECRET |
✅ | CDP API key secret |
PORT |
❌ | Port (Railway sets automatically) |
cp .env.example .env
# fill in env vars
npm install
npm run dev