API de Markdown a PDF#
La API de Markdown a PDF convierte un archivo Markdown en un documento PDF con estilo mediante POST /v1/convert/markdown-to-pdf. Tu archivo .md o .markdown se renderiza primero a HTML, con soporte para tablas, bloques de código delimitados con resaltado de sintaxis y tabla de contenidos. Después se convierte a PDF con WeasyPrint. La respuesta son los bytes del PDF en bruto por defecto, o metadatos JSON con una URL de descarga prefirmada cuando direct_download=false; los tamaños de página personalizados, márgenes, encabezados, pies de página y la salida en escala de grises están disponibles vía pdf_options.
Endpoint#
POST /v1/convert/markdown-to-pdf
Content-Type: multipart/form-data
Entrada aceptada: archivos .md o .markdown (codificados en UTF-8)
Formato de salida: .pdf (application/pdf)
Autenticación#
Requiere una clave API privada o un token JWT emitido a partir de una clave pública.
X-API-Key: sk_your_private_key
O bien:
Authorization: Bearer <jwt_token>
Parámetros de la solicitud#
| Parámetro | Tipo | Requerido | Por defecto | Descripción |
|---|---|---|---|---|
file |
file | Sí | -- | El archivo .md o .markdown a convertir. Debe estar codificado en UTF-8. |
output_filename |
string |
No | Nombre del archivo de entrada | Nombre de archivo de salida personalizado. La extensión .pdf se añade automáticamente. |
direct_download |
boolean |
No | true |
Con true, devuelve los bytes del PDF en bruto. Con false, devuelve metadatos JSON con una URL de descarga prefirmada. |
pdf_options |
string |
No | null |
Cadena JSON con las opciones de configuración del PDF. Ver abajo. |
Opciones de PDF#
Pásalas como cadena JSON en el campo de formulario pdf_options. Todos los campos son opcionales.
| Parámetro | Tipo | Por defecto | Descripción |
|---|---|---|---|
page_size |
string |
"A4" |
Tamaño de página con nombre. |
page_width |
float |
null |
Ancho de página personalizado en milímetros. Ancho y alto deben definirse juntos. |
page_height |
float |
null |
Alto de página personalizado en milímetros. |
orientation |
string |
"portrait" |
"portrait" u "landscape". |
margins |
object |
{"top": 10, "bottom": 10, "left": 10, "right": 10} |
Márgenes de página en milímetros. |
grayscale |
boolean |
false |
Convierte la salida a escala de grises. |
header |
object |
null |
Encabezado de página. Formato: {"content": "<text>", "height": 15}. |
footer |
object |
null |
Pie de página. Mismo formato que el encabezado. |
Tamaños de página soportados: A0-A6, B0-B5, Letter, Legal, Tabloid, Ledger
Variables de plantilla para encabezado/pie de página: {{page}}, {{total_pages}}, {{date}}, {{title}}, {{url}}
Detalles de la conversión#
La conversión es un proceso de dos pasos:
- Markdown a HTML usando Python-Markdown con las extensiones:
tables-- tablas delimitadas por barras verticalesfenced_code-- bloques de código con triple backtickcodehilite-- resaltado de sintaxistoc-- tabla de contenidos mediante el marcador[TOC]-
attr_list-- atributos HTML mediante la sintaxis{.class #id} -
HTML a PDF usando WeasyPrint con una hoja de estilos integrada que proporciona:
- Pila de fuentes del sistema, layout centrado con ancho máximo de 800px
- Bloques de código, tablas, citas e imágenes con estilo
- Dimensionado responsivo de imágenes (
max-width: 100%)
Las pdf_options se inyectan como reglas CSS @page antes del renderizado.
Respuesta#
Descarga directa (direct_download=true, por defecto)#
HTTP 200 OK
Content-Type: application/pdf
Content-Disposition: inline; filename="readme_20260405_123456789.pdf"
Respuesta con metadatos (direct_download=false)#
{
"presigned_url": "https://spaces.example.com/...",
"object_key": "env/files/{project_id}/markdown-to-pdf/readme_20260405_123456789.pdf",
"filename": "readme_20260405_123456789.pdf",
"file_size": 34567,
"conversion_time_seconds": 0.8
}
Ejemplos de código#
Python#
import requests
import json
with open("README.md", "rb") as f:
response = requests.post(
"https://api.enconvert.com/v1/convert/markdown-to-pdf",
headers={"X-API-Key": "sk_your_private_key"},
files={"file": ("README.md", f, "text/markdown")},
data={
"pdf_options": json.dumps({
"page_size": "Letter",
"margins": {"top": 25, "bottom": 25, "left": 20, "right": 20},
"footer": {"content": "Page {{page}} of {{total_pages}}", "height": 10}
})
}
)
with open("README.pdf", "wb") as out:
out.write(response.content)
Node.js#
const form = new FormData();
form.append("file", fs.createReadStream("README.md"));
form.append("pdf_options", JSON.stringify({
page_size: "Letter",
footer: { content: "Page {{page}} of {{total_pages}}", height: 10 }
}));
const response = await fetch("https://api.enconvert.com/v1/convert/markdown-to-pdf", {
method: "POST",
headers: { "X-API-Key": "sk_your_private_key" },
body: form
});
fs.writeFileSync("README.pdf", Buffer.from(await response.arrayBuffer()));
PHP#
$ch = curl_init("https://api.enconvert.com/v1/convert/markdown-to-pdf");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["X-API-Key: sk_your_private_key"],
CURLOPT_POSTFIELDS => [
"file" => new CURLFile("README.md", "text/markdown"),
"pdf_options" => json_encode(["page_size" => "Letter", "grayscale" => true])
]
]);
$pdf = curl_exec($ch);
curl_close($ch);
file_put_contents("README.pdf", $pdf);
Go#
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
part, _ := writer.CreateFormFile("file", "README.md")
file, _ := os.Open("README.md")
io.Copy(part, file)
writer.WriteField("pdf_options", `{"page_size":"Letter","grayscale":true}`)
writer.Close()
req, _ := http.NewRequest("POST", "https://api.enconvert.com/v1/convert/markdown-to-pdf", body)
req.Header.Set("Content-Type", writer.FormDataContentType())
req.Header.Set("X-API-Key", "sk_your_private_key")
resp, _ := http.DefaultClient.Do(req)
Respuestas de error#
| Estado | Condición |
|---|---|
400 Bad Request |
El archivo no es un archivo .md ni .markdown |
400 Bad Request |
Codificación de Markdown inválida (se espera UTF-8) |
400 Bad Request |
La conversión de Markdown a PDF falló |
400 Bad Request |
JSON de pdf_options inválido |
401 Unauthorized |
Clave API o token JWT ausente o inválido |
402 Payment Required |
Cuota mensual de ops agotada |
402 Payment Required |
Límite de almacenamiento alcanzado |
413 Payload Too Large |
El archivo supera el tamaño máximo de archivo del plan |
Límites#
| Límite | Valor |
|---|---|
| Tamaño máximo de archivo | Depende del plan (Founding: 5 MB) |
| Codificación de entrada | Solo UTF-8 |
| Extensiones aceptadas | .md, .markdown |
| Contenido de encabezado/pie de página | 2000 caracteres máx. |
| Conversiones mensuales | Depende del plan |
Preguntas frecuentes#
¿Cómo convierto un archivo Markdown a PDF con una API REST?#
Envía una solicitud multipart/form-data a POST /v1/convert/markdown-to-pdf con tu archivo .md o .markdown (codificado en UTF-8) en el campo file, autenticada vía X-API-Key o un JWT Bearer. Por defecto se devuelven directamente los bytes del PDF en bruto.
¿La conversión de Markdown a PDF soporta tablas y resaltado de sintaxis de código?#
Sí. El Markdown se renderiza con extensiones de Python-Markdown, incluyendo tables para tablas delimitadas por barras verticales, fenced_code para bloques de código con triple backtick y codehilite para el resaltado de sintaxis, y después se estiliza con una hoja de estilos integrada.
¿Puedo añadir una tabla de contenidos al PDF generado?#
Sí. Coloca un marcador [TOC] en tu Markdown y la extensión toc lo renderiza como una tabla de contenidos en el documento de salida.
¿Cómo añado números de página a un PDF de Markdown?#
Define un footer (o header) en el JSON de pdf_options, p. ej. {"content": "Page {{page}} of {{total_pages}}", "height": 10}. Las variables de plantilla soportadas son {{page}}, {{total_pages}}, {{date}}, {{title}} y {{url}}.
¿Por qué mi solicitud devuelve 400 Bad Request?#
Causas comunes: el archivo no es .md ni .markdown, el contenido no está codificado en UTF-8, el campo pdf_options no es JSON válido, o la conversión en sí falló. Revisa el mensaje de error específico en el cuerpo de la respuesta.