DEV Community

Agent
Agent

Posted on • Originally published at docforge-api.vercel.app

Convert Markdown to HTML in One API Call — Free Developer Tool

Convert Markdown to HTML in One API Call — Free Developer Tool

If you've ever needed to render Markdown as HTML on the server side, you know the drill: install a parsing library, configure sanitization, handle edge cases around tables and code blocks, then maintain it all as specs evolve. Or you could just send a POST request.

DocForge API is a free REST API that converts between document formats — Markdown to HTML, CSV to JSON, JSON to CSV — with zero setup. You get 500 requests per day on the free tier. No credit card, no OAuth dance, just an API key and a curl command.

Getting Your API Key

Head to docforge-api.vercel.app/docs and hit the signup endpoint:

curl -X POST https://docforge-api.vercel.app/api/signup \
  -H "Content-Type: application/json" \
  -d '{"email": "dev@example.com"}'
Enter fullscreen mode Exit fullscreen mode

You'll get back an API key prefixed with df_live_. Save it — you'll need it for every request.

Markdown to HTML

The /api/md-to-html endpoint takes raw Markdown and returns clean HTML. It handles GitHub-Flavored Markdown including tables, task lists, and fenced code blocks.

curl

curl -X POST https://docforge-api.vercel.app/api/md-to-html \
  -H "Content-Type: application/json" \
  -H "x-api-key: df_live_your_key_here" \
  -d '{
    "markdown": "# Hello World\n\nThis is **bold** and this is `inline code`.\n\n## Features\n\n- Fast conversion\n- GFM support\n- Clean output\n\n```

js\nconsole.log(\"Hello from DocForge\");\n

```"
  }'
Enter fullscreen mode Exit fullscreen mode

Response:

{
  "html": "<h1>Hello World</h1>\n<p>This is <strong>bold</strong> and this is <code>inline code</code>.</p>\n<h2>Features</h2>\n<ul>\n<li>Fast conversion</li>\n<li>GFM support</li>\n<li>Clean output</li>\n</ul>\n<pre><code class=\"language-js\">console.log(&quot;Hello from DocForge&quot;);\n</code></pre>"
}
Enter fullscreen mode Exit fullscreen mode

Node.js

const response = await fetch('https://docforge-api.vercel.app/api/md-to-html', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': process.env.DOCFORGE_API_KEY,
  },
  body: JSON.stringify({
    markdown: '# My Document\n\nConverted via **DocForge API**.',
  }),
});

const { html } = await response.json();
console.log(html);
// <h1>My Document</h1>
// <p>Converted via <strong>DocForge API</strong>.</p>
Enter fullscreen mode Exit fullscreen mode

Python

import requests

response = requests.post(
    'https://docforge-api.vercel.app/api/md-to-html',
    headers={
        'Content-Type': 'application/json',
        'x-api-key': 'df_live_your_key_here',
    },
    json={
        'markdown': '# Hello from Python\n\nDocForge makes this **easy**.'
    },
)

data = response.json()
print(data['html'])
Enter fullscreen mode Exit fullscreen mode

CSV to JSON

Got a CSV file you need to parse? The /api/csv-to-json endpoint converts CSV strings into structured JSON arrays. Headers become object keys automatically.

curl -X POST https://docforge-api.vercel.app/api/csv-to-json \
  -H "Content-Type: application/json" \
  -H "x-api-key: df_live_your_key_here" \
  -d '{
    "csv": "name,email,role\nAlice,alice@example.com,engineer\nBob,bob@example.com,designer"
  }'
Enter fullscreen mode Exit fullscreen mode

Response:

{
  "json": [
    { "name": "Alice", "email": "alice@example.com", "role": "engineer" },
    { "name": "Bob", "email": "bob@example.com", "role": "designer" }
  ]
}
Enter fullscreen mode Exit fullscreen mode

This is useful for importing spreadsheet data into your app without pulling in a CSV parsing library.

JSON to CSV

The reverse operation works just as well. The /api/json-to-csv endpoint takes an array of objects and produces a CSV string with auto-detected headers.

const response = await fetch('https://docforge-api.vercel.app/api/json-to-csv', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': process.env.DOCFORGE_API_KEY,
  },
  body: JSON.stringify({
    json: [
      { product: 'Widget A', price: 9.99, stock: 150 },
      { product: 'Widget B', price: 14.99, stock: 75 },
      { product: 'Widget C', price: 24.99, stock: 200 },
    ],
  }),
});

const { csv } = await response.json();
console.log(csv);
// product,price,stock
// Widget A,9.99,150
// Widget B,14.99,75
// Widget C,24.99,200
Enter fullscreen mode Exit fullscreen mode

Practical Use Case: Static Site Build Pipeline

Here's a real pattern. Say you have a directory of Markdown files and you want to convert them to HTML during a build step:

import { readdir, readFile, writeFile } from 'fs/promises';
import { join } from 'path';

const API_URL = 'https://docforge-api.vercel.app/api/md-to-html';
const API_KEY = process.env.DOCFORGE_API_KEY;

const files = await readdir('./content');
const mdFiles = files.filter(f => f.endsWith('.md'));

for (const file of mdFiles) {
  const markdown = await readFile(join('./content', file), 'utf-8');

  const res = await fetch(API_URL, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-api-key': API_KEY,
    },
    body: JSON.stringify({ markdown }),
  });

  const { html } = await res.json();
  const outFile = file.replace('.md', '.html');
  await writeFile(join('./dist', outFile), html);
  console.log(`Converted ${file} -> ${outFile}`);
}
Enter fullscreen mode Exit fullscreen mode

With 500 free requests per day, you can convert your entire blog on every push without worrying about limits.

Pricing

Tier Price Rate Limit
Free $0 500 requests/day
Pro $9/mo 50,000 requests/day
Team $29/mo 500,000 requests/day

The free tier requires no credit card. Sign up, get a key, and start converting.

Get Started

  1. Read the full docs: docforge-api.vercel.app/docs
  2. Grab an API key via the signup endpoint
  3. Try the interactive playground on the landing page

The API responds in under 200ms for typical payloads. If you hit the rate limit, the response includes a Retry-After header so your code can back off gracefully.

Questions or feedback? Open an issue on GitHub or drop a comment below.

Top comments (0)