# Riassumere PDF con Python — Tutorial sull'API PDF Summary

Aggiungi la sintesi dei PDF a uno script Python, un notebook o un backend in poche righe. Questo tutorial copre l'autenticazione, la prima richiesta, il formato di risposta, lo streaming, l'elaborazione di un'intera cartella e la corretta gestione degli errori.

## Key facts

- Endpoint: POST https://pdf-summarize.com/api/summarize.php con multipart/form-data, campo file.
- Autenticazione: intestazione Authorization: Bearer sk_... — chiave gratuita alla registrazione, nessuna carta di credito.
- Opzioni: length (short/medium/long/extensive), format (paragraph/bullets/mixed), outputLang (auto o codice lingua), includeKeywords.
- Risposta: JSON con summary, keywords, page_count, processing_time, requests_remaining.
- Aggiungi ?stream=1 per ricevere il riassunto come Server-Sent Events.

## Prerequisiti

- Python 3.8+ e la libreria `requests` (`pip install requests`).
- Una chiave API: [crea un account gratuito](/signup) e copia la tua chiave dalla dashboard. Archiviala in una variabile d'ambiente anziché nel codice:

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

## Il tuo primo riassunto PDF in Python

1. **Installa requests** — pip install requests.
2. **Imposta la chiave API** — Nella variabile d'ambiente PDF_SUMMARIZE_KEY.
3. **Invia il PDF** — Come multipart/form-data con il nome campo file.
4. **Leggi il JSON** — Il riassunto si trova in summary; controlla success e lo stato 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("Pagine:", result["page_count"], "| Parole chiave:", result.get("keywords"))
```

## La risposta

```json
{
  "success": true,
  "summary": "- Il fatturato è cresciuto del 6% a ...",
  "keywords": "fatturato, margine, previsioni, ...",
  "page_count": 48,
  "original_length": 182340,
  "summary_length": 1210,
  "processing_time": 6.214,
  "requests_remaining": 4987
}
```

`requests_remaining` indica la quota mensile residua (`-1` significa illimitata).

## Streaming del riassunto

Per documenti lunghi o app interattive, effettua lo streaming del riassunto man mano che viene generato:

```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")
```

## Elaborazione di una cartella di PDF

```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                      # compatibile con la ripresa
    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"], "pagine")
            break
        except RuntimeError as e:
            if str(e).startswith("429"):
                time.sleep(30 * (attempt + 1))   # limite superato: attesa esponenziale
            else:
                print("fallito", pdf.name, e)
                break
```

## Errori da gestire

| Stato | Significato | Cosa fare |
|---|---|---|
| 400 | File mancante, formato errato, limite pagine superato | Controlla il file e il limite di pagine del tuo piano |
| 401 | Chiave API mancante o non valida | Controlla l'intestazione `Authorization` |
| 403 | Account sospeso | Contatta l'assistenza |
| 413 | File troppo grande | Comprimi o dividi il PDF |
| 422 | Nessun testo leggibile (vuoto, protetto o scansione illeggibile) | Rimuovi la password; migliora la scansione |
| 429 | Limite di richieste o quota mensile raggiunta | Attendi e riprova, o effettua l'upgrade |
| 500 | Servizio di sintesi temporaneamente non disponibile | Riprova con un'attesa |

> **Vuoi testare senza scrivere codice?** — Prova lo stesso motore direttamente nel browser, gratis.

## Consigli

- **Imposta timeout** generosi (2-3 minuti) per PDF lunghi.
- **Memorizza nella cache i risultati** tramite l'hash del file per evitare di pagare due volte per lo stesso documento.
- **Tieni le chiavi sul lato server** — non includerle mai in un'app frontend o mobile.
- Riferimento completo dei parametri: la [documentazione dell'API](/docs).

## FAQ

### Esiste un piano API gratuito?

Sì. Il piano gratuito include una quota mensile di richieste senza bisogno di carta di credito. Consulta i prezzi.

### Posso inviare l'URL di un PDF anziché un file?

L'API accetta direttamente il file. Scarica il PDF nel tuo codice (ad es. con requests) e invia i byte.

### In quali lingue può essere generato il riassunto?

Usa outputLang=auto per mantenere la lingua del documento, oppure un codice lingua come it, en, fr, es, de.

### Come posso riassumere PDF scansionati tramite l'API?

Inviali come qualsiasi PDF; la pipeline di estrazione attiva automaticamente l'OCR in assenza di un layer di testo utilizzabile.

---
Source: https://pdf-summarize.com/it/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
