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

# Enviar mensagem

> Envio de mensagem de texto para um contato

```http theme={null}
POST https://api.hustapp.com/message/send
```

Envia uma mensagem para um contato através de uma conexão ativa. Esta página cobre o envio de **texto**; mídia usa a mesma rota e está em [Enviar mídia](/chat/enviar-midia).

## Modos de envio

O campo `called` determina se a mensagem abre um atendimento e quais campos são obrigatórios.

<Tabs>
  <Tab title="Abrindo atendimento">
    Comportamento padrão, quando você omite `called`. A rota procura um chamado em aberto para o contato e o reaproveita, ou cria um novo.

    Neste modo **`department` é obrigatório**.
  </Tab>

  <Tab title="Sem atendimento">
    Envie `"called": "without"` para disparar a mensagem sem abrir chamado. Útil para notificações automáticas.

    Neste modo `department` não é necessário.
  </Tab>

  <Tab title="Chamado existente">
    Envie `"called": { "id": 123 }` para usar um chamado específico. Ele passa para o status de atendimento e é atribuído ao usuário do token.

    Neste modo `department`, `contact` e `connection` são ignorados: os dados vêm do próprio chamado.
  </Tab>
</Tabs>

## Cabeçalhos

| Cabeçalho       | Valor                                                   |
| --------------- | ------------------------------------------------------- |
| `Authorization` | `Bearer SEU_TOKEN`. Veja [Autenticação](/autenticacao). |
| `Content-Type`  | `application/json`                                      |

## Corpo da requisição

| Campo         | Tipo               | Obrigatório                           | Descrição                                                                                                                                                         |
| ------------- | ------------------ | ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `type`        | `string`           | Sim                                   | `text`, `image`, `audio`, `video` ou `document`.                                                                                                                  |
| `text`        | `string`           | Se `type` for `text`                  | Conteúdo da mensagem. Dispensável se você enviar `predefinedMessage`.                                                                                             |
| `connection`  | `object`           | Sim                                   | `{ id }` ou `{ uuid }` da conexão. Precisa estar ativa.                                                                                                           |
| `contact`     | `object`           | Sim                                   | `{ id }` ou `{ phone }` do destinatário. Com `phone`, o Hust normaliza o número (falta de DDI, DDD ou nono dígito) e cadastra o contato se ele ainda não existir. |
| `department`  | `object`           | Ver [Modos de envio](#modos-de-envio) | `{ id }` do departamento. O usuário do token precisa pertencer a ele.                                                                                             |
| `called`      | `object \| string` | Não                                   | `"without"` ou `{ id }`. Veja [Modos de envio](#modos-de-envio).                                                                                                  |
| `signMessage` | `boolean`          | Não — padrão `true`                   | Ativa a assinatura automática. Veja [abaixo](#assinatura-automatica).                                                                                             |
| `reply`       | `object`           | Não                                   | `{ id }` da mensagem sendo respondida.                                                                                                                            |

## Exemplo mínimo

O jeito mais enxuto de mandar uma mensagem de texto: sem abrir atendimento, então sem `department`.

<Tip>
  Omitir `called` **não** tem o mesmo efeito — nesse caso o `department` volta a ser obrigatório. É preciso enviar `"called": "without"` explicitamente. Veja [Modos de envio](#modos-de-envio).
</Tip>

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.hustapp.com/message/send \
    -H "Authorization: Bearer SEU_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "type": "text",
      "text": "Olá! Seu pedido foi confirmado.",
      "connection": { "uuid": "9db04f68-9e7d-4297-ba41-5f4d4c44779a" },
      "contact": { "phone": "5541988887777" },
      "called": "without"
    }'
  ```

  ```javascript Node.js theme={null}
  const res = await fetch("https://api.hustapp.com/message/send", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${token}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      type: "text",
      text: "Olá! Seu pedido foi confirmado.",
      connection: { uuid: "9db04f68-9e7d-4297-ba41-5f4d4c44779a" },
      contact: { phone: "5541988887777" },
      called: "without",
    }),
  });

  const message = await res.json();
  ```

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

  res = requests.post(
      "https://api.hustapp.com/message/send",
      headers={"Authorization": f"Bearer {token}"},
      json={
          "type": "text",
          "text": "Olá! Seu pedido foi confirmado.",
          "connection": {"uuid": "9db04f68-9e7d-4297-ba41-5f4d4c44779a"},
          "contact": {"phone": "5541988887777"},
          "called": "without",
      },
  )

  message = res.json()
  ```

  ```php PHP theme={null}
  <?php
  $ch = curl_init('https://api.hustapp.com/message/send');
  curl_setopt_array($ch, [
      CURLOPT_POST => true,
      CURLOPT_RETURNTRANSFER => true,
      CURLOPT_HTTPHEADER => [
          'Authorization: Bearer ' . $token,
          'Content-Type: application/json',
      ],
      CURLOPT_POSTFIELDS => json_encode([
          'type' => 'text',
          'text' => 'Olá! Seu pedido foi confirmado.',
          'connection' => ['uuid' => '9db04f68-9e7d-4297-ba41-5f4d4c44779a'],
          'contact' => ['phone' => '5541988887777'],
          'called' => 'without',
      ]),
  ]);

  $response = curl_exec($ch);
  curl_close($ch);

  $message = json_decode($response, true);
  ```

  ```pascal Delphi theme={null}
  uses
    System.Net.HttpClient, System.JSON;

  var
    HttpClient: THTTPClient;
    Response: IHTTPResponse;
    RequestBody, Connection, Contact: TJSONObject;
  begin
    HttpClient := THTTPClient.Create;
    try
      RequestBody := TJSONObject.Create;
      try
        Connection := TJSONObject.Create.AddPair('uuid', '9db04f68-9e7d-4297-ba41-5f4d4c44779a');
        Contact := TJSONObject.Create.AddPair('phone', '5541988887777');

        RequestBody.AddPair('type', 'text');
        RequestBody.AddPair('text', 'Olá! Seu pedido foi confirmado.');
        RequestBody.AddPair('connection', Connection);
        RequestBody.AddPair('contact', Contact);
        RequestBody.AddPair('called', 'without');

        HttpClient.CustomHeaders['Authorization'] := 'Bearer ' + Token;
        HttpClient.ContentType := 'application/json';
        Response := HttpClient.Post('https://api.hustapp.com/message/send',
          TStringStream.Create(RequestBody.ToJSON, TEncoding.UTF8));
      finally
        RequestBody.Free;
      end;
    finally
      HttpClient.Free;
    end;
  end;
  ```
