# Envio em lote

> Cria múltiplas transações em uma única requisição (até 1000 por chamada).

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

Cria múltiplas transações em uma única requisição (até 1000 por chamada).

Use o envio em lote quando você precisa sincronizar grandes volumes (ex: carga inicial, reprocessamento de um dia inteiro). O processamento é por transação: o sucesso de uma não depende do sucesso das outras.

## Endpoint

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

## Autenticação

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

---

## Corpo da requisição

| Campo | Tipo | Descrição |
|---|---|---|
| `transactions` | array | Lista de transações (mín. 1, máx. 1000) |

Cada item do array segue o mesmo schema de [Criar transação](https://doc.rapidchargeback.com/canais/transactions/criar-transacao/): mesmos campos obrigatórios, opcionais, aninhados e validações.

---

## Validações

- O array `transactions` deve ter entre 1 e 1000 itens. Problema **no envelope** (array ausente, vazio ou acima de 1000) rejeita a requisição inteira
- O corpo da requisição pode ter até **5 MB**, o que cobre 1000 transações com todos os campos preenchidos. Acima disso a resposta é `413 PAYLOAD_TOO_LARGE` e nada é criado: divida em lotes menores
- Dentro do array, **cada transação é validada individualmente**: campo inválido, campo obrigatório ausente, texto acima do limite, duplicata, merchant inexistente. Tudo isso vira erro daquela linha
- Erro em uma linha **não** bloqueia as outras: as válidas são criadas e a resposta diz quais falharam
- Duplicata dentro do próprio lote (mesmo `external_source` e `external_id` duas vezes) cria a primeira e falha a segunda

---

## Exemplo de requisição

```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 }]
      }
    ]
  }'
```

---

## Exemplos de resposta

O lote responde **`200`**, e não `201`: numa chamada que cria algumas linhas e falha outras, o status sozinho não diz o resultado. Quem diz é o corpo. Confira sempre `failed` e `errors`, nunca só o código HTTP.

### Resultados mistos (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 item em `results` contém:
- `external_id`: identifica a transação no seu sistema.
- `tx_id`: UUID gerado pela Rapid (guarde para operações futuras).
- `warnings`: avisos de campos ausentes (não bloqueiam a criação).

Cada item em `errors` contém:
- `index`: posição da linha no array que você enviou, começando em zero. É por aqui que você localiza a linha quando o campo inválido é justamente o `external_id`.
- `external_id`: identifica qual transação falhou, ou string vazia se o valor enviado não era válido.
- `status`: código HTTP equivalente do erro (`422` validação, `404` merchant inexistente, `409` duplicata).
- `error`: mensagem descritiva.

`created + failed` é sempre o total de linhas enviadas. `results` e `errors` saem na ordem de entrada.

### Todas criadas com sucesso (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": []
  }
}
```

### Linha com campo inválido (200)

Uma linha reprovada na validação não derruba as outras: ela aparece em `errors` com `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)"
      }
    ]
  }
}
```

### Erro de validação do batch (fora do array)

Se o array `transactions` estiver vazio, faltando ou exceder 1000 itens, a requisição inteira é rejeitada:

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

---

## Comportamentos do lote que vale conhecer

- `merchant_ref` **desconhecido cria o vendedor** (com `merchant_name`, se enviado) e não retorna 404.
- Duplicata **dentro do mesmo lote** (mesmo `external_source`/`external_id` duas vezes) falha na segunda linha com `TRANSACTION_DUPLICATE`; a primeira é criada.
- A ordem de `results` é a ordem de entrada.
