Node4all
Back to blog

Markdown-to-PDF API on Sandbox and Main Endpoints

2026-04-21

A lot of agent and automation workflows generate Markdown first — reports, summaries, changelogs, tickets — but final delivery still needs a PDF. The Node4All md2pdf endpoint covers that step in a single request, on both sandbox.node4all.com (testnet) and api.node4all.com (mainnet), gated by x402 v2 payments.

What it does

POST a Markdown document, receive a PDF. The endpoint accepts either a JSON body with a markdown field or a multipart upload (file, .md, up to 10MB) and returns application/pdf directly — no async polling, no second request to fetch the result.

Endpoints

EnvironmentURL
Sandbox (Base Sepolia)POST https://sandbox.node4all.com/v1/md2pdf
Production (Base Mainnet)POST https://api.node4all.com/v1/md2pdf

Both URLs follow the same x402 v2 contract: an unauthorized request returns 402 Payment Required with a base64-encoded PAYMENT-REQUIRED header. Decode it, sign an EIP-3009 transferWithAuthorization, and resubmit with the PAYMENT-SIGNATURE header. The response includes the generated PDF and a PAYMENT-RESPONSE header carrying the settlement receipt.

Quick start with x402-fetch

The path of least resistance is the x402-fetch client — it negotiates the 402 challenge, signs the authorization, and retries the request for you.

import { wrapFetchWithPayment } from "x402-fetch";
import { privateKeyToAccount } from "viem/accounts";

const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
const fetchWithPayment = wrapFetchWithPayment(fetch, account);

const res = await fetchWithPayment(
  "https://sandbox.node4all.com/v1/md2pdf",
  {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ markdown: "# Hello\n\nThis PDF was generated from Markdown." }),
  },
);

const pdfBuffer = Buffer.from(await res.arrayBuffer());
// write pdfBuffer to disk, stream to S3, attach to an email, etc.

If you want to see the raw protocol — the 402 challenge, the headers, the encoded settlement — the same thing in curl looks like this:

# Step 1: probe the endpoint to see the price/asset/network the server expects.
curl -i -X POST https://sandbox.node4all.com/v1/md2pdf \
  -H "Content-Type: application/json" \
  -d '{"markdown":"# Hello"}'
# → HTTP/1.1 402 Payment Required
# → payment-required: <base64 JSON>

# Step 2: sign and resubmit (use x402-fetch or the agent toolkit; signing
# EIP-3009 by hand isn't fun).

For agents in Claude Desktop or any MCP-capable runtime, the @node4all/x402-agent-toolkit MCP server wraps the same flow as a tool call.

Multipart uploads

For files larger than what fits cleanly in a JSON body, use multipart:

curl -X POST https://sandbox.node4all.com/v1/md2pdf \
  -H "PAYMENT-SIGNATURE: <base64 EIP-3009 authorization>" \
  -F "file=@document.md" \
  --output output.pdf

The 10MB cap is generous — typical agent-generated Markdown lands under 200KB.

Errors you might hit

  • 400 Bad Request — neither markdown JSON field nor a file upload was provided.
  • 413 Payload Too Large — the document exceeds the 10MB limit.
  • 415 Unsupported Media Type — the multipart upload is not a .md file.
  • 500 Internal Server Error — surface this to us; it's almost always a Markdown edge case worth fixing.

Pricing

/v1/md2pdf is priced at $0.02 per request in USDC on Base. The sandbox version uses Base Sepolia testnet USDC, the production version uses real USDC.

What's next

The companion endpoint, /v1/pdf2md, is now live too — layout-aware PDF → Markdown extraction for ingesting long documents into a model context window. More endpoints (image extraction, structured data, archival) are queued behind it.