</CodeGroup>

## Exemplo abrindo atendimento

Sem `called`, a mensagem entra no fluxo de chamado e `department` passa a ser obrigatório:

```json theme={null}
{
  "type": "text",
  "text": "Olá! Seu pedido foi confirmado.",
  "connection": { "uuid": "9db04f68-9e7d-4297-ba41-5f4d4c44779a" },
  "contact": { "phone": "5541988887777" },
  "department": { "id": 169070 }
}
```

## Assinatura automática

Se a conexão estiver configurada para mostrar o nome do atendente e você não enviar `signMessage: false`, o Hust altera o texto antes de enviar:

```text theme={null}
🙎‍♂️ *Maria Silva:*
Olá! Seu pedido foi confirmado.
```

O campo `body` da resposta já vem com o prefixo aplicado. Se a sua integração compara o texto enviado com o texto retornado, use `signMessage: false`.

## Conexão efetivamente usada

A conexão da resposta pode ser diferente da que você informou. Dois mecanismos podem redirecionar o envio:

<AccordionGroup>
  <Accordion title="Contas Co-Ex (WABA + QR)" icon="arrows-left-right">
    Quando a empresa tem uma conexão WABA e uma QR para o mesmo número, o Hust escolhe entre elas conforme a janela de 24 horas da última mensagem do contato. Não se aplica a grupos.
  </Accordion>

  <Accordion title="Conexão master" icon="star">
    Com a configuração de troca de conexão ativa, o chamado e a mensagem são movidos para a conexão marcada como master da empresa.
  </Accordion>
</AccordionGroup>

Sempre leia `connection` na resposta em vez de assumir a conexão que você enviou.

## Resposta

