> 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/guia-de-migracao-call4u-sms-funnel.md).

# Guia de Migração: Call4U → SMS Funnel

Este guia é para quem integrava com a **API de parceiros do Call4U** (`https://api.call4u.com.br/parceiros/v1`) e passou a operar no **SMS Funnel**. Para cada endpoint antigo, mostramos o equivalente de hoje, o que muda na requisição e como fica a resposta.

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

{% hint style="warning" %}
**Autenticação:** continua sendo `Authorization: Bearer <token>`, mas o token é o da sua conta **SMS Funnel**. O token do Call4U não funciona aqui. Os IDs também mudaram: contas, campanhas e sequências agora são **UUID** (ex.: `018f9c2a-7b31-7c4e-9a1d-2f3b4c5d6e7f`), e não mais números inteiros.
{% endhint %}

{% hint style="info" %}
**Limite de requisições:** 60 por minuto, por conta.
{% endhint %}

***

#### Resumo da troca

| Call4U (antigo)                                                          | SMS Funnel (novo)                                          |
| ------------------------------------------------------------------------ | ---------------------------------------------------------- |
| `GET /credits`                                                           | `GET /credits`                                             |
| `GET /sent-calls?from_date=&to_date=`                                    | `GET /call4u/sent-calls?start_date=&end_date=`             |
| `GET /recharges?from_date=&to_date=`                                     | `GET /recharges?from_date=&to_date=`                       |
| `GET /campaigns?from_date=&to_date=&page=&per_page=`                     | `GET /sms/campaigns` + `GET /sms/campaigns/{id}/sequences` |
| `GET /campaigns/{campaignRef}/calls?from_date=&to_date=&page=&per_page=` | `GET /sms/sequences/{sequence_id}/calls?page=&per_page=`   |

{% hint style="info" %}
**Por que as ligações saem de "sequências"?** No SMS Funnel, a ligação disparada quando um lead entra numa lista é uma **sequência de voz** dentro de uma **campanha**. A campanha é ligada a uma lista, e cada sequência dela é um passo do fluxo (SMS ou ligação). Por isso a consulta das ligações é feita **por sequência**, e não mais por "campanha do Call4U".
{% endhint %}

**Fluxo para consultar as ligações**

```
1. GET /sms/campaigns                         → encontra a campanha ligada à sua lista   (campaign_id)
2. GET /sms/campaigns/{campaign_id}/sequences → encontra a sequência com "type": "call"  (sequence_id)
3. GET /sms/sequences/{sequence_id}/calls     → desfecho de cada ligação (paginado)
```

Os IDs dos passos 1 e 2 não mudam com o tempo: basta buscá-los uma vez e guardar.

***

#### Endpoints

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

**Função:** Consulta o saldo da conta. Substitui o `GET /credits` do Call4U. O saldo de ligação fica no bloco `call`.

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

```json5
{
    "sms": {
        "contracted": 50000,
        "sent": 12000,
        "available": 38000
    },
    "whatsapp": {
        "contracted": 0,
        "sent": 0,
        "available": 0
    },
    "call": {
        "contracted": 200000, // Total de créditos de ligação já contratados
        "sent": 150000,       // Créditos de ligação já consumidos
        "available": 50000    // Saldo disponível para novas ligações
    }
}
```

{% hint style="info" %}
**O que mudou:** no Call4U a resposta era `{"calls": {...}}`. Agora vem um bloco por canal, e o de ligação se chama **`call`**. Os campos `contracted`, `sent` e `available` têm o mesmo significado.
{% endhint %}

***

<mark style="color:green;">**GET**</mark>**&#x20;/call4u/sent-calls**

**Função:** Retorna a **quantidade** de ligações da conta no período. Substitui o `GET /sent-calls` do Call4U.

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

```json5
{
    "start_date": "2026-09-01", // Data inicial (YYYY-MM-DD)
    "end_date": "2026-09-24"    // Data final (YYYY-MM-DD)
}
```

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

```json5
{
    "calls": 88934 // Quantidade de ligações no período
}
```

