> For the complete documentation index, see [llms.txt](https://docs.smsfunnel.com.br/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.smsfunnel.com.br/api/parceiros/broadcasts.md).

# Broadcasts

Os **Broadcasts** representam o envio de SMS em massa. Através destes endpoints você pode disparar mensagens, listar e consultar seus envios, acompanhar o status individual de cada mensagem e cancelar um envio em andamento.

{% hint style="success" %}
**A URL de base de todos os endpoints é**: <https://web.smsfunnel.com.br/api/parceiros/v1>
{% endhint %}

{% hint style="info" %}
Os endpoints de listagem utilizam **paginação simples**. A resposta traz `current_page`, `data`, `per_page`, `next_page_url` e `prev_page_url` — não há campos `total` ou `last_page`. Para navegar, utilize o parâmetro de query `page`.
{% endhint %}

#### Status possíveis

**Status do broadcast:** `pending`, `scheduled`, `sending`, `sent`, `sent_with_errors`, `cancelled`, `sanitizing`, `importing`.

**Status da mensagem:** `queued` (aceita, aguardando disparo), `sent` (enviada), `delivered` (entrega confirmada), `failed` (falha) e `undelivered` (não entregue).

***

### Endpoints

<mark style="color:green;">**POST**</mark>**&#x20;/sms/messages**

**Função:** Enfileira o disparo de uma ou mais mensagens SMS. Cada chamada gera um ou mais broadcasts (um por grupo de agendamento) que agrupam as mensagens enviadas.

**Corpo de envio:**

```json5
{
    // Campos globais (opcionais) - aplicados a todas as mensagens, salvo quando sobrescritos por mensagem.
    "from": "SMSFunnel", // Remetente personalizado (até 20 caracteres)
    "flashSms": false, // Envio como flash SMS
    "concat": true, // Concatenação de mensagens longas
    "schedule": "2026-07-01T10:00:00Z", // Agendamento global
    "url": "https://example.com/promo", // "Meu Link". Obrigatório quando alguma mensagem contém {meu_link}.
    "messages": [ // Obrigatório. De 1 a 5000 mensagens.
        {
            "to": "+5511999999999", // Obrigatório. 10 a 15 dígitos, com DDI/DDD (aceita "+").
            "message": "Oferta: {meu_link}", // Obrigatório. 1 a 1530 caracteres.
            "reference": "order-123" // Opcional. Seu identificador (até 100 caracteres). Se omitido, geramos um.
        },
        {
            "to": "5511888888888",
            "message": "Ola!",
            "schedule": "2026-07-01T11:00:00", // Sobrescreve o agendamento global desta mensagem
            "from": "LOJA" // Sobrescreve o remetente global desta mensagem
        }
    ]
}
```

{% hint style="info" %}
**Agendamento (`schedule`):** aceita os formatos `2026-07-01T10:00:00Z` (ISO 8601 com offset), `2026-07-01T10:00:00` (ISO 8601 sem offset) ou `2026-07-01 10:00:00`. A data deve ser futura. Os campos por mensagem têm prioridade sobre os globais.
{% endhint %}

{% hint style="warning" %}
Quando alguma mensagem contém a variável `{meu_link}`, o campo `url` é **obrigatório** (e vice-versa). Nós encurtamos o link automaticamente e substituímos `{meu_link}` pelo link curto em cada mensagem.
{% endhint %}

{% hint style="info" %}
**Idempotência (opcional):** envie o header `Idempotency-Key` (máx. 80 caracteres) para evitar envios duplicados. Se recebermos a mesma chave em até **24 horas**, retornamos a resposta original sem reprocessar, incluindo o header `Idempotency-Replayed: true`.
{% endhint %}

**Corpo de resposta — `202 Accepted`:**

```json5
{
    "broadcast_id": "9b1f8e2a-7b31-7c4e-9a1d-2f3b4c5d6e7f", // ID do broadcast gerado
    "messages": [
        {
            "id": "0190c8e2-abab-7da9-9a46-4da50bd49147", // ID da mensagem (external_message_id)
            "reference": "order-123", // Sua referência (ou a gerada por nós)
            "phone": "5511999999999", // Telefone normalizado
            "status": "queued", // Status inicial
            "bill_factor": 1 // Créditos consumidos por esta mensagem (sempre 1)
        }
    ],
    "unsupported_features": ["flashSms", "concat", "from"] // Recursos solicitados que não foram aplicados, se houver
}
```

***

<mark style="color:green;">**GET**</mark>**&#x20;/sms/broadcasts**

**Função:** Lista seus broadcasts, do mais recente para o mais antigo.

**Parâmetros de query (opcionais):**

```json5
{
    "status": "sending", // Filtra por status (ver lista de status do broadcast)
    "start_date": "2026-06-01", // Filtra por created_at >= data (YYYY-MM-DD)
    "end_date": "2026-06-30", // Filtra por created_at <= data (YYYY-MM-DD)
    "text": "Carnaval", // Busca pelo nome do broadcast
    "per_page": 50, // Itens por página. Padrão: 50. Mínimo: 1, Máximo: 200.
    "page": 1 // Página desejada
}
```

**Corpo de resposta — `200 OK`:**

```json5
{
    "current_page": 1,
    "data": [
        {
            "id": "9b1f8e2a-7b31-7c4e-9a1d-2f3b4c5d6e7f", // ID do broadcast
            "name": "Campanha X", // Nome do broadcast
            "message": "Oferta: {meu_link}", // Mensagem enviada
            "status": "sending", // Status atual
            "scheduled_date": "2026-07-01T10:00:00-03:00", // Data de agendamento (ou nulo)
            "leads_count": 1500, // Quantidade de destinatários
            "partner_reference": "ref-abc", // Sua referência
            "flash_sms": false, // Enviado como flash SMS
            "concat": true, // Concatenação ativa
            "from": "LOJA", // Remetente personalizado (ou nulo)
            "idempotency_key": "key-123", // Chave de idempotência
            "created_at": "2026-06-30T14:00:00-03:00" // Data de criação
        }
    ],
    "first_page_url": "https://web.smsfunnel.com.br/api/parceiros/v1/sms/broadcasts?page=1",
    "from": 1,
    "next_page_url": "https://web.smsfunnel.com.br/api/parceiros/v1/sms/broadcasts?page=2",
    "path": "https://web.smsfunnel.com.br/api/parceiros/v1/sms/broadcasts",
    "per_page": 50,
    "prev_page_url": null,
    "to": 50
}
```

***

<mark style="color:green;">**GET**</mark>**&#x20;/sms/broadcasts/{id}**

**Função:** Obtém os detalhes de um broadcast específico, incluindo suas métricas.

**Corpo de resposta — `200 OK`:**

```json5
{
    "id": "9b1f8e2a-7b31-7c4e-9a1d-2f3b4c5d6e7f",
    "name": "Campanha X",
    "message": "Oferta: {meu_link}",
    "status": "sent_with_errors",
    "scheduled_date": null,
    "leads_count": 1500,
    "partner_reference": "ref-abc",
    "flash_sms": false,
    "concat": true,
    "from": "LOJA",
    "idempotency_key": "key-123",
    "created_at": "2026-06-30T14:00:00-03:00",
    "metrics": {
        "sent": 1450, // Mensagens enviadas/entregues
        "failed": 50, // Mensagens com falha/não entregues
        "total": 1500 // Total de mensagens
    }
}
```

***

<mark style="color:green;">**GET**</mark>**&#x20;/sms/broadcasts/{id}/contacts**

**Função:** Lista os contatos (mensagens individuais) de um broadcast.

**Parâmetros de query (opcionais):**

```json5
{
    "phone": "5511", // Busca por trecho do telefone
    "per_page": 50, // Itens por página. Padrão: 50. Mínimo: 1, Máximo: 200.
    "page": 1 // Página desejada
}
```

**Corpo de resposta — `200 OK`:**

```json5
{
    "current_page": 1,
    "data": [
        {
            "id": "0190c8e2-abab-7da9-9a46-4da50bd49147", // ID da mensagem (external_message_id)
            "reference": "order-123", // Sua referência
            "phone": "5511999999999", // Telefone
            "message": "Ola!", // Mensagem enviada ao contato
            "status": "delivered", // Status da mensagem
            "cancelled": false, // Indica se o envio foi cancelado
            "created_at": "2026-06-30T14:00:01-03:00"
        }
    ],
    "first_page_url": "https://web.smsfunnel.com.br/api/parceiros/v1/sms/broadcasts/9b1f8e2a-.../contacts?page=1",
    "from": 1,
    "next_page_url": null,
    "path": "https://web.smsfunnel.com.br/api/parceiros/v1/sms/broadcasts/9b1f8e2a-.../contacts",
    "per_page": 50,
    "prev_page_url": null,
    "to": 1
}
```

***

<mark style="color:green;">**GET**</mark>**&#x20;/sms/messages/{external\_message\_id}**

**Função:** Consulta o status de uma mensagem específica, pelo `id` retornado no envio.

**Corpo de resposta — `200 OK`:**

```json5
{
    "id": "0190c8e2-abab-7da9-9a46-4da50bd49147", // ID da mensagem (external_message_id)
    "reference": "order-123", // Sua referência
    "phone": "5511999999999", // Telefone
    "status": "delivered", // Status da mensagem
    "sent_at": "2026-06-30T14:00:05-03:00", // Data de envio (ou nulo)
    "delivered_at": "2026-06-30T14:00:12-03:00" // Data de entrega (ou nulo)
}
```

***

<mark style="color:blue;">**PUT**</mark>**&#x20;/sms/broadcasts/{id}/cancel**

**Função:** Cancela um broadcast. Apenas broadcasts nos status `pending`, `scheduled` ou `sending` podem ser cancelados.

**Corpo de resposta:**

* `200 OK` — broadcast `pending` ou `scheduled`: cancelamento completo (`cancellation: "complete"`).
* `202 Accepted` — broadcast `sending`: cancelamento parcial; mensagens já enfileiradas ainda podem ser disparadas (`cancellation: "partial"`).

```json5
{
    "id": "9b1f8e2a-7b31-7c4e-9a1d-2f3b4c5d6e7f",
    "name": "Campanha X",
    "message": "...",
    "status": "cancelled",
    "scheduled_date": "2026-07-01T10:00:00-03:00",
    "leads_count": 1500,
    "partner_reference": "ref-abc",
    "flash_sms": false,
    "concat": true,
    "from": "LOJA",
    "idempotency_key": "key-123",
    "created_at": "2026-06-30T14:00:00-03:00",
    "cancellation": "complete" // "complete" (200) ou "partial" (202)
}
```

{% hint style="warning" %}
Broadcasts já finalizados (`sent`, `sent_with_errors`) ou já cancelados (`cancelled`) retornam `409 INVALID_STATUS_TRANSITION`, com o status atual em `details.current_status`.
{% endhint %}

***

### Código de Erros Comuns

* `401 Unauthorized` (`UNAUTHORIZED`): Não foi possível identificar o parceiro a partir da Chave de API.
* `402 Payment Required` (`INSUFFICIENT_CREDITS`): Créditos de SMS insuficientes para o envio.
* `404 Not Found` (`NOT_FOUND`): O broadcast ou a mensagem não foi encontrada ou não pertence à sua conta.
* `409 Conflict` (`INVALID_STATUS_TRANSITION`): O broadcast não pode ser cancelado no status atual.
* `422 Unprocessable Entity` (`VALIDATION_ERROR`): Algum campo do corpo da requisição é inválido (inclui `{meu_link}` sem `url` e `Idempotency-Key` acima de 80 caracteres).
* `429 Too Many Requests` (`RATE_LIMIT_EXCEEDED`): Limite de **60 requisições por minuto** excedido. Consulte o header `Retry-After`.
* `502 Bad Gateway` (`SHORTENER_UNAVAILABLE`): Falha temporária ao encurtar o link de "Meu Link". Tente novamente.

**Corpo de resposta de erro:**

```json5
{
    "error": {
        "code": "INVALID_STATUS_TRANSITION", // Código do erro
        "message": "Broadcast cannot be cancelled in its current status.", // Descrição
        "details": { // Opcional: detalhes adicionais
            "current_status": "sent"
        }
    }
}
```

#### Dúvidas?

Em caso de dúvidas, entre em contato com nosso suporte.