Retorna `200` com os campos da mensagem, mais o chamado e o alerta de risco.

| Campo                      | Tipo      | Descrição                                                                                            |
| -------------------------- | --------- | ---------------------------------------------------------------------------------------------------- |
| `id`                       | `integer` | ID da mensagem no Hust.                                                                              |
| `body`                     | `string`  | Texto efetivamente enviado, já com a assinatura aplicada quando houver.                              |
| `type`                     | `string`  | Tipo da mensagem.                                                                                    |
| `ack`                      | `integer` | Estágio de entrega. Nasce em aguardando e evolui depois, conforme o WhatsApp confirma o recebimento. |
| `sent`                     | `boolean` | Indica que a mensagem foi aceita e enfileirada.                                                      |
| `date`                     | `string`  | Data e hora do registro, em ISO 8601.                                                                |
| `connection`               | `object`  | A conexão usada no envio — pode diferir da informada.                                                |
| `contact`                  | `object`  | O contato destinatário.                                                                              |
| `user`                     | `object`  | O usuário dono do token.                                                                             |
| `called`                   | `object`  | O chamado vinculado. Com `called: "without"`, traz só conexão e contato.                             |
| `connectionRiskScoreAlert` | `boolean` | Quando `true`, o envio foi retido por risco e não entrou na fila.                                    |

```json Exemplo de resposta theme={null}
{
  "id": 255678,
  "date": "2026-09-01T14:32:10.000Z",
  "body": "🙎‍♂️ *Maria Silva:*\nOlá! Seu pedido foi confirmado.",
  "type": "text",
  "ack": 0,
  "sent": true,
  "identifier": "3EB0C767D26B8F1A2C11",
  "connection": {
    "id": 919872,
    "name": "Comercial",
    "uuid": "9db04f68-9e7d-4297-ba41-5f4d4c44779a",
    "active": true,
    "type": "whatsapp"
  },
  "contact": {
    "id": 111211,
    "name": "José Maria",
    "idWhatsapp": "5541988887777@c.us"
  },
  "user": {
    "id": 42,
    "name": "Maria Silva",
    "email": "voce@empresa.com.br"
  },
  "connectionRiskScoreAlert": false
}
```

<Note>
  O `200` significa que a mensagem foi enfileirada, não que chegou ao destinatário. Acompanhe o `ack` para confirmar a entrega.
</Note>

## Erros

Todos os erros retornam **400**, inclusive falhas de validação e de autenticação de conexão.

```json theme={null}
{
  "userMessage": "É necessário definir o departamento para abertura do chamado.",
  "code": "MISSING_START_CALLED_DEPARTMENT",
  "actions": { "takeOver": false }
}
```

| Código                                      | Significado                                                      |
| ------------------------------------------- | ---------------------------------------------------------------- |
| `MISSING_TEXT`                              | `type` é `text` mas nenhum texto foi informado.                  |
| `MISSING_START_CALLED_CONTACT_INFORMATIONS` | Contato ausente ou não resolvido.                                |
| `MISSING_START_CALLED_CONNECTION`           | Conexão ausente ou não resolvida.                                |
| `MISSING_START_CALLED_DEPARTMENT`           | Departamento obrigatório não informado.                          |
| `CONTACT_NOT_FOUND`                         | O contato informado não existe.                                  |
| `CONNECTION_NOT_FOUND`                      | A conexão informada não existe.                                  |
| `DEPARTMENT_NOT_FOUND`                      | O departamento informado não existe.                             |
| `CALLED_NOT_FOUND`                          | O `called.id` informado não existe para esta empresa.            |
| `CALLED_ALREADY_STARTED`                    | Já existe atendimento aberto para o contato com outro atendente. |
| `CONNECTION_INACTIVE`                       | A conexão não está ativa.                                        |
| `CONNECTION_EXPIRED`                        | A autenticação da conexão WABA com a Meta expirou.               |
| `INVALID_LOCATION`                          | Envio de localização sem latitude ou longitude.                  |

Em `CALLED_ALREADY_STARTED`, o campo `actions` traz `takeOver` e os dados do chamado, permitindo que a interface ofereça a transferência do atendimento.
