> 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/ligacoes-audios.md).

# Ligações - Áudios

Os **Áudios** são as gravações que a plataforma toca quando disca para os seus contatos. Através destes endpoints você pode criar um áudio (enviando um arquivo ou gerando a locução a partir de um texto), listar, consultar, renomear, configurar as ações de teclado (DTMF) e remover.

É o mesmo recurso da tela **Áudios** do painel: o áudio criado pela API aparece lá, e vice-versa. O mesmo áudio serve tanto para um **Broadcast de Voz** quanto para uma **sequência de voz** dentro de uma campanha.

{% 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 %}

{% hint style="info" %}
Os endpoints ficam sob `/calls/`. O prefixo é do **canal**, não do fornecedor — os endpoints legados `/call4u/*` (ligação avulsa) continuam existindo e não mudaram.
{% endhint %}

**Fluxo de uso**

```
1. POST /calls/audios          → cria o áudio                (audio_id)
2. GET  /calls/audios/{id}     → repete até "ready": true
3. POST /calls/broadcasts      → dispara usando o audio_id
```

**Status possíveis**

**Status do áudio (`status`):** `processing` (medindo duração e transcodificando), `approved` (pronto para uso), `rejected` (recusado — veja `rejection_reason`) e `error` (falha no processamento).

{% hint style="warning" %}
Não interprete o `status` diretamente. Use o booleano **`ready`**: ele é `true` apenas quando o áudio já foi processado e pode ser usado em um disparo. Enquanto `ready` for `false`, os campos `duration_seconds` e `credits_per_call` ainda valem `0`.
{% endhint %}

**Créditos**

O custo é de **1 crédito de ligação a cada 30 segundos de áudio**, arredondado para cima, por ligação **atendida** — é o valor devolvido em `credits_per_call`. Multiplicado pelo tamanho da lista, ele dá o custo máximo de um disparo.

Criar um áudio por **upload não consome crédito**. Criar por **TTS consome**, porque a locução é gerada por um provedor pago — inclusive na pré-escuta (`preview-tts`).

***

#### Endpoints

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

**Função:** Lista os seus áudios, do mais recente para o mais antigo.

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

```json5
{
    "ready": true, // Quando true, devolve apenas os áudios já processados (prontos para uso)
    "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": "0192f100-7b31-7c4e-9a1d-2f3b4c5d6e7f", // ID do áudio (audio_id)
            "title": "Oferta de agosto", // Nome do áudio
            "type": "tts", // "tts" (locução gerada) ou "upload" (arquivo enviado)
            "status": "approved", // Status do processamento
            "ready": true, // true = pode ser usado em um disparo
            "duration_seconds": 42, // Duração medida. Vale 0 enquanto ready for false
            "credits_per_call": 2, // Créditos por ligação atendida. Vale 0 enquanto ready for false
            "file_name": "tts_66c1f0a9e21b4.mp3", // Nome do arquivo
            "tts_text": "Olá! Temos uma oferta especial...", // Texto da locução ou transcrição informada
            "tts_voice_id": "21m00Tcm4TlvDq8ikWAM", // Voz utilizada (apenas em type "tts")
            "created_at": "2026-08-18T12:00:00+00:00",
            "updated_at": "2026-08-18T12:00:41+00:00",
            "actions": [ // Ações de teclado (DTMF) configuradas
                {
                    "dtmf_key": "1", // Tecla digitada pelo contato
                    "action_type": "mark_interested", // Ação executada
                    "action_params": {} // Parâmetros da ação, quando houver
                }
            ]
        }
    ],
    "first_page_url": "https://web.smsfunnel.com.br/api/parceiros/v1/calls/audios?page=1",
    "from": 1,
    "next_page_url": null,
    "path": "https://web.smsfunnel.com.br/api/parceiros/v1/calls/audios",
    "per_page": 50,
    "prev_page_url": null,
    "to": 1
}
```

