Hub para desarrolladores

Construye con la API de PDF a Markdown

Un ciclo de vida del trabajo predecible sobre 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 saltan los límites del producto.

De un vistazo

Dos superficies, un motor

Elige la integración que encaje. Ambas llaman al mismo motor de conversión y obedecen los mismos espacios, límites y retención.

API REST

Endpoints HTTPS con una clave de API bearer. DTOs estables, errores predecibles, creación idempotente.

Ver el ciclo de vida

MCP alojado

Un endpoint gestionado de Model Context Protocol que expone la conversión como herramientas de agente: una capa fina sobre la misma API.

Conectar MCP

Custom GPT Actions

Importa un spec OpenAPI reducido en un Custom GPT de ChatGPT para que pueda convertir PDF como herramienta integrada.

Configurar la action
Autenticación

Claves de API bearer sobre HTTPS

La API y el MCP usan claves de API bearer, distintas de la vía firmada por dispositivo que usa la extensión de Chrome. Se requiere una cuenta gratuita de Google para generar claves.

Obtén 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 del lado del servidor, rótalas y revócalas cuando quieras.

Valores por defecto honestos

Claves, no contraseñas. La extensión se mantiene anónima y firmada por dispositivo; las claves de API/MCP son una credencial aparte, ligada a la cuenta.
Solo HTTPS. Envía siempre las claves sobre TLS; nunca embebas una clave en código del lado del cliente que llega a los usuarios.
Creación idempotente. Una Idempotency-Key opcional al crear te permite reintentar de forma segura sin trabajos duplicados.

Scopes. Cada clave de API lleva scopes: jobs:create, jobs:read, jobs:download, jobs:delete (los predeterminados), más settings:read / settings:write. Acuña claves de mínimo privilegio; tanto la API REST como las herramientas MCP aplican los scopes de la clave.

API REST

Crea un trabajo, espera, obtén 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

Haz POST de una URL de PDF o sube bytes. Recibes 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

Consulta el estado

Consulta el trabajo hasta ready o error, o registra un webhook firmado en los planes de pago en vez de consultar.

GET /api/v2/jobs/{id}mcp · pdf_to_markdown_get_job
3

Obtén el Markdown

Descarga el resultado una vez listo. Lee truncated y pages para saber si un documento largo se devolvió en parte.

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 de cara 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 auth, 404 trabajo desconocido, 409 sin espacio libre / slots_full, 413 demasiado grande, 429 límite de tasa). El esquema completo está en el spec OpenAPI.

Más endpoints de trabajos

Crear desde archivo (multipart)POST /api/v2/jobs
Listar tus trabajosGET /api/v2/jobs
Crear por lotes (de pago)POST /api/v2/jobs/batch

Create acepta un url JSON o un file multipart, más file_name, external_id, tags opcionales y callback_url / callback_secret para un webhook por trabajo. La creación por lotes es todo-o-nada y debe caber en tus espacios libres.

El objeto del trabajo

