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

# Archivos entre pasos

> Crea, consulta y reutiliza PDF, JSON, XML, hojas de cálculo y otros archivos dentro de una automatización.

Los pasos de una automatización pueden producir dos tipos de resultado:

```text theme={null}
output  → datos JSON
files   → archivos
```

Por ejemplo, el step de GNP devuelve el resumen en `output`, y en `files` deja
las pólizas ya normalizadas más el XLSX original.

No necesitas conocer el bucket, descargar URLs temporales ni copiar referencias
al `input` del siguiente paso. La automatización conserva los archivos y los
pone automáticamente a disposición de los pasos posteriores.

## Modelo mental

```text theme={null}
Paso 0: reporte de GNP
├── output: resumen y referencias
└── files: dataset.json, ExportResult.xlsx
             │
             ▼
Paso 1: JavaScript
└── files.fromStep(0)
```

Los índices de los pasos empiezan en cero:

| Paso visible | Índice |
| ------------ | ------ |
| Primer paso  | `0`    |
| Segundo paso | `1`    |
| Tercer paso  | `2`    |

## Leer archivos de un paso anterior

Dentro de `code.javascript`, usa:

```javascript theme={null}
const receiptFiles = files.fromStep(0);
```

`receiptFiles` es un arreglo. Cada archivo contiene metadatos:

```json theme={null}
{
  "id": "<file-id>",
  "name": "Recibo_000001.pdf",
  "type": "application/pdf",
  "size": 192530,
  "sha256": "<sha256>",
  "sourceStepIndex": 0
}
```

<Warning>
  Si el paso anterior publica más de un archivo, selecciónalo **por nombre** y no
  por posición. El orden del arreglo no es parte del contrato del paso y puede
  cambiar entre versiones:

  ```javascript theme={null}
  const reporte = files.fromStep(0).find((file) => file.name === "dataset.json");
  ```
</Warning>

Los bytes se descargan únicamente cuando los solicitas:

```javascript theme={null}
const [pdf] = files.fromStep(0);

if (!pdf) {
  throw new Error("El paso 0 no produjo archivos");
}

const bytes = await pdf.bytes();

output = {
  name: pdf.name,
  type: pdf.type,
  size: pdf.size,
  loadedBytes: bytes.length
};
```

<Info>
  `files.fromStep(0)` no agrega el contenido del archivo al payload del
  workflow. El contenido se carga de forma privada cuando llamas `bytes()`,
  `text()`, `json()` o `xlsx()`.
</Info>

## Leer texto, JSON o XML

### JSON

```javascript theme={null}
const [report] = files.fromStep(0);
const data = await report.json();

output = {
  records: data.records.length
};
```

### XML o texto

```javascript theme={null}
const [xmlFile] = files.fromStep(0);
const xml = await xmlFile.text();

output = {
  containsPolicy: xml.includes("<Policy>")
};
```

### Hojas de cálculo (XLSX)

Un XLSX es un contenedor comprimido, así que `text()` no sirve para leerlo. Usa
`xlsx()`, que devuelve las hojas con el texto de cada celda:

```javascript theme={null}
const [reporte] = files.fromStep(0);

const { sheets } = await reporte.xlsx();
const [encabezados, ...filas] = sheets[0].rows;

const registros = filas.map((fila) =>
  Object.fromEntries(encabezados.map((encabezado, i) => [encabezado, fila[i]])),
);

output = {
  hoja: sheets[0].name,
  total: registros.length,
  primero: registros[0]
};
```

La forma que devuelve es:

```json theme={null}
{
  "sheets": [
    {
      "name": "Pendientes",
      "rows": [
        ["No. de Póliza", "Ramo", "Monto"],
        ["000123", "Vida", "$0.00 MXN"]
      ]
    }
  ]
}
```

Cada celda llega como texto ya recortado, tal como se ve en la hoja. Las filas
completamente vacías se omiten. Si necesitas números o fechas, conviértelos tú
en el mismo paso.

Cuando los bytes no vienen de un archivo del workflow, por ejemplo si los
descargaste con `fetch` o `axios`, usa el global `xlsx`:

```javascript theme={null}
const response = await fetch("https://ejemplo.com/reporte.xlsx");
const { sheets } = await xlsx.read(await response.arrayBuffer());

output = { filas: sheets[0].rows.length };
```

`xlsx.read` acepta `Uint8Array`, `Buffer` y `ArrayBuffer`.

### Contenido binario

