> ## Documentation Index
> Fetch the complete documentation index at: https://docs.markpdf.tech/llms.txt
> Use this file to discover all available pages before exploring further.

# Streaming y trabajos asincrónicos

> Consuma /convert/stream y maneje 202 (auto-asíncrono) con Node.js SDK.

# Streaming y trabajos asincrónicos

Como en API, existen dos mecanismos diferentes:

1. **Transmisión de respuesta** (`/convert/stream`, `/convert/stream-from-url`): fragmentos de Markdown progresivo mientras el servidor convierte.
2. **Trabajos por saturación** (`202`): cuando todos los backends están ocupados, la solicitud se pone en cola y se responde a `202` con un `job_id`. Consulte [`GET /jobs/{id}`](/docs/public/es/api/jobs).

## Transmitiendo con `convertStream`

```ts theme={null}
const client = new MarkpdfClient({ apiKey: "YOUR_API_KEY" });

for await (const chunk of client.convertStream({ data: buffer }, { filename: "report.pdf" })) {
  process.stdout.write(chunk);
}
```

`convertStream` devuelve un `AsyncIterable<string>`; úselo con `for await...of` en Node/Deno/Bun, o consuma el iterador manualmente.

<CodeGroup>
  ```ts Local file theme={null}
  for await (const chunk of client.convertStream({ data: buffer }, { filename: "report.pdf", slim: true })) {
    handle(chunk);
  }
  ```

  ```ts Desde URL theme={null}
  for await (const chunk of client.convertStream({ url: "https://bucket.example.com/report.pdf?sig=..." }, { slim: true })) {
    handle(chunk);
  }
  ```

  ```ts Route Handler (App Router) — pass-through al cliente theme={null}
  export async function GET(req: Request) {
    const stream = new ReadableStream({
      async start(controller) {
        const encoder = new TextEncoder();
        for await (const chunk of client.convertStream({ url: pdfUrl })) {
          controller.enqueue(encoder.encode(chunk));
        }
        controller.close();
      },
    });
    return new Response(stream, { headers: { "content-type": "text/markdown" } });
  }
  ```
</CodeGroup>

### `streamSlimStrategy`

```ts theme={null}
client.convertStream({ data: buffer }, { slim: true, streamSlimStrategy: "sampled" });
```

* `"off"`: streaming puro por página, sin detección de ruido. TTFB mínimo.
* `"sampled"` (predeterminado): muestra las primeras páginas y luego genera por página.
* `"full"`: materializa el documento completo antes de su emisión. Mejor limpieza, peor TTFB.

Consulte [Parámetros](/docs/public/es/api/parameters#streaming-only-parameters).

<Note />

## Empleos por saturación (202)

De forma predeterminada, `convertFile` y `convertFromUrl` manejan `202` de forma transparente (`autoPoll: true`):

```ts theme={null}
// SDK waits and polls automatically
const markdown = await client.convertFile(buffer, { filename: "report.pdf" });
```

### Manual de encuestas

```ts theme={null}
import { MarkpdfJobQueuedError } from "@markpdf/sdk";

try {
  const markdown = await client.convertFile(buffer, {
    filename: "report.pdf",
    autoPoll: false,
  });
} catch (err) {
  if (err instanceof MarkpdfJobQueuedError) {
    console.log(`En cola: ${err.jobId}`);
    let status;
    do {
      await new Promise((r) => setTimeout(r, err.retryAfterSeconds * 1000));
      status = await client.getJob(err.jobId);
    } while (status.status === "queued" || status.status === "processing");

    if (status.status === "completed") {
      const markdown = status.body as string;
    } else {
      throw new Error(status.error);
    }
  } else {
    throw err;
  }
}
```

<Tip>
  En condiciones de carga normales, no verá `202`; solo sucede cuando todos los backends están saturados. `autoPoll: true` (el valor predeterminado) ya lo cubre sin código adicional en la mayoría de los casos.
</Tip>

<Warning>
  Los resultados de los trabajos completados caducan en aproximadamente 1 hora. Si guarda un `jobId` y recibe `404` al consultarlo, reenvíe la conversión original.
</Warning>
