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

# Biblioteca cliente de JavaScript

> Instala, inicializa, mapea métodos a endpoints y gestiona errores con el SDK oficial de JavaScript/TypeScript octoparse-client.

`octoparse-client` es el cliente oficial de JavaScript/TypeScript para Data Hub. Solo encapsula la API REST pública `/v1` y no tiene dependencias de tiempo de ejecución. Los métodos se mapean uno a uno a los endpoints, los nombres de parámetros siguen camelCase en el lado del cliente y se convierten a snake\_case de REST, y los valores devueltos son la carga útil `data` en bruto. Versión actual 0.2.9, Node.js 18+.

## Instalar

```bash theme={null}
npm install octoparse-client
```

## Inicializar

```js theme={null}
import { Client } from "octoparse-client";

const client = new Client({ apiKey: "<your API key>" });
```

| Parámetro | Descripción                                                                                                                                                                     |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `apiKey`  | API key de Data Hub. Si se omite, lee `OCTOPARSE_API_KEY`. Si sigue faltando, el cliente es anónimo y solo puede llamar endpoints anónimos.                                     |
| `baseUrl` | URL del servicio. Si se omite, lee `OCTOPARSE_BASE_URL`, con valor por defecto `https://api-datahub.octoparse.com`. Pásala de forma explícita en entornos locales o de staging. |
| `timeout` | Timeout HTTP por petición en milisegundos. Por defecto 90000.                                                                                                                   |

## Mapa método-endpoint

| Método                                                              | Endpoint                                  | Notas                                                       |
| ------------------------------------------------------------------- | ----------------------------------------- | ----------------------------------------------------------- |
| `meta()`                                                            | `GET /v1/meta`                            | Constantes de la plataforma                                 |
| `search(q, { limit, offset, ... })`                                 | `GET /v1/data-apps`                       | Una página de tarjetas, con `pagination`                    |
| `getApp(appId)`                                                     | `GET /v1/data-apps/{app_id}`              | Detalle completo de la app                                  |
| `run(appId, inputs, { wait, maxRecords, version, build })`          | `POST /v1/data-apps/{app_id}/runs`        | Iniciar una ejecución                                       |
| `call(appId, inputs, { maxRecords, timeout, raiseOnFailure, ... })` | `POST` + sondeo                           | Ayudante bloqueante: espera hasta estado terminal o timeout |
| `getRun(runId, { wait })`                                           | `GET /v1/runs/{run_id}`                   | Estado y snapshot de facturación                            |
| `listRunsPage(filters)`                                             | `GET /v1/runs`                            | Una página de ejecuciones, con `pagination`                 |
| `listRuns(filters)`                                                 | `GET /v1/runs`                            | Una página de ejecuciones, solo ítems                       |
| `iterateRuns(filters)`                                              | `GET /v1/runs`                            | Iterador asíncrono que pagina automáticamente               |
| `cancel(runId)`                                                     | `POST /v1/runs/{run_id}/cancel`           | Cancelar una ejecución                                      |
| `getRecords(runId, { offset, limit, fields })`                      | `GET /v1/runs/{run_id}/records`           | Una página de registros de resultado                        |
| `iterateRecords(runId, { batch, fields })`                          | `GET /v1/runs/{run_id}/records`           | Iterador asíncrono que pagina automáticamente               |
| `exportRecords(runId, format)`                                      | `GET /v1/runs/{run_id}/records`           | Exportación completa como texto `jsonl` / `csv`             |
| `listDatasets({ offset, limit })`                                   | `GET /v1/datasets`                        | Lista de datasets                                           |
| `setDatasetRetention(datasetId, retained)`                          | `PUT /v1/datasets/{dataset_id}/retention` | Establecer el flag de retención                             |
| `getDatasetRecords(datasetId, { offset, limit, fields })`           | `GET /v1/datasets/{dataset_id}/records`   | Una página de registros del dataset                         |
| `iterateDatasetRecords(datasetId, { batch, fields })`               | `GET /v1/datasets/{dataset_id}/records`   | Iterador asíncrono que pagina automáticamente               |
| `account()`                                                         | `GET /v1/account`                         | Info de cuenta y gasto acumulado                            |
| `billing({ groupBy, createdFrom, createdTo, tzOffset })`            | `GET /v1/billing`                         | Agregación de facturación                                   |

Los `filters` de listado de ejecuciones admiten `status`, `dataApp`, `triggeredBy`, `runKind`, `credential`, `createdFrom`, `createdTo`, más `offset` / `limit`. Los endpoints de publicación, operaciones y secrets no están encapsulados; llama a REST directamente.

## Uso típico

```js theme={null}
import { Client, ApiError, RunFailed } from "octoparse-client";

const client = new Client({ apiKey: "<your API key>" });

// Descubrir
const { items } = await client.search("reviews", { limit: 5 });
for (const card of items) console.log(card.app_id, card.namespace, card.app_name);
const detail = await client.getApp("carol/reviews-query");

// Ejecutar y consumir. Los timeouts son en milisegundos. TimeoutError no cancela la ejecución en el servidor.
const run = await client.call("carol/reviews-query", { product: "p-9001" }, {
  maxRecords: 100, timeout: 120_000, raiseOnFailure: true,
});
for await (const record of client.iterateRecords(run.run_id)) {
  console.log(record);
}

// No bloqueante: inicia y luego sondea tú mismo
const started = await client.run("carol/reviews-query", { product: "p-9002" }, { wait: 0 });
const polled = await client.getRun(started.run_id, { wait: 60 });

// Conciliar el gasto
console.log(await client.billing({ groupBy: "data_app", tzOffset: 480 }));
for await (const r of client.iterateRuns({ createdFrom: "2026-09-01T00:00:00+08:00" })) {
  console.log(r.run_id, r.status, r.billing.total);
}

// Los resultados se conservan 90 días por defecto; marca los datasets que necesites más tiempo
await client.setDatasetRetention(run.dataset_id, true);
```

## Gestión de errores

Las respuestas de error de la API lanzan `ApiError` (extiende `Error`). Los campos coinciden con el objeto REST `error`:

| Propiedad    | Significado                                                                       |
| ------------ | --------------------------------------------------------------------------------- |
| `statusCode` | Estado HTTP                                                                       |
| `code`       | Id estable del error para ramificar                                               |
| `category`   | Clase amplia                                                                      |
| `message`    | Descripción en inglés                                                             |
| `retryable`  | Si la misma petición se puede reintentar                                          |
| `details`    | Problemas a nivel de campo en fallos de validación de entrada; si no, `undefined` |

```js theme={null}
import { ApiError } from "octoparse-client";

try {
  await client.run("carol/reviews-query", {});
} catch (e) {
  if (e instanceof ApiError && e.code === "invalid-input") {
    for (const d of e.details ?? []) console.log(d.path, d.message);
  } else if (e instanceof ApiError && e.retryable) {
    // retroceder y reintentar
  } else {
    throw e;
  }
}
```

`RunFailed` se lanza cuando `call()` usa `raiseOnFailure: true` y la ejecución termina en `FAILED` / `CANCELLED` / `EXPIRED`. Su propiedad `run` contiene el objeto de ejecución completo.

## Referencias de app

`getApp()`, `run()`, `call()` y el filtro `dataApp` del listado de ejecuciones aceptan ambas formas: dos segmentos `<namespace>/<app_name>` (legible, se rompe tras un renombre) e `app_id` estable (`app_<hex>`, sobrevive al renombre). En integraciones de larga duración, guarda `app_id`. Las apps compartidas punto a punto no aparecen en la búsqueda del marketplace; usa `search("", { sharedWith: "me" })`.
