Tu primera petición en Node.js
- Consigue una clave de API gratuitaRegístrate y cópiala desde tu panel de control.
- Guárdala en una variable de entorno
PDF_SUMMARIZE_KEY. - Construye un FormDataAñade el PDF como un Blob bajo el campo
file. - Envía una petición POST y lee el JSON.
// summarize.mjs — node summarize.mjs report.pdf
import { readFile } from 'node:fs/promises';
import { basename } from 'node:path';
const API_URL = 'https://pdf-summarize.com/api/summarize.php';
const KEY = process.env.PDF_SUMMARIZE_KEY;
export async function summarizePdf(path, { length = 'medium', format = 'bullets', outputLang = 'auto' } = {}) {
const form = new FormData();
form.append('file', new Blob([await readFile(path)], { type: 'application/pdf' }), basename(path));
form.append('length', length);
form.append('format', format);
form.append('outputLang', outputLang);
const res = await fetch(API_URL, {
method: 'POST',
headers: { Authorization: `Bearer ${KEY}` },
body: form,
signal: AbortSignal.timeout(180_000),
});
const data = await res.json();
if (!res.ok || !data.success) throw new Error(`${res.status}: ${data.error ?? JSON.stringify(data)}`);
return data;
}
const result = await summarizePdf(process.argv[2]);
console.log(result.summary);
console.log(`${result.page_count} páginas, ${result.processing_time}s, ${result.requests_remaining} peticiones restantes`);
Streaming del resumen
export async function streamSummary(path, onText) {
const form = new FormData();
form.append('file', new Blob([await readFile(path)], { type: 'application/pdf' }), basename(path));
form.append('length', 'long');
const res = await fetch(API_URL + '?stream=1', { method: 'POST', headers: { Authorization: `Bearer ${KEY}` }, body: form });
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const decoder = new TextDecoder();
let buffer = '';
for await (const chunk of res.body) {
buffer += decoder.decode(chunk, { stream: true });
const lines = buffer.split('\n');
buffer = lines.pop();
for (const line of lines) {
if (!line.startsWith('data: ')) continue;
const payload = line.slice(6);
if (payload === '[DONE]') return;
const event = JSON.parse(payload);
if (event.error) throw new Error(event.error);
if (event.type === 'summary') onText(event.content);
}
}
}
await streamSummary('paper.pdf', (t) => process.stdout.write(t));
Un endpoint en Express para tu propia aplicación
Tu interfaz sube el archivo a tu servidor, el cual añade la clave y reenvía el archivo:
import express from 'express';
import multer from 'multer';
const app = express();
const upload = multer({ limits: { fileSize: 20 * 1024 * 1024 } });
app.post('/summarize', upload.single('file'), async (req, res) => {
if (!req.file) return res.status(400).json({ error: 'Falta el archivo' });
const form = new FormData();
form.append('file', new Blob([req.file.buffer], { type: 'application/pdf' }), req.file.originalname);
form.append('length', req.body.length ?? 'medium');
const r = await fetch('https://pdf-summarize.com/api/summarize.php', {
method: 'POST', headers: { Authorization: `Bearer ${process.env.PDF_SUMMARIZE_KEY}` }, body: form,
});
res.status(r.status).json(await r.json());
});
app.listen(3000);
Manejo de errores
| Estado | Significado |
|---|---|
| 400 | Falta el archivo, no es un PDF o se ha superado el límite de páginas |
| 401 | Clave ausente o no válida |
| 413 | Archivo demasiado grande |
| 422 | No hay texto legible en el PDF |
| 429 | Límite de peticiones o cuota alcanzada — inténtalo más tarde con retroceso exponencial |
| 500 | Error temporal de resumen — inténtalo de nuevo |
Preguntas frecuentes
¿Puedo llamar a la API directamente desde el navegador?
Técnicamente sí, pero tu clave quedaría visible para cualquiera. Haz un proxy de las peticiones a través de tu backend como en el ejemplo de Express.
¿Funciona con Deno, Bun o Cloudflare Workers?
Sí, cualquier entorno de ejecución con fetch y FormData estándar funciona de la misma manera.
¿Existe un SDK de TypeScript?
Aún no. La API es un único endpoint multipart, por lo que basta con un pequeño envoltorio tipado alrededor de fetch.
¿Dónde está la referencia completa?
En la documentación de la API, con todos los parámetros y ejemplos en varios lenguajes.