job_idstring
statusqueued · processing · ready · error
pages · output_sizeinteger
truncatedboolean
error_code · error_messagemotivo (cuando error)
download_urlstring (cuando 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í con requests. Para un recorrido 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 webhooks está en la sección Webhooks; la configuración del cliente MCP está en la sección MCP. Esquema completo: OpenAPI.

MCP alojado

La conversión como herramientas de agente

Conecta un agente compatible a nuestro endpoint MCP gestionado. Las herramientas son una capa fina sobre la API REST, así que cada llamada obedece los mismos espacios, límites y retención.

1

Apunta el agente al endpoint

JSON-RPC 2.0 sobre Streamable HTTP con tu clave de API como token bearer. Sin 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 los límites, expuesto como siete herramientas. Cada una respeta los scopes 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 herramienta llevan 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 Custom GPT Actions

Importa el spec, obtén una herramienta integrada

Publicamos dos specs: el OpenAPI completo para desarrolladores, y un spec de action reducido con el subconjunto seguro y mínimo para clientes de IA y Custom GPT Actions de ChatGPT.

OpenAPI completo

El contrato completo: cada endpoint, parámetro, DTO y error. Genera clientes o explóralo en tus herramientas.

Abrir el spec completo

Spec reducido para Custom GPT

Un subconjunto mínimo de action (crear, estado, obtener) para Custom GPT Actions de ChatGPT. Importa la URL, pon tu clave de API como auth, y tu GPT convierte PDF de forma nativa.

Abrir el spec reducido

El spec reducido es una comodidad para clientes de IA, no una frontera de seguridad: aplican la misma auth, scopes y límites que en la API completa.

Límites y límites de tasa

Límites por plan, aplicados igual a API y MCP

Los límites vienen de tu plan y se aplican de forma idéntica en cada superficie. Los valores en vivo están en la página de precios.

Plan gratuito (con una cuenta)

Espacios activos (profundidad de cola)3
Tamaño máximo de PDF10 MB
Presupuesto de tiempo por documento15 min
Retención del resultado listo1 hora

Los planes de pago amplían espacios, tamaño de archivo, presupuesto de tiempo, retención y límites de tasa, y añaden webhooks y creación por lotes. Comparar planes →

Límites de tasa y contrapresión

Límites de tasa por plan. Las solicitudes se limitan por clave; si los superas, recibes 429 con una cabecera Retry-After: espera y reintenta.
Presión de espacios. Si todos los espacios están ocupados, create devuelve 409. Libera un espacio con delete, o espera a que un trabajo termine.
Prioridad en los de pago. Los trabajos de pago corren con mayor prioridad de cola en un pool de conversión de pago dedicado, así no esperan detrás del backlog gratuito.
Webhooks

Recibe aviso en vez de consultar

En los planes de pago, registra un webhook firmado (o pasa un callback_url por trabajo) y te hacemos 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 lleva contenido del documento, así que obtén el Markdown por la API después de recibirlo.

1

Registra un endpoint

Haz POST de una URL HTTPS (con protección SSRF) y un filtro events opcional. El secreto de firma whsec_… se devuelve una sola vez. O pon callback_url + callback_secret en un único trabajo.

POST /api/v2/webhooksGET /api/v2/webhooks/deliveries
2

Recibe el evento

Te hacemos POST de JSON con las cabeceras X-P2M-Event, X-P2M-Timestamp, X-P2M-Delivery y X-P2M-Signature.

3

Verifica, luego actúa

Recalcula la firma, confirma con 2xx, y sé idempotente (las entregas pueden reintentar con backoff). 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)
Prompts y seguridad

Instrucciones portables para agentes

Pon estas reglas en el system prompt de un agente para que maneje las herramientas correctamente y nunca invente resultados.

Espera a ready

Nunca reclames ni resumas un resultado antes de status=ready. Mientras esté queued o processing, sigue consultando o espera el webhook.

Confirma los borrados

Eliminar un trabajo queued o processing es destructivo. Pregunta al usuario antes de llamar a pdf_to_markdown_delete_job en un trabajo sin terminar.

Maneja la truncación

Si truncated=true, dile al usuario que el documento se devolvió en parte hasta el presupuesto de tiempo del plan, y ofrece un plan superior o dividir el archivo.

Respeta el 429

Ante un 429, espera los segundos de Retry-After antes de reintentar. No martillees la cola.

Limpia espacios

Elimina los trabajos terminados que ya no necesites para no agotar tus espacios.

Lee el descubrimiento

Empieza por /llms.txt y el spec OpenAPI en vez de adivinar endpoints a partir de la prosa.

Descubrimiento legible por máquinas

Todo lo que un agente necesita para integrarse sin leer código fuente: un archivo compacto de capacidades, un archivo de contexto detallado y el spec OpenAPI.