# Resumir PDFs com Python — Tutorial da API de Resumo de PDF

Adicione a sumarização de PDFs a um script em Python, um notebook ou um backend em poucas linhas. Este tutorial aborda autenticação, a primeira requisição, o formato de resposta, streaming, processamento de pastas inteiras e tratamento adequado de erros.

## Key facts

- Endpoint: POST https://pdf-summarize.com/api/summarize.php com multipart/form-data, campo file.
- Autenticação: cabeçalho Authorization: Bearer sk_... — chave gratuita no cadastro, sem cartão de crédito.
- Opções: length (short/medium/long/extensive), format (paragraph/bullets/mixed), outputLang (auto ou código do idioma), includeKeywords.
- Resposta: JSON com summary, keywords, page_count, processing_time, requests_remaining.
- Adicione ?stream=1 para receber o resumo como Server-Sent Events.

## Pré-requisitos

- Python 3.8+ e a biblioteca `requests` (`pip install requests`).
- Uma chave de API: [crie uma conta gratuita](/signup) e copie sua chave no painel. Armazene-a em uma variável de ambiente em vez de deixá-la no código:

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

## Seu primeiro resumo de PDF em Python

1. **Instalar o requests** — pip install requests.
2. **Definir sua chave de API** — Na variável de ambiente PDF_SUMMARIZE_KEY.
3. **Enviar o PDF** — Como multipart/form-data com o nome de campo file.
4. **Ler o JSON** — O resumo está em summary; verifique success e o status 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"], "| Palavras-chave:", result.get("keywords"))
```

## A resposta

```json
{
  "success": true,
  "summary": "- A receita cresceu 6% para...",
  "keywords": "receita, margem, projeção,...",
  "page_count": 48,
  "original_length": 182340,
  "summary_length": 1210,
  "processing_time": 6.214,
  "requests_remaining": 4987
}
```

`requests_remaining` é a sua cota mensal restante (`-1` significa ilimitado).

## Fazendo streaming do resumo

Para documentos longos ou aplicativos interativos, faça o streaming do resumo à medida que ele é gerado:

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

## Processando uma pasta 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                      # compatível com retomada
    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))   # limite de taxa: aguardar
            else:
                print("falhou", pdf.name, e)
                break
```

## Erros para tratar

| Status | Significado | O que fazer |
|---|---|---|
| 400 | Arquivo ausente, tipo incorreto, limite de páginas excedido | Verifique o arquivo e o limite de páginas do seu plano |
| 401 | Chave de API ausente ou inválida | Verifique o cabeçalho `Authorization` |
| 403 | Conta suspensa | Entre em contato com o suporte |
| 413 | Arquivo muito grande | Comprima ou divida o PDF |
| 422 | Sem texto legível (vazio, protegido ou digitalização ilegível) | Remova a senha; melhore a digitalização |
| 429 | Limite de taxa ou cota mensal atingidos | Aguarde e tente novamente, ou faça upgrade |
| 500 | Resumo temporariamente indisponível | Tente novamente com espera exponencial |

> **Quer testar sem código primeiro?** — Experimente o mesmo motor no seu navegador, de graça.

## Dicas

- **Defina timeouts** generosos (2 a 3 minutos) para PDFs longos.
- **Faça cache dos resultados** pelo hash do arquivo para evitar pagar duas vezes pelo mesmo documento.
- **Mantenha as chaves no servidor** — nunca as embuta em um aplicativo front-end ou móvel.
- Referência completa de parâmetros: a [documentação da API](/docs).

## FAQ

### Existe um plano de API gratuito?

Sim. O plano gratuito inclui uma cota mensal de requisições sem necessidade de cartão de crédito. Veja os preços.

### Posso enviar a URL de um PDF em vez de um arquivo?

A API aceita o arquivo em si. Baixe o PDF no seu código (por exemplo, com o requests) e envie os bytes.

### Em quais idiomas o resumo pode ser gerado?

Use outputLang=auto para manter o idioma do documento, ou um código de idioma como pt, en, fr, es.

### Como resumo PDFs digitalizados através da API?

Envie-os como qualquer PDF; o pipeline de extração recorre ao OCR quando não há camada de texto utilizável.

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