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

# Carga masiva (lotes)

> Emita muchos DTE de una sola vez subiendo un archivo Excel: crear el lote, seguir su estado y obtener los resultados por fila.

Un **lote** permite emitir muchos DTE de una sola vez: en vez de llamar `POST /dte` documento por documento, se sube un archivo Excel con una fila por documento (y sus ítems), y un proceso asíncrono de Fegora emite cada documento por su cuenta.

<Tip>
  Si prefiere no armar el archivo por API, la aplicación web de Fegora ofrece una pantalla de carga guiada — vea [Carga masiva (guía de usuario)](/guia-web/carga-masiva).
</Tip>

## Crear un lote: `POST /lote`

```bash theme={null}
curl -X POST https://api.fegora.com/lote \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...ejemplo" \
  -H "Content-Type: application/json" \
  -d '{
        "idCuenta": "12345678",
        "archivo": "UEsDBBQABgAIAAAAIQBBN4LPbgEAAAQFAAATAAgC...ejemplo-base64-xlsx"
      }'
```

| Campo      | Tipo            | Obligatorio | Descripción                                            |
| ---------- | --------------- | ----------- | ------------------------------------------------------ |
| `idCuenta` | string          | Sí          | Cuenta emisora sobre la que se crearán los documentos. |
| `archivo`  | string (base64) | Sí          | Contenido del archivo Excel, codificado en base64.     |

### Respuesta

```json theme={null}
{
  "id": "030b57e5-c84a-4376-813d-150bdd933151",
  "idCuenta": "12345678",
  "estado": "Creado",
  "archivoUri": "https://cdn.fegora.com/lotes/12345678_20260712155000.xlsx",
  "resultadoArchivoUri": null,
  "cantidadOperaciones": 25,
  "cantidadOperacionesEjecutadas": 0,
  "cantidadOperacionesError": 0,
  "cantidadOperacionesPendientesEjecucion": 25,
  "fechaCreacion": "2026-07-12T15:50:00",
  "usuarioCreacion": "integracion@empresa-ejemplo.com"
}
```

Al crear el lote, Fegora ya valida el archivo y calcula `cantidadOperaciones` contando las filas no vacías de la columna `OPERACION` (menos el encabezado). Si el archivo no puede leerse, no tiene hojas, no tiene filas o falta la columna `OPERACION`, la solicitud falla con `400` y uno de los códigos `LOT-INVEXC-2`..`LOT-INVEXC-5`.

## Formato del archivo Excel

* **Extensión: `.xlsx` únicamente.** La validación al crear el lote usa una librería que no lee el formato antiguo `.xls` — un archivo `.xls` es rechazado con `LOT-INVEXC-2` antes de procesarse.
* La primera fila debe contener los encabezados de columna (nombres exactos, sin distinguir mayúsculas/minúsculas).
* Cada documento ocupa **una fila de encabezado** (con la columna `OPERACION` en `CREAR`) seguida de **una o más filas de detalle** (una por ítem, sin valor en `OPERACION`), hasta la siguiente fila `CREAR` o hasta 5 filas vacías consecutivas.

<Warning>
  El procesador de lotes actual sólo reconoce `TIPO`: `factura`, `notaCredito` o `facturaEspecial` (sin distinguir mayúsculas/minúsculas). Para emitir otros tipos de documento en volumen (`notaDebito`, `recibo`, tipos SV/DO, etc.), use `POST /dte` directamente en un ciclo desde su sistema, o confirme con Fegora si el procesador de lotes ya soporta más tipos.
</Warning>

### Columnas de encabezado del documento

| Columna                                                                                                            | Descripción                                                                                       |
| ------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------- |
| `OPERACION`                                                                                                        | `CREAR` marca el inicio de un nuevo documento en esa fila.                                        |
| `CODIGO_ESTABLECIMIENTO`                                                                                           | Código de establecimiento del emisor.                                                             |
| `TIPO`                                                                                                             | `factura`, `notaCredito` o `facturaEspecial`.                                                     |
| `NUMERO_TRANSACCION`                                                                                               | Número de transacción propio, para evitar duplicados.                                             |
| `FECHA` (o `FECHA_ANIO` / `FECHA_MES` / `FECHA_DIA`)                                                               | Fecha de emisión.                                                                                 |
| `MONEDA`                                                                                                           | Moneda del documento.                                                                             |
| `ID_RECEPTOR`                                                                                                      | Identificador fiscal del receptor (`CF` para consumidor final).                                   |
| `NOMBRE_RECEPTOR`                                                                                                  | Nombre del receptor.                                                                              |
| `DIRECCION_RECEPTOR` / `MUNICIPIO_RECEPTOR` / `DEPARTAMENTO_RECEPTOR` / `PAIS_RECEPTOR` / `CODIGO_POSTAL_RECEPTOR` | Dirección del receptor.                                                                           |
| `DIRECCION_CORREO_ELECTRONICO_RECEPTOR`                                                                            | Correo del receptor.                                                                              |
| `DATO_ADICIONAL_1_NOMBRE` / `_ETIQUETA` / `_VALOR` / `_VISIBLE` (y `_2_`, `_3_`)                                   | Hasta 3 datos adicionales a nivel de documento — vea [Datos adicionales](/dte/datos-adicionales). |
| `ABONO_PACTADO_1_FECHA` / `_MONTO` (hasta `_5_`)                                                                   | Hasta 5 abonos pactados — vea [Casos especiales](/dte/casos-especiales).                          |