{% hint style="warning" %}
**Os parâmetros mudaram de nome:** use `start_date` e `end_date`, e não mais `from_date` e `to_date`. Se enviar os nomes antigos, eles são ignorados e a resposta traz o total **sem filtro de data**.
{% endhint %}

{% hint style="info" %}
O número considera todas as ligações registradas no período, inclusive as que ainda aguardam discagem. Para saber o desfecho de cada uma, use `GET /sms/sequences/{sequence_id}/calls`.
{% endhint %}

***

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

**Função:** Lista as recargas aprovadas da conta no período. Substitui o `GET /recharges` do Call4U.

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

```json5
{
    "from_date": "2026-07-01", // Data inicial (YYYY-MM-DD). Se enviar, to_date é obrigatório.
    "to_date": "2026-09-24"    // Data final (YYYY-MM-DD). Se enviar, from_date é obrigatório.
}
```

Sem datas, a consulta retorna os **últimos 90 dias**. O intervalo máximo entre as datas é de **90 dias**.

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

```json5
{
    "recharges": [
        {
            "created_at": "2026-09-10 14:32:05",               // Data de aprovação da recarga
            "description": "Recarga de créditos de ligação",   // Descrição
            "service": "Ligação",                              // "SMS", "WhatsApp" ou "Ligação"
            "credits": 100000,                                 // Créditos adicionados
            "price": "0.0900",                                 // Preço unitário (string, preserva as casas decimais)
            "total": "9000.00",                                // Valor total (string)
            "situation": "APPROVED",                           // Sempre APPROVED
            "invoice_url": "https://..."                       // Nota fiscal, ou null
        }
    ]
}
```

{% hint style="warning" %}
**O que mudou em relação ao Call4U:**

* **Não há paginação.** A lista do período vem inteira. Não envie `page` nem `per_page`: **qualquer parâmetro além de `from_date`, `to_date`, `email` e `user_id` retorna `422`**.
* A resposta não tem mais `total`, `page`, `per_page` e `total_pages`.
* `service` passa de `"CALL"`/`"SMS"` para **`"Ligação"`**, `"SMS"` ou `"WhatsApp"`. Para ver só as recargas de ligação, filtre por `"Ligação"`.
* Só aparecem recargas **aprovadas**. Recargas pendentes ou canceladas não são listadas.
  {% endhint %}

***

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

**Função:** Lista as suas campanhas. É o primeiro passo para encontrar a sequência de voz. Substitui a parte de "listar campanhas" do `GET /campaigns` do Call4U.

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

```json5
{
    "per_page": 20, // Itens por página. Padrão: 20. Mínimo: 1, Máximo: 100.
    "page": 1       // Página desejada
}
```

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

```json5
{
    "current_page": 1,
    "data": [
        {
            "id": "018f9c2a-7b31-7c4e-9a1d-2f3b4c5d6e7f",           // ID da campanha
            "name": "Captação Goldebet",                           // Nome da campanha
            "active": true,                                        // Campanha ativa
            "lead_list_id": "018f9c2a-1111-7c4e-9a1d-aaaabbbbcccc", // ID da lista vinculada
            "created_at": "2026-06-30T14:05:00+00:00",
            "updated_at": "2026-06-30T14:05:00+00:00"
        }
    ],
    "first_page_url": "https://web.smsfunnel.com.br/api/parceiros/v1/sms/campaigns?page=1",
    "from": 1,
    "next_page_url": null,
    "path": "https://web.smsfunnel.com.br/api/parceiros/v1/sms/campaigns",
    "per_page": 20,
    "prev_page_url": null,
    "to": 1
}
```

{% hint style="info" %}
Use o `lead_list_id` para identificar qual campanha é a da lista que você alimenta.
{% endhint %}

***

<mark style="color:green;">**GET**</mark>**&#x20;/sms/campaigns/{campaign\_id}/sequences**

**Função:** Lista as sequências (passos) de uma campanha. A sequência de ligação é a que tem **`"type": "call"`**. Guarde o `id` dela: é o `sequence_id` usado na consulta das ligações.

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

