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