### Columnas de detalle (una fila por ítem)

| Columna                                                                                | Descripción                                |
| -------------------------------------------------------------------------------------- | ------------------------------------------ |
| `LINEA_DESCRIPCION`                                                                    | Descripción del ítem.                      |
| `LINEA_TIPO`                                                                           | `bien` o `servicio`.                       |
| `LINEA_CANTIDAD`                                                                       | Cantidad.                                  |
| `LINEA_PRECIO_UNITARIO` / `LINEA_PRECIO`                                               | Precio unitario o precio de línea.         |
| `LINEA_DESCUENTO`                                                                      | Descuento del ítem.                        |
| `LINEA_IMPUESTO_1_NOMBRE_CORTO`                                                        | Nombre corto del impuesto (p. ej. `IVA`).  |
| `LINEA_DATO_ADICIONAL_1_NOMBRE` / `_ETIQUETA` / `_VALOR` / `_VISIBLE` (y `_2_`, `_3_`) | Hasta 3 datos adicionales a nivel de ítem. |

{/* TODO(review): no se encontró un límite de filas activamente impuesto por el procesador de lotes actual — el código define una constante interna de 3,000 filas, pero la validación que la aplicaría está deshabilitada (comentada) en el código revisado. La aplicación web sí limita la carga a 1,000 filas desde su propia interfaz (vea /guia-web/carga-masiva), pero eso es un límite de esa pantalla, no del API. Confirmar con el equipo cuál es el límite real/soportado antes de publicar una cifra concreta aquí; mientras tanto, se recomienda mantener los archivos en un tamaño moderado aunque el backend no lo exija hoy. */}

## Seguir el estado: `GET /lote/{id}`

```bash theme={null}
curl -X GET https://api.fegora.com/lote/030b57e5-c84a-4376-813d-150bdd933151 \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...ejemplo"
```

```json theme={null}
{
  "id": "030b57e5-c84a-4376-813d-150bdd933151",
  "estado": "procesado",
  "archivoUri": "https://cdn.fegora.com/lotes/12345678_20260712155000.xlsx",
  "resultadoArchivoUri": "https://cdn.fegora.com/lotes/12345678_20260712155000-resultado.xlsx",
  "cantidadOperaciones": 25,
  "cantidadOperacionesEjecutadas": 23,
  "cantidadOperacionesError": 2,
  "cantidadOperacionesPendientesEjecucion": 0,
  "fechaCreacion": "2026-07-12T15:50:00",
  "ultimaFechaEdicion": "2026-07-12T15:52:30"
}
```

<Warning>
  El valor de `estado` no sigue un catálogo cerrado ni una capitalización consistente en el API actual: al crear el lote se observa `"Creado"`, y el proceso de emisión de Fegora luego lo actualiza a `"enProceso"` y finalmente `"procesado"` (minúscula). No existe un estado `"Error"` propio del lote — un lote puede terminar en `"procesado"` con `cantidadOperacionesError` mayor a cero, indicando que algunas filas fallaron aunque el lote en sí ya terminó de procesarse. Compare `estado` sin distinguir mayúsculas/minúsculas y guíese por los contadores (`cantidadOperacionesEjecutadas`, `cantidadOperacionesError`, `cantidadOperacionesPendientesEjecucion`) para el progreso real, no sólo por el texto de `estado`.
</Warning>

Mientras `cantidadOperacionesPendientesEjecucion` sea mayor a cero, siga consultando este endpoint periódicamente hasta que llegue a cero.

## Actualizar un lote: `PATCH /lote/{id}`

Fegora usa esta misma ruta internamente para reportar el avance del procesamiento. Como integrador normalmente sólo necesita **leer** el lote (`GET /lote/{id}`), pero la ruta de actualización acepta los mismos campos:

```json theme={null}
{
  "estado": "procesado",
  "cantidadOperacionesEjecutadas": 23,
  "cantidadOperacionesError": 2,
  "cantidadOperacionesPendientesEjecucion": 0
}
```

Todos los campos son opcionales — sólo se actualizan los que se envían.

## Obtener los resultados por fila

Cuando el lote termina de procesarse, `resultadoArchivoUri` (si está disponible) apunta a un archivo con el detalle de cada fila, incluidas las que fallaron.

## Páginas relacionadas

<Columns cols={2}>
  <Card title="Carga masiva (guía de usuario)" icon="upload" href="/guia-web/carga-masiva">
    La misma funcionalidad desde la aplicación web, sin usar el API directamente.
  </Card>

  <Card title="Casos especiales" icon="puzzle" href="/dte/casos-especiales">
    Plantillas reutilizables, resguardo de XML y otros flujos fuera de la emisión estándar.
  </Card>
</Columns>