{% hint style="info" %}
O campo `rejection_reason` só aparece quando o `status` é `rejected` ou `error`, explicando o motivo da recusa.

O caminho do arquivo (`file_path`/`file_url`) **não** faz parte do contrato: o áudio é servido ao discador, não ao integrador.
{% endhint %}

***

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

**Função:** Cria um áudio. Há dois caminhos, escolhidos pelo campo `type`: enviar um arquivo (`upload`) ou deixar a plataforma gerar a locução a partir de um texto (`tts`).

**Corpo de envio — locução gerada (`type: "tts"`, `application/json`):**

```json5
{
    "title": "Oferta de agosto", // Obrigatório. Até 255 caracteres.
    "type": "tts", // Obrigatório. "upload" ou "tts".
    "tts_text": "Olá! Temos uma oferta. Digite 1 para falar com um consultor.", // Obrigatório quando type = "tts". Até 5000
caracteres.
    "tts_voice_id": "21m00Tcm4TlvDq8ikWAM", // Opcional. Ausente = voz padrão da plataforma.
    "actions": [ // Opcional. Até 12 ações de teclado (DTMF). Ver tabela abaixo.
        {
            "dtmf_key": "1", // Obrigatório. Uma tecla: 0-9, * ou #.
            "action_type": "mark_interested" // Obrigatório. Ver tabela de ações.
        }
    ]
}
```

**Corpo de envio — arquivo (`type: "upload"`, `multipart/form-data`):**

| Campo      | Valor                                                                                                     |
| ---------- | --------------------------------------------------------------------------------------------------------- |
| `title`    | Obrigatório. Até 255 caracteres.                                                                          |
| `type`     | Obrigatório. `upload`.                                                                                    |
| `file`     | Obrigatório. MP3, WAV, OGG ou M4A. Até **10 MB** e **30 segundos**.                                       |
| `tts_text` | Opcional. Transcrição do áudio, para você reconhecê-lo depois sem precisar ouvi-lo.                       |
| `actions`  | Opcional. Neste formato, envie como **string JSON**: `[{"dtmf_key":"1","action_type":"mark_interested"}]` |

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

```json5
{
    "id": "0192f100-7b31-7c4e-9a1d-2f3b4c5d6e7f",
    "title": "Oferta de agosto",
    "type": "tts",
    "status": "processing", // Nasce sempre em processing
    "ready": false, // Ainda não pode ser usado em um disparo
    "duration_seconds": 0, // Só é medida ao final do processamento
    "credits_per_call": 0, // Só é calculado ao final do processamento
    "file_name": "tts_66c1f0a9e21b4.mp3",
    "tts_text": "Olá! Temos uma oferta. Digite 1 para falar com um consultor.",
    "tts_voice_id": "21m00Tcm4TlvDq8ikWAM",
    "created_at": "2026-08-18T12:00:00+00:00",
    "updated_at": "2026-08-18T12:00:00+00:00",
    "actions": [
        { "dtmf_key": "1", "action_type": "mark_interested", "action_params": {} }
    ]
}
```

{% hint style="warning" %}
**A resposta é `202`, e não `201`.** O áudio já existe, mas **ainda não serve para disparar**: a plataforma precisa medir a duração e transcodificá-lo para o formato que o discador reproduz.

Consulte `GET /calls/audios/{id}` até que `ready` seja `true`. Só então `duration_seconds` e `credits_per_call` são válidos, e só então um disparo aceita este `audio_id` (antes disso, `422 AUDIO_NOT_READY`).
{% endhint %}

{% hint style="warning" %}
**Áudio acima de 30 segundos é recusado — inclusive no TTS.** No TTS a recusa acontece **depois** de gerar a locução: um texto longo custa a chamada ao provedor e ainda assim retorna `422`. Encurte o texto antes de enviar.
{% endhint %}

***

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

**Função:** Consulta um áudio específico. A resposta tem exatamente o mesmo formato dos itens de `data` na listagem.