```javascript theme={null}
const [pdf] = files.fromStep(0);
const bytes = await pdf.bytes();

const response = await fetch("https://api.ejemplo.com/documentos", {
  method: "PUT",
  headers: {
    "Content-Type": pdf.type,
    "X-Filename": pdf.name
  },
  body: bytes
});

output = {
  sent: response.ok,
  status: response.status
};
```

## Crear un archivo

Un step JavaScript también puede crear archivos:

```javascript theme={null}
const report = await files.create({
  name: "resultado.json",
  type: "application/json",
  data: JSON.stringify({
    generatedAt: new Date().toISOString(),
    records: input.records
  })
});

output = {
  generatedFileId: report.id
};
```

El archivo creado aparecerá automáticamente en:

```text theme={null}
files.fromStep(índice-del-step)
```

para todos los pasos posteriores.

`data` acepta:

* `string`;
* `Buffer`;
* `Uint8Array`;
* `ArrayBuffer`.

## Ejemplo completo: GNP y su reporte XLSX

```json theme={null}
{
  "name": "Procesar reporte pendiente GNP",
  "status": "disabled",
  "trigger": {
    "type": "webhook"
  },
  "steps": [
    {
      "name": "Reporte de pólizas pendientes en GNP",
      "actionKey": "gnp.pending-receipts",
      "credentialId": "cred_0123456789ab"
    },
    {
      "name": "Contar filas por conducto",
      "actionKey": "code.javascript",
      "code": "const [reporte] = files.fromStep(0);\nif (!reporte) {\n  throw new Error('El paso 0 no publicó el reporte');\n}\nconst { sheets } = await reporte.xlsx();\nconst [encabezados, ...filas] = sheets[0].rows;\nconst columna = encabezados.indexOf('Conducto');\nconst porConducto = {};\nfor (const fila of filas) {\n  const conducto = fila[columna];\n  porConducto[conducto] = (porConducto[conducto] ?? 0) + 1;\n}\noutput = { archivo: reporte.name, filas: filas.length, porConducto };"
    }
  ]
}
```

El segundo paso no declara `input.files`. Los archivos del paso 0 están
disponibles automáticamente.

## Límite y seguridad

* Máximo `100 MB` por archivo.
* Sólo puedes leer archivos de pasos anteriores de la misma ejecución.
* Un step no puede leer archivos de otro tenant o de otra run.
* Las referencias no exponen bucket, ruta interna ni URL persistente.
* El contenido y las URLs temporales no se guardan en logs.
* El sistema verifica tamaño y SHA-256 al leer.

Si un archivo supera 100 MB, la operación falla explícitamente. El archivo no
se trunca.

## Errores frecuentes

| Error                             | Causa                                                                          | Solución                                                                          |
| --------------------------------- | ------------------------------------------------------------------------------ | --------------------------------------------------------------------------------- |
| `files.fromStep(0)` devuelve `[]` | El paso no produjo archivos o todavía no terminó.                              | Confirma que el paso anterior terminó exitosamente y generó documentos.           |
| `WORKFLOW_FILE_TOO_LARGE`         | El archivo supera 100 MB.                                                      | Reduce el tamaño o divide el archivo antes de guardarlo.                          |
| `WORKFLOW_FILE_CHECKSUM_MISMATCH` | El contenido no coincide con su referencia.                                    | Reintenta la ejecución; no reutilices referencias externas.                       |
| `WORKFLOW_FILE_ACCESS_DENIED`     | La referencia pertenece a otra run o a un paso posterior.                      | Usa únicamente valores obtenidos con `files.fromStep()`.                          |
| `json()` falla                    | El contenido no es JSON válido.                                                | Usa `text()` o valida el tipo antes de parsear.                                   |
| `WORKFLOW_XLSX_NOT_A_SPREADSHEET` | Le pasaste a `xlsx()` un archivo que no es XLSX. El mensaje nombra el archivo. | Selecciónalo por nombre. Un JSON se lee con `json()` y un CSV con `text()`.       |
| `WORKFLOW_XLSX_PARSE_FAILED`      | El archivo es una hoja de cálculo pero está corrupta o incompleta.             | Reintenta la ejecución; si persiste, revisa el archivo en el paso que lo produjo. |
| `WORKFLOW_XLSX_INVALID_INPUT`     | Le pasaste a `xlsx.read` algo que no son bytes.                                | Usa `Uint8Array`, `Buffer` o `ArrayBuffer`.                                       |

## Relacionado

* [Paso JavaScript](/automatizaciones/paso-javascript)
* [Reporte de pólizas y recibos pendientes en GNP](/automatizaciones/paso-gnp-recibos-vencidos)
* [Tipos de paso](/automatizaciones/tipos-de-paso)
* [Crear automatización](/automatizaciones/crear-automatizacion)
