# Resumir PDFs con Python — Tutorial de la API de PDF Summarizer

Añade la capacidad de resumir PDFs a un script de Python, un cuaderno o un backend en pocas líneas. Este tutorial cubre la autenticación, una primera petición, el formato de respuesta, el streaming, el procesamiento de carpetas enteras y la gestión adecuada de errores.

## Key facts

- Endpoint: POST https://pdf-summarize.com/api/summarize.php con multipart/form-data, campo file.
- Autenticación: cabecera Authorization: Bearer sk_... — clave gratuita al registrarse, sin tarjeta de crédito.
- Opciones: length (short/medium/long/extensive), format (paragraph/bullets/mixed), outputLang (auto o un código de idioma), includeKeywords.
- Respuesta: JSON con summary, keywords, page_count, processing_time, requests_remaining.
- Añade ?stream=1 para recibir el resumen mediante Server-Sent Events.

## Requisitos previos

- Python 3.8+ y la librería `requests` (`pip install requests`).
- Una clave de API: [crea una cuenta gratuita](/signup) y copia tu clave desde el panel de control. Guárdala en una variable de entorno en lugar de incluirla en el código:

```bash
export PDF_SUMMARIZE_KEY="sk_live_..."
```

## Tu primer resumen de PDF en Python

1. **Instala requests** — pip install requests.
2. **Configura tu clave de API** — En la variable de entorno PDF_SUMMARIZE_KEY.
3. **Envía el PDF** — Como multipart/form-data con el nombre de campo file.
4. **Lee el JSON** — El resumen se encuentra en summary; comprueba success y el código de estado HTTP.

```python
import os
import requests

API_URL = "https://pdf-summarize.com/api/summarize.php"
API_KEY = os.environ["PDF_SUMMARIZE_KEY"]

def summarize_pdf(path, length="medium", fmt="bullets", lang="auto"):
    with open(path, "rb") as f:
        resp = requests.post(
            API_URL,
            headers={"Authorization": f"Bearer {API_KEY}"},
            files={"file": (os.path.basename(path), f, "application/pdf")},
            data={"length": length, "format": fmt, "outputLang": lang, "includeKeywords": "1"},
            timeout=180,
        )
    data = resp.json()
    if resp.status_code != 200 or not data.get("success"):
        raise RuntimeError(f"{resp.status_code}: {data.get('error', data)}")
    return data

result = summarize_pdf("annual-report.pdf")
print(result["summary"])
print("Páginas:", result["page_count"], "| Palabras clave:", result.get("keywords"))
```

## La respuesta

```json
{
  "success": true,
  "summary": "- Los ingresos crecieron un 6% hasta...",
  "keywords": "ingresos, margen, previsiones, ...",
  "page_count": 48,
  "original_length": 182340,
  "summary_length": 1210,
  "processing_time": 6.214,
  "requests_remaining": 4987
}
```

`requests_remaining` representa tu cuota mensual restante (`-1` indica ilimitada).

## Hacer streaming del resumen

Para documentos largos o aplicaciones interactivas, transmite el resumen a medida que se genera:

```python
import json

def stream_summary(path):
    with open(path, "rb") as f:
        with requests.post(
            API_URL + "?stream=1",
            headers={"Authorization": f"Bearer {API_KEY}"},
            files={"file": (os.path.basename(path), f, "application/pdf")},
            data={"length": "long", "format": "mixed"},
            stream=True, timeout=300,
        ) as resp:
            resp.raise_for_status()
            for line in resp.iter_lines(decode_unicode=True):
                if not line or not line.startswith("data: "):
                    continue
                payload = line[6:]
                if payload == "[DONE]":
                    break
                event = json.loads(payload)
                if "error" in event:
                    raise RuntimeError(event["error"])
                if event.get("type") == "summary":
                    print(event["content"], end="", flush=True)

stream_summary("research-paper.pdf")
```

## Procesar una carpeta de PDFs

```python
import pathlib, time

out_dir = pathlib.Path("summaries")
out_dir.mkdir(exist_ok=True)

for pdf in sorted(pathlib.Path("pdfs").glob("*.pdf")):
    target = out_dir / (pdf.stem + ".md")
    if target.exists():
        continue                      # permite reanudar el proceso fácilmente
    for attempt in range(3):
        try:
            data = summarize_pdf(str(pdf), length="long", fmt="mixed")
            target.write_text(data["summary"], encoding="utf-8")
            print("ok", pdf.name, data["page_count"], "páginas")
            break
        except RuntimeError as e:
            if str(e).startswith("429"):
                time.sleep(30 * (attempt + 1))   # límite de peticiones: espera antes de reintentar
            else:
                print("error", pdf.name, e)
                break
```

## Errores que debes gestionar

| Estado | Significado | Qué hacer |
|---|---|---|
| 400 | Falta el archivo, formato incorrecto, límite de páginas superado | Comprueba el archivo y el límite de páginas de tu plan |
| 401 | Clave de API ausente o no válida | Verifica la cabecera `Authorization` |
| 403 | Cuenta suspendida | Contacta con soporte |
| 413 | Archivo demasiado grande | Comprime o divide el PDF |
| 422 | Sin texto legible (vacío, protegido o escaneo ilegible) | Elimina la contraseña; mejora el escaneo |
| 429 | Límite de peticiones o cuota mensual alcanzada | Espera y reintenta, o actualiza tu plan |
| 500 | Resumen temporalmente no disponible | Reintenta aplicando espera exponencial |

> **¿Quieres probar sin escribir código primero?** — Prueba el mismo motor en tu navegador, gratis.

## Consejos

- **Configura tiempos de espera (timeouts)** generosos (2-3 minutos) para PDFs largos.
- **Almacena en caché los resultados** mediante el hash del archivo para evitar pagar dos veces por el mismo documento.
- **Mantén las claves en el servidor** — nunca las incluyas en el código de una aplicación frontend o móvil.
- Referencia completa de parámetros: la [documentación de la API](/docs).

## FAQ

### ¿Hay un plan de API gratuito?

Sí. El plan gratuito incluye una cuota mensual de peticiones sin necesidad de tarjeta de crédito. Consulta las tarifas.

### ¿Puedo enviar la URL de un PDF en lugar de un archivo?

La API recibe el archivo directamente. Descarga el PDF en tu código (por ejemplo, con requests) y envía los bytes.

### ¿En qué idiomas puede estar el resumen?

Usa outputLang=auto para conservar el idioma del documento, o indica un código de idioma como en, fr, es, de.

### ¿Cómo puedo resumir PDFs escaneados a través de la API?

Envíalos como cualquier PDF; el sistema de extracción recurre automáticamente al OCR cuando no hay una capa de texto utilizable.

---
Source: https://pdf-summarize.com/es/guides/pdf-summary-api-python — PDF Summarizer (free PDF summarizer, Q&A with page citations, OCR, REST API). Site overview: https://pdf-summarize.com/llms.txt
