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

# Crear transacciones en lote

> Crear múltiples transacciones en una sola llamada para escenarios de alto volumen — en la API de monitoreo transaccional gu1 para fraude y AML.

## Resumen

Crea múltiples transacciones en una sola operación en lote. Este endpoint está optimizado para alto volumen.

**Límites:**

* **Un solo lote:** hasta **100.000 transacciones** por petición; el cuerpo no debe superar **50 MB**.
* **Varios archivos en una llamada:** usar `POST /transactions/batch/background-multi` con un array `sources` (hasta **5 archivos**, 100.000 transacciones cada uno); límite del cuerpo **150 MB**.
* **Carga por archivos (multipart):** usar `POST /transactions/batch/upload` para enviar archivos CSV, Excel o JSON directamente; máx. **5 archivos** por petición. El límite por archivo depende de tu [plan](#límites-por-plan).

**Comportamiento (endpoint síncrono):**

* La API mantiene la conexión abierta hasta **30 segundos**.
* Si el lote **termina en 30 segundos**, responde **200** con el resumen completo (creadas, omitidas, reglas ejecutadas, tiempo, etc.).
* Si **supera 30 segundos**, responde **202** con un `jobId` y sigue procesando en segundo plano. Al terminar se notifica en el dashboard (y por socket en tiempo real si está conectado).

**Endpoints en segundo plano (siempre asíncronos):**

* `POST /transactions/batch/background` — Un solo lote; devuelve 202 de inmediato y notifica por socket al terminar.
* `POST /transactions/batch/background-multi` — Varios archivos en una petición (máx. 5); devuelve 202 y una notificación cuando se procesan todos.
* `POST /transactions/batch/upload` — **Multipart form-data:** enviar uno o más archivos (CSV, Excel, JSON) en el campo `file`; el servidor los parsea y ejecuta el mismo flujo. Ideal cuando tenés archivos en lugar de JSON.

Ideal para: importar histórico, archivos grandes (CSV, Excel, JSON), procesadores de pagos de alto volumen, migración de datos.

## Endpoints

```
POST http://api.gu1.ai/transactions/batch
POST http://api.gu1.ai/transactions/batch/background
POST http://api.gu1.ai/transactions/batch/background-multi
POST http://api.gu1.ai/transactions/batch/upload   (multipart/form-data)
```

## Carga por archivos (multipart)

Usá **`POST /transactions/batch/upload`** cuando tengas archivos CSV, Excel o JSON y quieras que el servidor los parsee. La petición debe ser **`multipart/form-data`** (FormData), no JSON.

* **Máx. 5 archivos** por petición.
* **Formatos aceptados:** CSV (`.csv`), Excel (`.xlsx`, `.xls`), JSON (`.json`).
* **Límite de transacciones por archivo** según el plan de la organización (ver [Límites por plan](#límites-por-plan)).
* **Query:** `validateGap` (por defecto `false`). Si enviás `validateGap=true` con varios archivos, la API comprueba que no haya un salto de tiempo de 30 minutos o más entre el fin de un archivo y el inicio del siguiente (por `transactedAt`). Si lo hay, devuelve **400** con `code: "GAP_VALIDATION_REQUIRED"` y la lista de saltos. Por defecto la validación está desactivada; usá `?validateGap=true` para activarla.

### Campos del form

| Campo                    | Tipo   | Requerido | Descripción                                                                         |
| ------------------------ | ------ | --------- | ----------------------------------------------------------------------------------- |
| `file`                   | File   | Sí        | Uno o más archivos (CSV, Excel, JSON). Repetí el campo `file` para varios archivos. |
| `executeRules`           | string | No        | `"true"` (default) o `"false"`                                                      |
| `skipDuplicates`         | string | No        | `"true"` (default) o `"false"`                                                      |
| `validateExistingEntity` | string | No        | `"true"` (default) o `"false"`                                                      |

### Ejemplo: envío con FormData (JavaScript)

```javascript theme={null}
const form = new FormData();
form.append('file', fileInput.files[0]);
form.append('executeRules', 'true');
form.append('skipDuplicates', 'true');
form.append('validateExistingEntity', 'true');

const response = await fetch('http://api.gu1.ai/transactions/batch/upload', {
  method: 'POST',
  headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
  body: form   // No pongas Content-Type; el navegador setea el boundary multipart
});
const data = await response.json();
```

### Ejemplo: cURL

```bash theme={null}
curl -X POST http://api.gu1.ai/transactions/batch/upload \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "file=@transacciones.csv" \
  -F "executeRules=true" \
  -F "skipDuplicates=true"
```

## Límites por plan

El **máximo de transacciones por archivo** (tanto en upload como en background-multi) depende del plan de la organización:

| Plan                    | Máx. transacciones por archivo |
| ----------------------- | ------------------------------ |
| Freemium                | 4.000                          |
| Startup                 | 12.000                         |
| Growth                  | 30.000                         |
| Enterprise              | 100.000                        |
| Por uso (pay-as-you-go) | 100.000                        |

Si la carga batch está deshabilitada para tu organización, los endpoints devuelven **403**. Contactá a soporte para habilitarla o cambiar de plan.

## Plantillas

Para armar archivos CSV, Excel o JSON que cumplan el esquema:

1. **Dashboard:** En **Monitoreo de transacciones**, abrí el modal **Carga batch**. Usá los botones **Descargar CSV**, **Descargar Excel** o **Descargar JSON** para obtener plantillas con los encabezados correctos y una fila de ejemplo. Es la forma más sencilla de empezar.
2. **Campos requeridos por fila:** Cada transacción debe incluir al menos `externalId`, `type`, `amount` y `currency`. Recomendados: `transactedAt`, `status`, `originName`, `destinationName`, `description`. Esquema completo en [Crear transacción](/es/api-reference/transactions/create).
3. **CSV/Excel:** Los nombres de columna pueden ser camelCase (`externalId`, `transactedAt`) o snake\_case (`external_id`, `transacted_at`); el servidor los normaliza. Fecha en ISO 8601 (ej. `2025-01-15T10:30:00.000Z`).

No hay una URL pública para descargar plantillas fuera del dashboard; usá el modal de carga batch para obtener las plantillas actualizadas.

## Autenticación

```bash theme={null}
Authorization: Bearer YOUR_API_KEY
```

## Cuerpo (sync y background)

<ParamField body="transactions" type="array" required>
  Array de objetos de transacción (mín. 1, máx. 100.000 por petición). Misma estructura que [Crear transacción](/es/api-reference/transactions/create). Cuerpo máx. 50 MB.

  **`exchangeRate` opcional por fila:** solo si falla la conversión automática; ver [Conversión de moneda](/es/api-reference/transactions/create#conversión-de-moneda).
</ParamField>

<ParamField body="executeRules" type="boolean" default="true">
  Si se ejecutan reglas para todas las transacciones del lote
</ParamField>

<ParamField body="skipDuplicates" type="boolean" default="true">
  Omitir transacciones con `externalId` duplicado en lugar de fallar todo el lote
</ParamField>

<ParamField body="validateExistingEntity" type="boolean" default="true">
  Con **`true`** (por defecto en lote): por cada fila, cada extremo (origen/destino) se valida solo si enviaste al menos un identificador de ese extremo (`*EntityId`, `*ExternalId` o `*TaxId` en raíz). Cada campo enviado debe existir en la org; si no, **400** `INVALID_ENTITY_REFERENCES` y **ninguna** transacción del lote se crea (según `batchErrorHandling`). El orden de auto-vinculación sigue siendo: entityId → externalId → taxId.

  Con **`false`**: mismo comportamiento permisivo que [Crear transacción](/es/api-reference/transactions/create) (default **`false`** ahí) — referencias sin match no bloquean el lote.
</ParamField>

Si hay match en el paso 2 o 3, se rellenan `*EntityId` y, si no enviaste nombre/país, se pueden rellenar `*Name` y `*Country` desde la entidad (como en creación individual).

Cuando un extremo queda vinculado (incluso si ya enviaste `*EntityId`), **`originTaxId` / `originExternalId` y `destinationTaxId` / `destinationExternalId` se sincronizan siempre desde la entidad** antes del insert — misma denormalización canónica que [Crear transacción — origen](/es/api-reference/transactions/create#origen-entidad).

### Cuerpo (solo background-multi)

<ParamField body="sources" type="array" required>
  Array de objetos: `{ "fileName": "opcional", "transactions": [ ... ] }`. Mín. 1, máx. 5 fuentes. Cada `transactions`: máx. 100.000 (o el límite de tu plan por archivo). Cuerpo total máx. 150 MB.
</ParamField>

## Respuesta 200 (completado en 30 s)

<ResponseField name="success" type="boolean">
  Si la operación en lote se completó correctamente
</ResponseField>

<ResponseField name="created" type="number">
  Número de transacciones creadas
</ResponseField>

<ResponseField name="skipped" type="number">
  Omitidas (duplicados o errores de validación)
</ResponseField>

<ResponseField name="failed" type="number">
  Fallidas
</ResponseField>

<ResponseField name="transactions" type="array">
  Transacciones creadas
</ResponseField>

<ResponseField name="errors" type="array">
  Errores por transacción: `index`, `externalId`, `error`, `code`
</ResponseField>

<ResponseField name="processingTime" type="string">
  Tiempo total de procesamiento
</ResponseField>

## Respuesta 202 (procesamiento > 30 s o background)

<ResponseField name="jobId" type="string">
  Identificador del job; correlacionar con la notificación en tiempo real al completar
</ResponseField>

<ResponseField name="status" type="string">
  `"processing"`
</ResponseField>

<ResponseField name="message" type="string">
  Mensaje indicando que el proceso continúa en segundo plano y se notificará en el dashboard
</ResponseField>

<ResponseField name="fileCount" type="number">
  (Solo background-multi.) Número de archivos en proceso
</ResponseField>

## Ejemplo de uso

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST http://api.gu1.ai/transactions/batch \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "transactions": [
        {
          "externalId": "txn_001",
          "type": "PAYMENT",
          "amount": 50.00,
          "currency": "USD",
          "originExternalId": "customer_001",
          "destinationExternalId": "merchant_100",
          "channel": "web_browser"
        }
      ],
      "executeRules": true,
      "skipDuplicates": true
    }'
  ```

  ```python Python theme={null}
  import requests
  response = requests.post(
      'http://api.gu1.ai/transactions/batch',
      headers={'Authorization': f'Bearer {API_KEY}', 'Content-Type': 'application/json'},
      json={
          'transactions': transactions,
          'executeRules': True,
          'skipDuplicates': True
      }
  )
  result = response.json()
  print(f"Creadas: {result['created']}, Omitidas: {result['skipped']}, Fallidas: {result['failed']}")
  ```
</CodeGroup>

## Errores

* **400** - Lote vacío o tamaño excedido (máx. 100.000 por request)
* **413** - Cuerpo > 50 MB (o 150 MB en multi). Dividir en lotes más pequeños.

## Buenas prácticas

1. Respetar límites: 100.000 por request, 50 MB (150 MB multi).
2. Usar siempre `skipDuplicates: true`.
3. Para importación histórica: `executeRules: false` y opcionalmente `validateExistingEntity: false`.
4. Manejar 200 vs 202: 200 = resultado en el cuerpo; 202 = job en background, esperar notificación.
5. Validar campos requeridos según [Crear transacción](/es/api-reference/transactions/create).
6. Usar background-multi para muchos archivos (hasta 10 en una llamada).

## Próximos pasos

* [Crear transacción](/es/api-reference/transactions/create) - Una transacción
* [Cambiar estado de transacción](/es/use-cases/transaction-monitoring/change-status-api) - Cambiar estado
* [Monitoreo de transacciones](/es/use-cases/transaction-monitoring/overview) - Detección de fraude