É este o endpoint a ser consultado repetidamente após a criação, até que `ready` seja `true`.

Áudio inexistente ou de outra conta retorna `404 NOT_FOUND`.

***

<mark style="color:blue;">**PUT**</mark>**&#x20;/calls/audios/{id}** **Função:** Renomeia o áudio e reconfigura as suas ações de teclado (DTMF). Atualização parcial: envie apenas os campos que deseja alterar.

**Corpo de envio:**

```json5
{
    "title": "Oferta de agosto — v2", // Opcional. Até 255 caracteres.
    "tts_text": "Transcrição corrigida", // Opcional. Corrige apenas o texto gravado (ver aviso abaixo).
    "actions": [ // Opcional. Presente, SUBSTITUI o conjunto inteiro de ações.
        { "dtmf_key": "1", "action_type": "mark_interested" }
    ]
}
```

**Corpo de resposta — `200 OK`:** o áudio atualizado, no mesmo formato do `GET /calls/audios/{id}`.

{% hint style="warning" %}
**O campo `actions`, quando presente, substitui todas as ações existentes.** Envie `[]` para remover todas, ou **omita o campo** para preservar as atuais.
{% endhint %}

{% hint style="warning" %}
**Este endpoint não troca o áudio.** Os campos `type`, `file` e `tts_voice_id` são recusados com `422`, e `tts_text` aqui **apenas corrige a transcrição gravada — não regera a locução**. O que o contato escuta continua sendo o mesmo arquivo.

Para mudar o áudio, crie outro e aponte o disparo para o novo `audio_id`. O motivo: a duração já entrou no cálculo de créditos dos disparos que usam este áudio, e trocar o arquivo mudaria o custo de um disparo em andamento.
{% endhint %}

***

<mark style="color:red;">**DELETE**</mark>**&#x20;/calls/audios/{id}**

**Função:** Remove o áudio. A remoção apaga **o registro e o arquivo**.

**Corpo de resposta:** `204 No Content`.

{% hint style="warning" %}
Como o arquivo é apagado, um áudio em uso não pode ser removido — as próximas ligações tocariam um arquivo inexistente. Retorna `409 AUDIO_IN_USE` quando:

* o áudio é usado por um **broadcast de voz** que ainda não encerrou (qualquer status que não seja `completed` ou `cancelled`) — os IDs vêm em `details.broadcast_ids`;
* o áudio é usado por uma **sequência de voz** de uma campanha, **ativa ou não** — os IDs vêm em `details.sequence_ids`. Uma automação não "termina" sozinha: troque o áudio da sequência (`PUT /sms/sequences/{id}`) ou remova a sequência antes.

Broadcast já `completed` ou `cancelled` **não** impede a remoção — o histórico e os relatórios dele seguem intactos.
{% endhint %}

***

<mark style="color:green;">**POST**</mark>**&#x20;/calls/audios/preview-tts**

**Função:** Gera a locução e devolve o **binário MP3** (`Content-Type: audio/mpeg`), **sem gravar nada**. Existe para quem monta a própria tela de criação de áudio e precisa deixar o usuário ouvir antes de confirmar.

**Corpo de envio:**

```json5
{
    "tts_text": "Olá! Temos uma oferta especial para você.", // Obrigatório. Até 5000 caracteres.
    "tts_voice_id": "21m00Tcm4TlvDq8ikWAM" // Opcional. Ausente = voz padrão da plataforma.
}
```

**Corpo de resposta — `200 OK`:** o arquivo MP3 em binário. É o **único** endpoint da API de Parceiros que não responde JSON.

{% hint style="danger" %}
**Cada chamada é paga.** Mesmo sem criar nenhum áudio, cada pré-escuta é uma chamada ao provedor de locução e exige saldo de créditos de ligação. Não utilize em laço de teste.
{% endhint %}

***

#### Ações de teclado (DTMF)

