markdown-to-html
Convert a Markdown file to a fully styled HTML document. The output is a complete, self-contained HTML page with embedded CSS, a responsive layout, and a built-in dark mode toggle -- ready to open in any browser.
Endpoint
POST /v1/convert/markdown-to-html
Content-Type: multipart/form-data
Accepted input: .md or .markdown files (UTF-8 encoded)
Output format: .html (text/html)
Authentication
Requires either a private API key or a JWT token from a public key.
X-API-Key: sk_live_your_private_key
Or:
Authorization: Bearer <jwt_token>
Request Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
file |
file | Yes | -- | The .md or .markdown file to convert. Must be UTF-8 encoded. |
output_filename |
string |
No | Input filename | Custom output filename. The .html extension is added automatically. |
direct_download |
boolean |
No | true |
When true, returns the HTML document directly. When false, returns JSON metadata with a presigned download URL. |
Conversion Rules
The converter uses Python-Markdown with the following extensions enabled:
| Extension | What It Does |
|---|---|
tables |
Pipe-delimited Markdown tables rendered as HTML <table> elements |
fenced_code |
Triple-backtick code blocks with language identifiers (```python) |
codehilite |
Syntax highlighting CSS classes on code blocks (via Pygments) |
toc |
Table of contents generation via a [TOC] marker in your document |
attr_list |
Attach HTML attributes to elements using {.class #id} syntax |
Example
Input:
# My Document
[TOC]
## Introduction
This is a **bold** and *italic* example.
## Data Table
| Name | Age | City |
|-------|-----|--------|
| Alice | 30 | London |
| Bob | 25 | Paris |
## Code Sample
```python
def hello():
print("Hello, world!")
```
Output: A complete <!DOCTYPE html> document with:
- The rendered Markdown inside a
<body>with max-width 800px, centered layout - Styled tables, code blocks, links, and headings
- A clickable table of contents generated from the headings
- A dark mode toggle button (top-right corner) that persists the user's preference to
localStorage
Output Styling
The generated HTML includes an embedded <style> block with:
- Light and dark themes via CSS custom properties, toggled by a
data-themeattribute - System font stack (
-apple-system, BlinkMacSystemFont, Segoe UI, Arial, sans-serif) - Responsive layout with 800px max-width and centered content
- Line height of 1.6 for readability
- Styled elements: code blocks (with background), tables (with borders and striped rows), links, and block quotes
Note on syntax highlighting: The
codehilite extension adds Pygments CSS class names to code blocks, but no Pygments stylesheet is bundled in the output. Code blocks will have correct structure and basic styling, but language-specific color highlighting requires adding a Pygments CSS theme to the page. The built-in styling provides background and font styling for all code blocks regardless.
Response
Direct Download (direct_download=true, default)
HTTP 200 OK
Content-Type: text/html
Content-Disposition: inline; filename="readme_20260405_123456789.html"
Returns the full HTML document. Since the Content-Disposition is inline, browsers will render the page directly.
Metadata Response (direct_download=false)
{
"presigned_url": "https://spaces.example.com/...",
"object_key": "env/files/{project_id}/markdown-to-html/readme_20260405_123456789.html",
"filename": "readme_20260405_123456789.html",
"file_size": 5678,
"conversion_time_seconds": 0.04
}
Code Examples
Python
import requests
with open("README.md", "rb") as f:
response = requests.post(
"https://api.enconvert.com/v1/convert/markdown-to-html",
headers={"X-API-Key": "sk_live_your_private_key"},
files={"file": ("README.md", f, "text/markdown")}
)
with open("README.html", "wb") as out:
out.write(response.content)
Node.js
const form = new FormData();
form.append("file", fs.createReadStream("README.md"));
const response = await fetch("https://api.enconvert.com/v1/convert/markdown-to-html", {
method: "POST",
headers: { "X-API-Key": "sk_live_your_private_key" },
body: form
});
const html = await response.text();
fs.writeFileSync("README.html", html);
PHP
$ch = curl_init("https://api.enconvert.com/v1/convert/markdown-to-html");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["X-API-Key: sk_live_your_private_key"],
CURLOPT_POSTFIELDS => ["file" => new CURLFile("README.md", "text/markdown")]
]);
$html = curl_exec($ch);
curl_close($ch);
file_put_contents("README.html", $html);
Go
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
part, _ := writer.CreateFormFile("file", "README.md")
file, _ := os.Open("README.md")
io.Copy(part, file)
writer.Close()
req, _ := http.NewRequest("POST", "https://api.enconvert.com/v1/convert/markdown-to-html", body)
req.Header.Set("Content-Type", writer.FormDataContentType())
req.Header.Set("X-API-Key", "sk_live_your_private_key")
resp, _ := http.DefaultClient.Do(req)
JavaScript -- Browser (Public Key)
const tokenRes = await fetch("https://api.enconvert.com/v1/auth/token", {
method: "POST",
headers: { "X-API-Key": "pk_live_your_public_key" }
});
const { token } = await tokenRes.json();
const form = new FormData();
form.append("file", fileInput.files[0]);
const response = await fetch("https://api.enconvert.com/v1/convert/markdown-to-html", {
method: "POST",
headers: { "Authorization": `Bearer ${token}` },
body: form
});
const data = await response.json();
window.open(data.presigned_url, "_blank");
Error Responses
| Status | Condition |
|---|---|
400 Bad Request |
File is not a .md or .markdown file |
400 Bad Request |
Invalid Markdown encoding (expected UTF-8) |
400 Bad Request |
Markdown to HTML conversion failed |
401 Unauthorized |
Missing or invalid API key / JWT token |
402 Payment Required |
Monthly conversion limit reached |
402 Payment Required |
Storage limit reached |
413 Payload Too Large |
File exceeds plan's maximum file size |
Limits
| Limit | Value |
|---|---|
| Max file size | Plan-dependent (Free: 5 MB) |
| Input encoding | UTF-8 only |
| Accepted extensions | .md, .markdown |
| Monthly conversions | Plan-dependent |