API de cualquier archivo a Markdown#
El endpoint POST /v1/convert/anything-to-markdown convierte casi cualquier documento que subas — PDF, Word, PowerPoint, Excel, CSV, HTML, EPUB, texto plano y archivos OpenDocument — a Markdown limpio con reconocimiento de encabezados. Detecta el formato automáticamente a partir del archivo que envías, lo despacha al extractor adecuado y devuelve un único archivo .md con la estructura que los pipelines de LLM y RAG realmente necesitan: encabezados #/##/### reales, tablas de tuberías GitHub-Flavored, bloques de código delimitados y enlaces resueltos. Es la contraparte para archivos de url-to-markdown, y el mismo conversor impulsa la ingesta de archivos en el endpoint de ingesta — de modo que el Markdown que obtienes aquí es exactamente lo que consume el fragmentador semántico.
Un solo endpoint reemplaza toda una pila de bibliotecas específicas por formato (pdfplumber, mammoth, python-pptx, openpyxl): sube un archivo, obtén Markdown y aliméntalo a tus embeddings.
Endpoint#
POST /v1/convert/anything-to-markdown
Content-Type: multipart/form-data
Formato de salida: Markdown (.md, UTF-8). El formato se detecta automáticamente a partir de la extensión del nombre del archivo subido y de sus magic bytes — no especificas un tipo de entrada.
Formatos de entrada admitidos#
El tipo de entrada se detecta a partir de la extensión del archivo (validada contra los magic bytes del archivo). Estos son todos los formatos que acepta el endpoint:
| Categoría | Formatos | Extensiones | Notas |
|---|---|---|---|
.pdf |
Encabezados inferidos a partir del tamaño de fuente; tablas extraídas como tablas de tuberías; encabezados/pies de página recurrentes deduplicados. Los PDF escaneados o solo de imagen no tienen capa de texto y se rechazan — no se realiza OCR. | ||
| Word | DOCX, DOC | .docx, .doc |
Los estilos de encabezado de Word se convierten en #/##/###; se conservan listas y tablas. .doc (heredado) se maneja a través de LibreOffice. |
| Presentaciones | PPTX, PPT | .pptx, .ppt |
Una sección ## Slide N por diapositiva, viñetas del cuerpo, tablas y notas del orador. .ppt (heredado) a través de LibreOffice. |
| Hojas de cálculo | XLSX, XLS, CSV | .xlsx, .xls, .csv |
Un encabezado ## SheetName más una tabla GFM por hoja. Los valores de las celdas se conservan tal cual (los ceros a la izquierda y los códigos no se reformatean). |
| Libros electrónicos | EPUB | .epub |
Capítulos concatenados en orden de lectura (spine); se omite el documento de tabla de contenidos/navegación. |
| Web / marcado | HTML, XHTML | .html, .htm, .xhtml |
Conversión fiel del documento completo (no una extracción solo del artículo). |
| OpenDocument | ODT, ODS, ODP | .odt, .ods, .odp |
Documentos de texto, hoja de cálculo y presentación, a través de LibreOffice. |
| Texto enriquecido | RTF | .rtf |
Convertido a través de LibreOffice. |
| Texto plano | Text, Markdown | .txt, .text, .md, .markdown, .mdown, .mkd |
Paso directo con codificación normalizada (Markdown ya es una salida válida). |
.png, .jpg y similares) aún no son compatibles con este endpoint — el OCR de imágenes requiere un pipeline separado y limitado por costos. Subir una imagen devuelve un 400 con un mensaje claro. Para convertir una página web a Markdown en lugar de un archivo, usa url-to-markdown.
Autenticación#
Este endpoint admite autenticación tanto con clave privada como con clave pública.
Clave privada#
Incluye tu clave secreta en el encabezado X-API-Key. Úsalo para llamadas de servidor a servidor donde la clave nunca queda expuesta al cliente.
X-API-Key: sk_live_your_private_key
Clave pública con JWT#
Para uso del lado del cliente, primero genera un token JWT con tu clave pública y luego pásalo como token Bearer.
Paso 1 -- Obtén un token:
POST /v1/auth/token
X-API-Key: pk_live_your_public_key
Paso 2 -- Usa el token:
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
El flujo completo, incluyendo el bloqueo por dominio y la renovación de tokens, está en la guía de autenticación. Cada clave de API lleva una lista blanca de endpoints permitidos — si /v1/convert/anything-to-markdown no está en la lista de la clave, la solicitud se rechaza con 403.
Parámetros de la solicitud#
Envía el archivo como multipart/form-data. El documento va en el campo file; el resto son campos de formulario opcionales.
| Parámetro | Tipo | Obligatorio | Predeterminado | Descripción |
|---|---|---|---|---|
file |
file | Sí | -- | El documento a convertir. Su extensión debe ser uno de los formatos de entrada admitidos anteriores. |
output_filename |
string |
No | Nombre de entrada | Nombre personalizado para el archivo de salida. La extensión .md se añade automáticamente. |
direct_download |
boolean |
No | true |
Se acepta por paridad en la forma de la solicitud con los demás endpoints de conversión. |
job_id |
string |
No | -- | ID de trabajo proporcionado por el cliente para la recuperación ante timeouts. Cuando una conversión síncrona supera los límites de tiempo del proxy inverso, consulta GET /v1/convert/status/{job_id} para recuperar el resultado. |
Respuesta#
La conversión se ejecuta en el mismo proceso y el archivo .md resultante se almacena; luego el endpoint devuelve un cuerpo JSON con una URL de descarga prefirmada:
{
"presigned_url": "https://spaces.example.com/...signed...",
"object_key": "env/files/{project_id}/anything-to-markdown/report_20260714_101530123.md",
"filename": "report_20260714_101530123.md",
"file_size": 5124,
"conversion_time_seconds": 1.8,
"job_id": null
}
Los mismos valores se reflejan en los encabezados de respuesta (X-Object-Key, X-File-Size, X-Conversion-Time, X-Filename) para que puedas leerlos sin analizar el cuerpo. Descarga el Markdown desde presigned_url — el enlace es de corta duración.
Cómo se convierte cada formato#
Cada formato se normaliza a la misma forma de Markdown limpio, de modo que la fragmentación y el embedding posteriores ven una estructura consistente independientemente del origen.
- PDF — El texto se extrae con posicionamiento a nivel de palabra. El tamaño de fuente más común se trata como texto del cuerpo; los tamaños mayores se convierten en encabezados
#/##/###(los más grandes primero). Las tablas se detectan geométricamente y se emiten como tablas de tuberías GFM, y su texto se elimina del flujo de prosa para que nada se duplique. Las líneas que se repiten en la mayoría de las páginas (encabezados/pies de página recurrentes) se descartan. Un PDF sin capa de texto (un escaneo o una exportación solo de imagen) se rechaza con un claro400— este endpoint no ejecuta OCR. - DOCX / DOC — Los estilos de párrafo "Heading 1/2/3" de Word se asignan limpiamente a
#/##/###; se conservan listas, tablas, negrita y cursiva. El.docheredado se enruta primero a través de LibreOffice. - PPTX / PPT — Cada diapositiva se convierte en una sección
## Slide N: Title, los marcadores de posición del cuerpo se convierten en viñetas, las tablas en tablas de tuberías y las notas del orador se añaden como una subsección### Notes— de modo que cada diapositiva es una unidad independiente y recuperable. - XLSX / XLS / CSV — Cada hoja de cálculo se convierte en un encabezado
## SheetNamemás una tabla GFM; un CSV es una única tabla. Las celdas se leen como cadenas, por lo que los ID, los códigos y los ceros a la izquierda se conservan exactamente. - EPUB — Los documentos de contenido se leen en orden de spine (lectura) y se convierten capítulo por capítulo; el documento de navegación/tabla de contenidos se omite para que no contamine tus fragmentos.
- HTML / XHTML — El documento completo se convierte fielmente (no se reduce a un único "artículo"), con script/style/noscript eliminados y encabezados, listas, tablas, enlaces y código conservados.
- ODT / ODS / ODP / RTF — Convertidos a través del mismo motor de LibreOffice que impulsa los endpoints de documento a PDF.
- Text / Markdown — Los finales de línea y la codificación se normalizan; una subida
.mdpasa esencialmente sin cambios.
Formato de salida#
El resultado es Markdown GitHub-Flavored diseñado para el consumo por máquinas:
- Encabezados — ATX (
#,##,###), usados como límites semánticos de sección. - Tablas — Tablas de tuberías GFM (mantenidas atómicas, nunca divididas), con
|escapado dentro de las celdas. - Código — Bloques delimitados con indicaciones de lenguaje cuando son detectables.
- Estructura — Se conservan párrafos, listas y citas; las secciones por diapositiva y por hoja dan límites reales incluso a formatos planos.
Como los encabezados son encabezados ATX reales, esta salida alimenta directamente a un fragmentador con reconocimiento de encabezados. Si quieres los fragmentos — no solo el Markdown — envía el archivo a el endpoint de ingesta en su lugar, que ejecuta esta misma conversión y luego divide el resultado en JSONL listo para RAG.
Cómo construir un pipeline de RAG#
Este endpoint convierte un archivo a la vez a Markdown. Para un pipeline de recuperación completo normalmente quieres fragmentos, no Markdown en bruto, y a menudo muchos archivos a la vez:
- Un archivo, solo el Markdown — usa este endpoint y luego fragméntalo tú mismo.
- Muchos archivos, fragmentados en JSONL — usa
POST /v2/ingest/files. Ejecuta la misma conversión en cada archivo subido, divide cada uno en fragmentos con reconocimiento de encabezados y ensambla un único archivo JSONL que se carga directamente en LangChainJSONLoader, LlamaIndexSimpleDirectoryReadero una base de datos vectorial. - Páginas web en lugar de archivos — usa
POST /v2/ingest(rastreo o lista de URL) o url-to-markdown para una sola página.
Ejemplos de código#
curl (clave privada)#
curl -X POST https://api.enconvert.com/v1/convert/anything-to-markdown \
-H "X-API-Key: sk_live_your_private_key" \
-F "[email protected]"
Python (clave privada)#
import requests
with open("quarterly-report.pdf", "rb") as f:
response = requests.post(
"https://api.enconvert.com/v1/convert/anything-to-markdown",
headers={"X-API-Key": "sk_live_your_private_key"},
files={"file": ("quarterly-report.pdf", f)},
)
response.raise_for_status()
result = response.json()
# Download the Markdown from the pre-signed URL.
markdown = requests.get(result["presigned_url"]).text
print(markdown)
Node.js (clave privada)#
import { readFile } from "node:fs/promises";
const form = new FormData();
form.append(
"file",
new Blob([await readFile("quarterly-report.pdf")]),
"quarterly-report.pdf"
);
const response = await fetch(
"https://api.enconvert.com/v1/convert/anything-to-markdown",
{ method: "POST", headers: { "X-API-Key": "sk_live_your_private_key" }, body: form }
);
const result = await response.json();
const markdown = await fetch(result.presigned_url).then((r) => r.text());
console.log(markdown);
PHP (clave privada)#
$ch = curl_init("https://api.enconvert.com/v1/convert/anything-to-markdown");
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("quarterly-report.pdf", "application/pdf", "quarterly-report.pdf"),
],
]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);
echo $data["presigned_url"];
Respuestas de error#
| Estado | Condición |
|---|---|
400 Bad Request |
Tipo de archivo no admitido, un archivo vacío, la subida de una imagen (OCR no admitido) o un documento sin texto extraíble (p. ej. un PDF escaneado). |
400 Bad Request |
Los bytes del archivo no coinciden con su extensión declarada (discrepancia de magic bytes). |
401 Unauthorized |
Clave de API / token JWT ausente o inválido. |
402 Payment Required |
Se alcanzó el límite mensual de conversiones o el límite de almacenamiento. |
403 Forbidden |
/v1/convert/anything-to-markdown no está en los endpoints permitidos de la clave de API. |
413 Payload Too Large |
La subida excede el límite de tamaño por archivo de tu plan. |
500 Internal Server Error |
La conversión falló inesperadamente. |
La referencia completa de códigos de estado está en la guía de códigos de error.
Límites#
| Límite | Valor |
|---|---|
| Tamaño máximo de subida | Según el plan (Free: 5 MB) |
| Conversiones mensuales | Según el plan (Free: 100) |
| Retención de archivos | Según el plan (Free: 1 hora) |
| Límite de páginas PDF | 2,000 páginas |
| Formatos de entrada admitidos | Consulta la tabla de formatos de entrada admitidos |
Preguntas frecuentes#
¿Cómo convierto un PDF a Markdown con una API?#
Envía una solicitud POST a /v1/convert/anything-to-markdown como multipart/form-data con el PDF en el campo file y tu clave en el encabezado X-API-Key. Recibes JSON con un presigned_url a un archivo .md cuyos encabezados provienen de los tamaños de fuente del PDF y cuyas tablas son tablas de tuberías GitHub-Flavored. Los PDF escaneados o solo de imagen no tienen capa de texto y se rechazan — este endpoint no ejecuta OCR.
¿Qué formatos de archivo puedo convertir a Markdown?#
PDF, Word (.docx, .doc), PowerPoint (.pptx, .ppt), Excel (.xlsx, .xls), CSV, EPUB, HTML/XHTML, OpenDocument (.odt, .ods, .odp), RTF y texto plano/Markdown. La lista completa con notas por formato está en la tabla de formatos de entrada admitidos. Las imágenes aún no son compatibles.
¿Puedo convertir documentos a Markdown para un pipeline de RAG o LLM?#
Sí — para eso está diseñada la salida: encabezados #/##/### reales, tablas de tuberías atómicas y código delimitado. Para un solo archivo obtienes el Markdown aquí y lo fragmentas tú mismo; para muchos archivos fragmentados en JSONL listo para embeber, envíalos a POST /v2/ingest/files, que ejecuta esta misma conversión y divide cada archivo en fragmentos listos para RAG.
¿En qué se diferencia esto de Microsoft MarkItDown o docling?#
Resuelve el mismo problema de "cualquier archivo a Markdown" como una API alojada — sin instalación local, sin dependencias pesadas de ML y con salida con reconocimiento de encabezados optimizada para la fragmentación. Se combina directamente con /v2/ingest para que la misma conversión alimente un pipeline de RAG de extremo a extremo (convertir → fragmentar → JSONL) sin que tengas que conectar bibliotecas entre sí.
¿Convierten PDF escaneados o imágenes?#
No en este endpoint. Un PDF debe tener una capa de texto real; un PDF escaneado o solo de imagen, o un archivo de imagen (.png, .jpg), se rechaza con un claro 400 porque el OCR es un pipeline separado y limitado por costos. Los PDF nativos digitales y los demás formatos de documento listados se convierten sin problemas.