```json5
[
    {
        "id": "018f9c2a-9999-7c4e-9a1d-1234567890ab",          // ID da sequência (sequence_id)
        "campaign_id": "018f9c2a-7b31-7c4e-9a1d-2f3b4c5d6e7f", // ID da campanha
        "type": "call",                                        // "call" = ligação | "sms" = SMS
        "interval": 1,
        "interval_type_id": 1,                                 // 1=Minuto, 2=Hora, 3=Dia, 4=Semana, 5=Mês
        "position": 1,                                         // Ordem do passo na campanha
        "text": null,
        "active": true,
        "url": null,
        "short_url": null,
        "created_at": "2026-06-30T14:05:00+00:00",
        "updated_at": "2026-06-30T14:05:00+00:00"
    }
]
```

{% hint style="info" %}
A resposta é uma lista simples, sem paginação. Uma campanha pode ter mais de uma sequência de voz. Nesse caso, consulte as ligações de cada uma.
{% endhint %}

***

<mark style="color:green;">**GET**</mark>**&#x20;/sms/sequences/{sequence\_id}/calls**

**Função:** Lista as ligações de uma sequência de voz, com o desfecho de cada uma. **Substitui o `GET /campaigns/{campaignRef}/calls` do Call4U.**

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

```json5
{
    "page": 1,                  // Página desejada
    "per_page": 200,            // Itens por página. Padrão: 50. Mínimo: 1, Máximo: 200.
    "status": "answered_dtmf",  // Filtra por desfecho (veja a tabela abaixo)
    "phone": "11987654321"      // Filtra por telefone (busca parcial)
}
```

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

```json5
{
    "current_page": 1,
    "data": [
        {
            "id": "01a0d1f2-9c3e-7a41-8b2d-5e6f7a8b9c0d", // ID da ligação
            "phone": "11987654321",                      // Telefone
            "name": "Maria Souza",                       // Nome do lead (ou null)
            "status": "answered_dtmf",                   // Desfecho (slug estável, use este para programar)
            "status_label": "Atendida com Digitação",    // Desfecho em texto, igual ao painel
            "pabx_status": "ANSWER",                     // Status bruto da central telefônica
            "call_duration_seconds": 18,                 // Duração em segundos (ou null)
            "listened_percentage": 72.5,                 // Percentual do áudio ouvido (ou null)
            "dtmf_response": "1",                        // Tecla digitada (ou null)
            "tries": 1,                                  // Tentativa atual
            "max_attempts": 3,                           // Tentativas configuradas
            "sent_at": "2026-09-24T10:15:02-03:00",      // Quando a ligação foi disparada
            "answered_at": "2026-09-24T10:15:31-03:00"   // Quando recebemos o resultado da ligação
        },
        {
            "id": "01a0d1f2-9c3e-7a41-8b2d-5e6f7a8b9c0e",
            "phone": "21976543210",
            "name": "João Lima",
            "status": "no_answer",
            "status_label": "Recusada / Não Atendida",
            "pabx_status": "NOANSWER",
            "call_duration_seconds": 0,
            "listened_percentage": null,
            "dtmf_response": null,
            "tries": 3,
            "max_attempts": 3,
            "sent_at": "2026-09-24T10:17:40-03:00",
            "answered_at": "2026-09-24T10:17:52-03:00"
        }
    ],
    "first_page_url": "https://web.smsfunnel.com.br/api/parceiros/v1/sms/sequences/{sequence_id}/calls?page=1",
    "from": 1,
    "next_page_url": "https://web.smsfunnel.com.br/api/parceiros/v1/sms/sequences/{sequence_id}/calls?page=2",
    "path": "https://web.smsfunnel.com.br/api/parceiros/v1/sms/sequences/{sequence_id}/calls",
    "per_page": 200,
    "prev_page_url": null,
    "to": 200
}
```

{% hint style="warning" %}
**Paginação diferente do Call4U:**

* Não há `total`, `total_pages` nem `last_page`. Avance incrementando `page` até `next_page_url` vir `null`.
* **Sempre envie `per_page` (e `status`, se estiver filtrando) em todas as páginas.** O `next_page_url` devolvido leva apenas o `page`. Se você seguir o link como está, a próxima página volta com o padrão de 50 itens.
  {% endhint %}