Uma ação define o que acontece quando o contato digita uma tecla durante a ligação. Elas são configuradas no áudio, em `actions`, e valem para todos os disparos que o utilizam.

\| `action_type` | `action_params` | O que faz\
\| | ----------------------- | --------------- | -------------------------------------------------------------------------------------------------------------------- | | `mark_interested` | — | Marca o contato como interessado\
\| | `mark_not_interested` | — | Marca o contato como não interessado\
\| | `add_tag` | `tag_id` | Adiciona a tag ao contato\
\| | `remove_tag` | `tag_id` | Remove a tag do contato\
\| | `move_to_list` | `list_id` | **Move** o lead para outra lista sua | | `add_to_list` | `list_id` | **Copia** o lead para outra lista sua (mantém na atual) | | `trigger_sequence` | `sequence_id` | Inscreve o lead em uma sequência sua | | `webhook` | `url` | Envia um `POST` ao seu endereço com `{lead_id, name, phone, dtmf_key, sequence_id, broadcast_call_id, action_type}` |

**Exemplo com parâmetros:**

```json5
{
    "actions": [
        { "dtmf_key": "1", "action_type": "mark_interested" },
        { "dtmf_key": "2", "action_type": "move_to_list", "action_params": { "list_id": "0192e789-..." } },
        { "dtmf_key": "9", "action_type": "webhook", "action_params": { "url": "https://seu-dominio.com/dtmf" } }
    ]
}
```

* `dtmf_key` é **uma** tecla do teclado telefônico: `0` a `9`, `*` ou `#`.
* **Uma ação por tecla.** Repetir a mesma tecla no array retorna `422`: a plataforma executaria apenas uma delas, e não haveria como dizer qual.
* São aceitas no máximo **12 ações** por áudio.
* `list_id` e `sequence_id` precisam pertencer **à sua conta**. Um ID desconhecido e um ID de outro parceiro retornam o mesmo `422`, com a mesma mensagem — de propósito, para não revelar o que existe na conta alheia.
* A `url` de `webhook` não pode apontar para endereços privados ou internos (`422`).

***

#### 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 ligação insuficientes. Ocorre apenas em `type: "tts"` e em `preview-tts` — o upload de arquivo não consome crédito. O saldo atual vem em `details.available_credits`.
* `404 Not Found` (`NOT_FOUND`): O áudio não foi encontrado ou não pertence à sua conta.
* `409 Conflict` (`AUDIO_IN_USE`): O áudio está em uso e não pode ser removido. Os IDs vêm em `details.broadcast_ids` e `details.sequence_ids`.
* `422 Unprocessable Entity` (`VALIDATION_ERROR`): Algum campo do corpo da requisição é inválido — inclui arquivo que não é um áudio válido, áudio acima de 30 segundos, tecla DTMF repetida, ação sem o parâmetro obrigatório e `list_id`/`sequence_id` que não pertence à sua conta. à sua conta.
* `429 Too Many Requests` (`RATE_LIMIT_EXCEEDED`): Limite de **60 requisições por minuto** excedido. Consulte o header `Retry-After`.
* `502 Bad Gateway` (`AUDIO_PROVIDER_ERROR`): O provedor de locução falhou. Nada foi gravado; repetir a chamada mais tarde costuma resolver.
* `502 Bad Gateway` (`AUDIO_UPLOAD_FAILED`): Falha ao armazenar o arquivo enviado. Nada foi gravado.

**Corpo de resposta de erro:**

```json5
{   
    "error": {
        "code": "AUDIO_IN_USE", // Código do erro
        "message": "O áudio está em uso por broadcast de voz que ainda não encerrou. Cancele ou aguarde o broadcast antes de
remover.", // Descrição
        "details": { // Opcional: detalhes adicionais
            "broadcast_ids": ["9b1f8e2a-7b31-7c4e-9a1d-2f3b4c5d6e7f"],
            "sequence_ids": []
        }
    }
}
```

**Dúvidas?**

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