PDF to Markdown
Servidor MCP alojado que convierte PDFs en Markdown limpio y listo para LLM, con tablas, fórmulas (LaTeX) y OCR. Motores propios (MinerU + Docling), no un envoltorio de LLM.
Documentación
Centro de desarrolladores
Construye con la API de PDF to Markdown
Un ciclo de vida de trabajo predecible a través de una API REST y un MCP alojado equivalente: crea un trabajo, espera a ready, obtén el Markdown, libera el espacio. La API y el MCP nunca omiten los límites del producto.
Ver precios Ir a la API OpenAPI
De un vistazo
Dos superficies, un mismo motor
Elige la integración que se adapte. Ambas usan el mismo motor de conversión y respetan los mismos espacios, límites y retención.
REST API
Endpoints HTTPS con una clave de API de portador. DTOs estables, errores predecibles, creación idempotente.
Ver el ciclo de vida
MCP alojado
Un endpoint de Model Context Protocol gestionado que expone la conversión como herramientas de agente: una capa delgada sobre la misma API.
Conectar MCP
Custom GPT Actions
Importa una especificación OpenAPI reducida en un ChatGPT Custom GPT para que pueda convertir PDFs como herramienta integrada.
Configurar la acción
Autenticación
Claves de API de portador sobre HTTPS
La API y el MCP usan claves de API de portador, distintas de la ruta firmada por dispositivo que usa la extensión de Chrome. Se requiere una cuenta de Google gratuita para generar claves.
Obtener una clave
- Inicia sesión con Google (cuenta gratuita).
- Genera una clave de API en tu cuenta; se muestra una sola vez.
- Envíala como
Authorization: Bearer p2m_…en cada solicitud. - Las claves son secretos: guárdalas en el servidor, rota y revoca en cualquier momento.
Valores predeterminados honestos
Claves, no contraseñas. La extensión permanece anónima y firmada por dispositivo; las claves de API/MCP son una credencial separada vinculada a la cuenta.
Solo HTTPS. Envía siempre las claves a través de TLS; nunca incrustes una clave en código del lado del cliente que se distribuya a los usuarios.
Creación idempotente. Un Idempotency-Key opcional en la creación te permite reintentar de forma segura sin trabajos duplicados.
Ámbitos. Cada clave de API lleva ámbitos: jobs:create, jobs:read, jobs:download, jobs:delete (los predeterminados), más settings:read / settings:write. Emite claves con privilegios mínimos; tanto la API REST como las herramientas MCP aplican los ámbitos de la clave.
REST API
Crea un trabajo, espera, obtén el Markdown, limpia el espacio
Un ciclo de vida predecible, dos formas de manejarlo: llama a la API REST desde tu propio código, o usa las herramientas equivalentes del MCP alojado. Nunca reclames un resultado antes de status=ready.
API REST MCP alojado
1
Crea el trabajo
Envía una URL de PDF o sube bytes. Obtén un id de trabajo y un espacio. Idempotency-Key se respeta pero es opcional.
POST /api/v2/jobsmcp · pdf_to_markdown_create_job_from_url
2
Comprueba el estado
Consulta el trabajo hasta ready o error, o registra un webhook firmado en los planes de pago en lugar de consultar.
GET /api/v2/jobs/{id}mcp · pdf_to_markdown_get_job
3
Obtén el Markdown
Descarga el resultado una vez que esté listo. Lee truncated y pages para saber si un documento largo se devolvió parcialmente.
GET /api/v2/jobs/{id}/downloadmcp · pdf_to_markdown_get_markdown
4
Elimina / limpia el espacio
Libera un espacio cuando termines. Eliminar trabajos en cola o en proceso es destructivo: confírmalo en los clientes orientados al usuario.
DELETE /api/v2/jobs/{id}mcp · pdf_to_markdown_delete_job
# 1. create a job from a PDF URL
curl -X POST https://pdf2md.dev/api/v2/jobs \
-H "Authorization: Bearer p2m_…" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com/report.pdf"}'
# → { "job_id": "job_9f3c…", "status": "queued" }
# 2. poll status
curl https://pdf2md.dev/api/v2/jobs/job_9f3c… \
-H "Authorization: Bearer p2m_…"
# → { "status": "ready", "pages": 24, "truncated": false }
# 3. fetch the Markdown
curl https://pdf2md.dev/api/v2/jobs/job_9f3c…/download \
-H "Authorization: Bearer p2m_…"
# 4. free the slot
curl -X DELETE https://pdf2md.dev/api/v2/jobs/job_9f3c… \
-H "Authorization: Bearer p2m_…"
Errores. Las respuestas usan formas estables y códigos HTTP predecibles (400 entrada incorrecta, 401 autenticación, 404 trabajo desconocido, 409 sin espacio libre / slots_full, 413 demasiado grande, 429 límite de velocidad). El esquema completo está en la especificación OpenAPI.
Más endpoints de trabajo
Crear desde archivo (multipart)POST /api/v2/jobs
Lista tus trabajosGET /api/v2/jobs
Creación por lotes (de pago)POST /api/v2/jobs/batch
La creación acepta un url JSON o un file multipart, además de file_name, external_id, tags y callback_url / callback_secret opcionales para un webhook por trabajo. La creación por lotes es todo o nada y debe caber en tus espacios libres.
El objeto de trabajo
job_idstring
statusqueued · processing · ready · error
pages · output_sizeinteger
truncatedboolean
error_code · error_messagereason (when error)
download_urlstring (when ready)
external_id · tagstus metadatos
slot_usage · tiercontexto de cuota
Cuenta y uso. Consulta tu plan, límites y uso en tiempo de ejecución con GET /api/v2/me, /api/v2/limits y /api/v2/usage; gestiona claves en /api/v2/api-keys y webhooks en /api/v2/webhooks.
Inicio rápido
Convierte un PDF a Markdown en Python
Las mismas cuatro llamadas desde cualquier lenguaje. Aquí está con requests. Para un tutorial completo paso a paso con manejo de errores, consulta el tutorial de Python.
# pip install requests
import time, requests
API = "https://pdf2md.dev/api/v2"
H = {"Authorization": "Bearer p2m_…"}
# 1. create a job from a PDF URL (or post a file with files={"file": ...})
job = requests.post(f"{API}/jobs", headers=H,
json={"url": "https://example.com/report.pdf"}).json()
jid = job["job_id"]
# 2. poll until ready (or register a webhook instead)
while True:
j = requests.get(f"{API}/jobs/{jid}", headers=H).json()
if j["status"] in ("ready", "error"):
break
time.sleep(3)
# 3. download the Markdown
md = requests.get(f"{API}/jobs/{jid}/download", headers=H).text
print(md)
Más recetas: subida de archivos y Node
Crear desde un archivo local (curl)
# multipart upload of a local PDF
curl -X POST https://pdf2md.dev/api/v2/jobs \
-H "Authorization: Bearer p2m_…" \
-F "[email protected]" \
-F "file_name=document.pdf"
Node 18+ (fetch global)
// create from URL, poll, download
const API = "https://pdf2md.dev/api/v2";
const H = { Authorization: "Bearer p2m_…" };
let job = await (await fetch(`${API}/jobs`, {
method: "POST",
headers: { ...H, "Content-Type": "application/json" },
body: JSON.stringify({ url: "https://example.com/report.pdf" })
})).json();
while (job.status === "queued" || job.status === "processing") {
await new Promise(s => setTimeout(s, 2000));
job = await (await fetch(`${API}/jobs/${job.job_id}`, { headers: H })).json();
}
if (job.status === "ready") {
const md = await (await fetch(`${API}/jobs/${job.job_id}/download`, { headers: H })).text();
console.log(md);
}
La verificación de firma de webhook está en la sección de Webhooks; la configuración del cliente MCP está en la sección de MCP. Esquema completo: OpenAPI.
MCP alojado
Conversión como herramientas de agente
Conecta un agente compatible a nuestro endpoint MCP gestionado. Las herramientas son una capa delgada sobre la API REST, por lo que cada llamada respeta los mismos espacios, límites y retención.
1
Apunta el agente al endpoint
JSON-RPC 2.0 sobre HTTP Streamable con tu clave de API como token de portador. No hay servidor local que ejecutar. Métodos: initialize, tools/list, tools/call, ping.
POST https://pdf2md.dev/api/v2/mcp
2
Llama a las herramientas
El mismo ciclo de vida más límites, expuesto como siete herramientas. Cada una respeta los ámbitos de la clave; las respuestas de tools/call incluyen slot_usage y tier.
create_job_from_url · create_job_from_upload (jobs:create)list_jobs · get_job (jobs:read)get_markdown (jobs:download) · delete_job (jobs:delete)get_limits
3
Respeta las reglas
Espera a ready antes de usar la salida; confirma antes de eliminar trabajos en cola/en proceso; maneja truncated y 429 Retry-After. (Los nombres de las herramientas tienen el prefijo pdf_to_markdown_.)
// MCP client config (hosted, no local process)
{
"mcpServers": {
"pdf2md": {
"url": "https://pdf2md.dev/api/v2/mcp",
"headers": {
"Authorization": "Bearer p2m_…"
}
}
}
}
OpenAPI y acciones de Custom GPT
Importa la especificación, obtén una herramienta integrada
Publicamos dos especificaciones: la OpenAPI completa para desarrolladores, y una especificación de acción reducida con el subconjunto seguro y mínimo para clientes de IA y acciones de ChatGPT Custom GPT.
OpenAPI completa
El contrato completo: cada endpoint, parámetro, DTO y error. Genera clientes o explóralo en tus herramientas.
Abrir la especificación completa
Especificación reducida para Custom GPT
Un subconjunto de acciones mínimo (crear, estado, obtener) para acciones de ChatGPT Custom GPT. Importa la URL, configura tu clave de API como autenticación, y tu GPT convierte PDFs de forma nativa.
Abrir la especificación reducida
La especificación reducida es una conveniencia para clientes de IA, no un límite de seguridad: se aplican la misma autenticación, ámbitos y límites que en la API completa.
Límites y límites de velocidad
Límites por plan, aplicados por igual a API y MCP
Los límites provienen de tu plan y se aplican de manera idéntica en todas las superficies. Los valores en vivo están en la página de precios.
Plan gratuito (con cuenta)
Espacios activos (profundidad de cola)3
Tamaño máximo de PDF10 MB
Presupuesto de tiempo por documento15 min
Retención de resultados listos1 hora
Los planes de pago aumentan espacios, tamaño de archivo, presupuesto de tiempo, retención y límites de velocidad, y añaden webhooks y creación por lotes. Comparar planes →
Límites de velocidad y contrapresión
Límites de velocidad por plan. Las solicitudes tienen límite de velocidad por clave; si las superas, obtienes 429 con un encabezado Retry-After: retrocede y reintenta.
Presión de espacios. Si todos los espacios están ocupados, la creación devuelve 409. Libera un espacio con eliminar, o espera a que un trabajo termine.
Prioridad en planes de pago. Los trabajos de pago se ejecutan con mayor prioridad de cola en un grupo de conversión de pago dedicado, por lo que no esperan detrás de la acumulación gratuita.
Webhooks
Recibe notificaciones en lugar de consultar
En los planes de pago, registra un webhook firmado (o pasa un callback_url por trabajo) y te enviamos un POST en cada evento terminal notable: job.ready, job.error, job.truncated y job.deleted. El evento es una notificación, no una entrega: no contiene contenido del documento, así que obtén el Markdown a través de la API después de recibirlo.
1
Registra un endpoint
Envía por POST una URL HTTPS (protegida contra SSRF) y un filtro opcional events. El secreto de firma whsec_… se devuelve una vez. O establece callback_url + callback_secret en un solo trabajo.
POST /api/v2/webhooksGET /api/v2/webhooks/deliveries
2
Recibe el evento
Enviamos JSON con los encabezados X-P2M-Event, X-P2M-Timestamp, X-P2M-Delivery y X-P2M-Signature.
3
Verifica y luego actúa
Recalcula la firma, confirma con 2xx y sé idempotente (las entregas pueden reintentar con retroceso). Luego descarga el Markdown.
# delivery → your endpoint
X-P2M-Event: job.ready
X-P2M-Timestamp: 1718900000
X-P2M-Signature: sha256=9a8b7c…
{
"event": "job.ready",
"job": {
"job_id": "job_9f3c…",
"status": "ready",
"pages": 24, "truncated": false,
"download_url": "/api/v2/jobs/job_9f3c…/download"
}
}
# verify (Python): signature = sha256= + hex(HMAC(secret, "ts.rawbody"))
import hmac, hashlib
def verify(secret, ts, raw_body, sig):
expected = "sha256=" + hmac.new(
secret.encode(), f"{ts}.".encode() + raw_body,
hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, sig)
Indicaciones y seguridad
Instrucciones portables para agentes
Incorpora estas reglas en el prompt del sistema de un agente para que maneje las herramientas correctamente y nunca invente resultados.
Espera a que esté listo
Nunca reclames ni resumas un resultado antes de status=ready. Mientras queued o processing, sigue consultando o espera el webhook.
Confirma eliminaciones
Eliminar un trabajo queued o processing es destructivo. Pregunta al usuario antes de llamar a pdf_to_markdown_delete_job en un trabajo no finalizado.
Maneja la truncación
Si truncated=true, informa al usuario que el documento se devolvió parcialmente hasta el presupuesto de tiempo del plan, y ofrece un plan superior o dividir el archivo.
Respeta el 429
En 429, espera Retry-After segundos antes de reintentar. No golpees la cola.
Limpia espacios
Elimina los trabajos finalizados que ya no necesites para no agotar tus espacios.
Lee el descubrimiento
Comienza desde /llms.txt y la especificación OpenAPI en lugar de adivinar endpoints a partir de prosa.
Descubrimiento legible por máquina
Todo lo que un agente necesita para integrarse sin leer código fuente: un archivo de capacidades compacto, un archivo de contexto detallado y la especificación OpenAPI.
llms.txt llms-full.txt OpenAPI