{% hint style="warning" %}
**Não há filtro por data** (`from_date`/`to_date`). A consulta traz todas as ligações da sequência. Para recortar um período, filtre pelo `sent_at` do seu lado.
{% endhint %}

{% hint style="info" %}
Se o `sequence_id` for de uma sequência de SMS, a resposta é `409` com o código `INVALID_SEQUENCE_TYPE`.
{% endhint %}

***

#### De → para dos campos da ligação

| Call4U (`/campaigns/{ref}/calls`) | SMS Funnel (`/sms/sequences/{id}/calls`) | Observação                                                  |
| --------------------------------- | ---------------------------------------- | ----------------------------------------------------------- |
| `id`                              | `id`                                     | Agora é UUID                                                |
| `cliente_nome`                    | `name`                                   |                                                             |
| `numero`                          | `phone`                                  |                                                             |
| `status`                          | `status` / `status_label`                | `status` é um slug fixo. Veja a tabela de desfechos abaixo. |
| `percentual_ouvido` (`"72.50%"`)  | `listened_percentage` (`72.5`)           | Agora é número, sem o `%`                                   |
| `duracao_segundos`                | `call_duration_seconds`                  |                                                             |
| `tentativa_atual`                 | `tries`                                  |                                                             |
| `tentativas_configuradas`         | `max_attempts`                           |                                                             |
| `data_ligacao`                    | `sent_at`                                |                                                             |
| `data_hora`                       | `sent_at`                                | Não há campo separado de data de criação                    |
| —                                 | `dtmf_response`                          | Novo: tecla digitada                                        |
| —                                 | `pabx_status`                            | Novo: status bruto da central                               |
| —                                 | `answered_at`                            | Novo: quando o resultado da ligação chegou                  |
| `campaign_id`, `campaign_name`    | —                                        | Use o `sequence_id` da consulta                             |

#### Desfechos da ligação

| `status`            | `status_label`           | Equivalente no Call4U                                 |
| ------------------- | ------------------------ | ----------------------------------------------------- |
| `waiting`           | Aguardando               | Pendente / Em andamento                               |
| `no_answer`         | Recusada / Não Atendida  | Não atendida / Recusada                               |
| `answered_hangup`   | Atendida e Desligada     | Atendida e desconectada (ouviu menos de 95% do áudio) |
| `answered_listened` | Escutou até o Fim        | Atendida e ouviu até o final (95% ou mais do áudio)   |
| `answered_dtmf`     | Atendida com Digitação   | Atendida com digitação                                |
| `cancelled`         | Cancelado                | Cancelada pelo usuário                                |
| `error`             | Erro / Telefone inválido | Número inválido                                       |

{% hint style="info" %}
**Estatísticas por campanha:** o `GET /campaigns` do Call4U trazia um bloco `statistics` (total enviado, atendidas, digitação etc.). No SMS Funnel não há hoje um endpoint com esses totais para ligações de sequência. Para calculá-los, some os `status` retornados por `GET /sms/sequences/{sequence_id}/calls`, ou consulte só um desfecho com o filtro `?status=`.
{% endhint %}

***

#### Erros

| Código HTTP | Quando acontece                                                                         |
| ----------- | --------------------------------------------------------------------------------------- |
| `401`       | Token ausente ou inválido                                                               |
| `404`       | Campanha ou sequência não encontrada, ou não pertence à sua conta                       |
| `409`       | `INVALID_SEQUENCE_TYPE`: a sequência consultada não é de ligação                        |
| `422`       | Parâmetro inválido (data fora do formato, intervalo acima de 90 dias, campo não aceito) |
| `429`       | Limite de requisições excedido                                                          |

**Formato do erro nos endpoints `/sms/*`:**

```json5
{
    "error": {
        "code": "NOT_FOUND",            // Código do erro
        "message": "Sequence not found." // Descrição
    }
}
```

**Formato do erro em `/recharges`:**

```json5
{
    "error": "The difference between from_date and to_date cannot be greater than 90 days."
}
```
