# Envío por lotes

> Crea varias transacciones en una sola solicitud (hasta 1000 por llamada).

Página: https://doc.rapidchargeback.com/es/canais/transactions/envio-em-lote/

Crea varias transacciones en una sola solicitud (hasta 1000 por llamada).

Usa el envío por lotes cuando necesitas sincronizar grandes volúmenes (ej.: carga inicial, reprocesamiento de un día entero). El procesamiento es por transacción: el éxito de una no depende del éxito de las demás.

## Endpoint

```
POST https://api.rapidchargeback.com/api/v1/transactions/batch
```

## Autenticación

```
Authorization: Basic base64(client_id:client_secret)
Content-Type: application/json
```

---

## Cuerpo de la solicitud

| Campo | Tipo | Descripción |
|---|---|---|
| `transactions` | array | Lista de transacciones (mín. 1, máx. 1000) |

Cada ítem del array sigue el mismo schema de [Crear transacción](https://doc.rapidchargeback.com/es/canais/transactions/criar-transacao/): los mismos campos obligatorios, opcionales y anidados, y las mismas validaciones.

---

## Validaciones

- El array `transactions` debe tener entre 1 y 1000 ítems. Un problema **en el envoltorio** (array ausente, vacío o con más de 1000) rechaza la solicitud entera
- El cuerpo de la solicitud puede tener hasta **5 MB**, lo que cubre 1000 transacciones con todos los campos completos. Por encima de eso la respuesta es `413 PAYLOAD_TOO_LARGE` y no se crea nada: divídelo en lotes más chicos
- Dentro del array, **cada transacción se valida individualmente**: campo inválido, campo obligatorio ausente, texto por encima del límite, duplicado, merchant inexistente. Todo eso se convierte en error de esa línea
- Un error en una línea **no** bloquea las demás: las válidas se crean y la respuesta indica cuáles fallaron
- Un duplicado dentro del propio lote (mismo `external_source` y `external_id` dos veces) crea la primera y hace fallar la segunda

---

## Ejemplo de solicitud

```bash
curl -X POST https://api.rapidchargeback.com/api/v1/transactions/batch \
  -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" \
  -H "Content-Type: application/json" \
  -d '{
    "transactions": [
      {
        "merchant_id": "00000000-0000-0000-0000-000000000001",
        "external_source": "custom",
        "external_id": "TXN-2026-001",
        "transaction_date": "2026-04-01T10:00:00Z",
        "amount": 150.00,
        "currency": "USD",
        "card_last4": "4242",
        "items": [{ "product_description": "Item A", "unit_price": 150.00 }]
      },
      {
        "merchant_id": "00000000-0000-0000-0000-000000000001",
        "external_source": "custom",
        "external_id": "TXN-2026-002",
        "transaction_date": "2026-04-01T11:00:00Z",
        "amount": 200.00,
        "currency": "BRL",
        "card_last4": "1234",
        "items": [{ "product_description": "Item B", "unit_price": 200.00 }]
      }
    ]
  }'
```

---

## Ejemplos de respuesta

El lote responde **`200`**, no `201`: en una llamada que crea algunas líneas y falla otras, el estado por sí solo no dice el resultado. Lo dice el cuerpo. Revisa siempre `failed` y `errors`, nunca solo el código HTTP.

### Resultados mixtos (200)

```json
{
  "data": {
    "created": 1,
    "failed": 1,
    "results": [
      {
        "external_id": "TXN-2026-001",
        "tx_id": "00000000-0000-0000-0000-000000000042",
        "warnings": ["card_bin missing: reduces match accuracy"]
      }
    ],
    "errors": [
      {
        "index": 1,
        "external_id": "TXN-2026-002",
        "status": 409,
        "error": "Transaction already exists"
      }
    ]
  }
}
```

Cada ítem en `results` contiene:
- `external_id`: identifica la transacción en tu sistema.
- `tx_id`: UUID generado por Rapid (guárdalo para operaciones futuras).
- `warnings`: avisos de campos ausentes (no bloquean la creación).

Cada ítem en `errors` contiene:
- `index`: posición de la línea en el array que enviaste, empezando en cero. Es así como ubicas la línea cuando el campo inválido es justamente el `external_id`.
- `external_id`: identifica qué transacción falló, o string vacío si el valor enviado no era válido.
- `status`: código HTTP equivalente del error (`422` validación, `404` merchant inexistente, `409` duplicado).
- `error`: mensaje descriptivo.

`created + failed` es siempre el total de líneas enviadas. `results` y `errors` salen en el orden de entrada.

### Todas creadas con éxito (200)

```json
{
  "data": {
    "created": 2,
    "failed": 0,
    "results": [
      { "external_id": "TXN-2026-001", "tx_id": "uuid-1", "warnings": [] },
      { "external_id": "TXN-2026-002", "tx_id": "uuid-2", "warnings": [] }
    ],
    "errors": []
  }
}
```

### Línea con un campo inválido (200)

Una línea rechazada en la validación no tumba a las demás: aparece en `errors` con `status: 422`.

```json
{
  "data": {
    "created": 1,
    "failed": 1,
    "results": [
      { "external_id": "TXN-2026-001", "tx_id": "uuid-1", "warnings": [] }
    ],
    "errors": [
      {
        "index": 1,
        "external_id": "TXN-2026-002",
        "status": 422,
        "error": "Currency must be 3 uppercase letters (ISO 4217)"
      }
    ]
  }
}
```

### Error de validación del batch (fuera del array)

Si el array `transactions` está vacío, falta o supera los 1000 ítems, se rechaza la solicitud entera:

```json
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Array must contain at most 1000 element(s)"
  }
}
```

---

## Comportamientos del lote que vale la pena conocer

- Un `merchant_ref` **desconocido crea el vendedor** (con `merchant_name`, si se envía) y no devuelve 404.
- Un duplicado **dentro del mismo lote** (mismo `external_source`/`external_id` dos veces) falla en la segunda línea con `TRANSACTION_DUPLICATE`; la primera se crea.
- El orden de `results` es el orden de entrada.
