---
seo_title: API de Markdown a PDF: convierte Markdown a PDF | EnConvert
meta_desc: Convierte Markdown a PDF vía API REST. POST /v1/convert/markdown-to-pdf genera PDFs con estilo desde archivos .md: tablas, resaltado de código, encabezados y pies.
keywords: api markdown a pdf, convertir markdown a pdf api, md a pdf api rest, markdown a pdf con resaltado de sintaxis, convertir readme a pdf api, markdown a pdf api python, markdown a pdf api node js, api md a pdf
---

# 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:

1. **Markdown a HTML** usando Python-Markdown con las extensiones:
   - `tables` -- tablas delimitadas por barras verticales
   - `fenced_code` -- bloques de código con triple backtick
   - `codehilite` -- resaltado de sintaxis
   - `toc` -- tabla de contenidos mediante el marcador `[TOC]`
   - `attr_list` -- atributos HTML mediante la sintaxis `{.class #id}`

2. **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`)

```json
{
    "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

```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

```javascript
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

```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

```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.
