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

# Envio em Lote

> Como enviar campanhas com mais de 2.000 destinatários

Cada chamada à API aceita no máximo **2.000 mensagens**. Para campanhas maiores, você tem duas opções:

1. **Batches independentes** — cada chamada usa um `campaignId` diferente. Cada um é uma campanha separada no dashboard.
2. **Batches incrementais** — múltiplas chamadas usam o **mesmo `campaignId` e `name`**, com o campo `batch` obrigatório e único por envio. O resultado é uma única campanha no dashboard com os destinatários acumulados.

## Batches Incrementais (Mesma Campanha)

Use esta abordagem quando quiser que todos os destinatários apareçam sob uma única campanha no dashboard.

**Regras:**

* `campaignId` e `name` devem ser idênticos em todas as chamadas
* `batch` é **obrigatório** a partir do segundo envio (recomendado desde o primeiro)
* O nome do `batch` deve ser único dentro da campanha
* O mesmo número de telefone não pode aparecer em dois batches da mesma campanha

```python theme={null}
import uuid
import requests

API_URL = "https://api-hub-campaign.convertt.ai/api/v1/"
TOKEN = "seu-access-token"
TEMPLATE_ID = "seu-template-id"
CAMPAIGN_ID = str(uuid.uuid4())  # ← mesmo em todas as chamadas
CAMPAIGN_NAME = "Black Friday 2025"  # ← mesmo em todas as chamadas
BATCH_SIZE = 2000

all_recipients = load_recipients()  # ex: 10.000 registros

for i in range(0, len(all_recipients), BATCH_SIZE):
    batch = all_recipients[i:i + BATCH_SIZE]
    batch_number = (i // BATCH_SIZE) + 1

    response = requests.post(
        f"{API_URL}/external/campaigns/dispatch",
        headers={
            "Authorization": f"Bearer {TOKEN}",
            "Content-Type": "application/json"
        },
        json={
            "campaignId": CAMPAIGN_ID,          # ← SEMPRE O MESMO
            "name": CAMPAIGN_NAME,              # ← SEMPRE O MESMO
            "templateId": TEMPLATE_ID,
            "batch": f"lote-{batch_number}",   # ← ÚNICO POR ENVIO
            "messages": [
                {"phone": r["phone"], "uid": r["id"], "vars": r.get("vars", {})}
                for r in batch
            ]
        }
    )

    result = response.json()
    print(f"Batch {batch_number}: {result['accepted']} aceitas, {result['rejected']} rejeitadas")
```

**Erros possíveis:**

| Status | Motivo                                                 |
| ------ | ------------------------------------------------------ |
| 400    | Campo `batch` ausente no segundo+ envio                |
| 409    | Nome de `batch` já utilizado nesta campanha            |
| 409    | Número de telefone já presente em batch anterior       |
| 409    | `campaignId` usado para uma campanha de nome diferente |

## Estratégia Multi-Batch

Cada chamada é processada **independentemente**. O campo `batch` é apenas metadado para sua referência.

```python theme={null}
import uuid
import requests

API_URL = "https://api-hub-campaign.convertt.ai/api/v1/"
TOKEN = "seu-access-token"
TEMPLATE_ID = "seu-template-id"
BATCH_SIZE = 2000

# Sua lista completa de destinatários
all_recipients = load_recipients()  # ex: 10.000 registros

# Dividir em batches
for i in range(0, len(all_recipients), BATCH_SIZE):
    batch = all_recipients[i:i + BATCH_SIZE]
    batch_number = (i // BATCH_SIZE) + 1

    campaign_id = str(uuid.uuid4())

    payload = {
        "campaignId": campaign_id,
        "name": f"Campanha Nov 2025 - Batch {batch_number}",
        "templateId": TEMPLATE_ID,
        "messages": [
            {
                "phone": r["phone"],
                "uid": r["id"],
                "vars": r.get("vars", {})
            }
            for r in batch
        ],
        "batch": f"batch-{batch_number}"
    }

    response = requests.post(
        f"{API_URL}/external/campaigns/dispatch",
        headers={
            "Authorization": f"Bearer {TOKEN}",
            "Content-Type": "application/json"
        },
        json=payload
    )

    result = response.json()
    print(f"Batch {batch_number}: {result['accepted']} aceitas, {result['rejected']} rejeitadas")
```

## Boas Práticas

<AccordionGroup>
  <Accordion title="Trate erros por batch">
    Se um batch falhar, reenvie apenas ele. Os outros batches não são afetados.
  </Accordion>

  <Accordion title="Monitore via webhook">
    Configure webhooks para acompanhar o status de entrega em tempo real, ao invés de consultar o dashboard manualmente.
  </Accordion>

  <Accordion title="Respeite os rate limits">
    Mantenha no máximo 60 chamadas por minuto. Adicione um intervalo entre os batches se necessário.
  </Accordion>
</AccordionGroup>

## Mapeamento de Resultados

Use o campo `uid` para correlacionar os webhooks de status com seus registros internos:

```
Disparo: uid="user-123" → Webhook: uid="user-123", status="delivered"
```
