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

# Enviar Mídia

> Envia imagem, vídeo, áudio (voz/regular) ou documento por URL ou base64

**Auth:** `TokenAccount` ou `TokenInstance` • **Rate-limit:** `Global` (100/min) • **Idempotente:** não

## Descrição

Envia uma mídia (`image`, `video`, `document` ou `audio`) a partir de uma **URL pública** ou de uma **string base64**. A origem pode ser informada em `mediaUrl` (que aceita tanto a URL quanto o base64 da mídia) **ou** no campo `mediaBase64`, envie um ou outro, nunca os dois. Suporta `message` como legenda (caption), `replyTo` (citação por ID), `replyPrivate`, `mention` / `mentionAll` (apenas em grupos), `delay` (em segundos) para simular digitação real e, para áudio, `isVoice` (PTT), `duration` e `waveform`. O servidor faz o download (quando URL) ou decodifica o base64, detecta o `mimeType` quando omitido e faz o upload nos servidores do WhatsApp antes do envio.

## Exemplos

### Imagem por URL

Envia uma imagem (`mediaType: "image"`) baixada de uma URL pública, com `message` usado como legenda (caption) que aparece abaixo da foto no chat.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://ryzeapi.cloud/api/message/media/$Instance_Name" \
    -H "token: $Token_Instance" \
    -H "Content-Type: application/json" \
    -d '{
      "number":    "5511999999999",
      "mediaType": "image",
      "mediaUrl":  "https://exemplo.com/foto.jpg",
      "message":   "Confere essa foto!"
    }'
  ```

  ```javascript JavaScript theme={null}
  await fetch(`https://ryzeapi.cloud/api/message/media/${process.env.Instance_Name}`, {
    method: "POST",
    headers: {
      "token":        process.env.Token_Instance,
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      number:    "5511999999999",
      mediaType: "image",
      mediaUrl:  "https://exemplo.com/foto.jpg",
      message:   "Confere essa foto!"
    })
  });
  ```

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

  requests.post(
      f"https://ryzeapi.cloud/api/message/media/{os.environ['Instance_Name']}",
      headers={
          "token":        os.environ["Token_Instance"],
          "Content-Type": "application/json"
      },
      json={
          "number":    "5511999999999",
          "mediaType": "image",
          "mediaUrl":  "https://exemplo.com/foto.jpg",
          "message":   "Confere essa foto!"
      }
  )
  ```

  ```go Go theme={null}
  package main

  import (
      "net/http"
      "os"
      "strings"
  )

  func main() {
      body := strings.NewReader(`{
          "number":    "5511999999999",
          "mediaType": "image",
          "mediaUrl":  "https://exemplo.com/foto.jpg",
          "message":   "Confere essa foto!"
      }`)
      req, _ := http.NewRequest("POST", "https://ryzeapi.cloud/api/message/media/"+os.Getenv("Instance_Name"), body)
      req.Header.Set("token", os.Getenv("Token_Instance"))
      req.Header.Set("Content-Type", "application/json")
      http.DefaultClient.Do(req)
  }
  ```
</CodeGroup>

### Imagem por base64

Em vez de uma URL, envie o conteúdo da mídia em base64. Você pode colocar o base64 no próprio `mediaUrl` (com ou sem prefixo data URI `data:image/jpeg;base64,`) **ou** no campo dedicado `mediaBase64`. Como não há URL para inferir o nome/tipo, recomenda-se informar `mimeType` (e `fileName`, para documentos).

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://ryzeapi.cloud/api/message/media/$Instance_Name" \
    -H "token: $Token_Instance" \
    -H "Content-Type: application/json" \
    -d '{
      "number":      "5511999999999",
      "mediaType":   "image",
      "mediaBase64": "/9j/4AAQSkZJRgABAQAAAQABAAD...",
      "mimeType":    "image/jpeg",
      "message":     "Confere essa foto!"
    }'
  ```

  ```javascript JavaScript theme={null}
  await fetch(`https://ryzeapi.cloud/api/message/media/${process.env.Instance_Name}`, {
    method: "POST",
    headers: {
      "token":        process.env.Token_Instance,
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      number:      "5511999999999",
      mediaType:   "image",
      mediaBase64: "/9j/4AAQSkZJRgABAQAAAQABAAD...",
      mimeType:    "image/jpeg",
      message:     "Confere essa foto!"
    })
  });
  ```

  ```python Python theme={null}
  import os, base64, requests

  with open("foto.jpg", "rb") as f:
      media_b64 = base64.b64encode(f.read()).decode()

  requests.post(
      f"https://ryzeapi.cloud/api/message/media/{os.environ['Instance_Name']}",
      headers={
          "token":        os.environ["Token_Instance"],
          "Content-Type": "application/json"
      },
      json={
          "number":      "5511999999999",
          "mediaType":   "image",
          "mediaBase64": media_b64,
          "mimeType":    "image/jpeg",
          "message":     "Confere essa foto!"
      }
  )
  ```

  ```go Go theme={null}
  package main

  import (
      "net/http"
      "os"
      "strings"
  )

  func main() {
      body := strings.NewReader(`{
          "number":      "5511999999999",
          "mediaType":   "image",
          "mediaBase64": "/9j/4AAQSkZJRgABAQAAAQABAAD...",
          "mimeType":    "image/jpeg",
          "message":     "Confere essa foto!"
      }`)
      req, _ := http.NewRequest("POST", "https://ryzeapi.cloud/api/message/media/"+os.Getenv("Instance_Name"), body)
      req.Header.Set("token", os.Getenv("Token_Instance"))
      req.Header.Set("Content-Type", "application/json")
      http.DefaultClient.Do(req)
  }
  ```
</CodeGroup>

### Áudio de voz (PTT)

Quando `mediaType: "audio"` e `isVoice` é omitido, o servidor assume `true` por padrão (mensagem de voz/PTT). Para enviar como áudio "regular" (faixa de música, por exemplo), passe `isVoice: false`.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://ryzeapi.cloud/api/message/media/$Instance_Name" \
    -H "token: $Token_Instance" \
    -H "Content-Type: application/json" \
    -d '{
      "number":    "5511999999999",
      "mediaType": "audio",
      "mediaUrl":  "https://exemplo.com/audio.ogg",
      "isVoice":   true
    }'
  ```

  ```javascript JavaScript theme={null}
  await fetch(`https://ryzeapi.cloud/api/message/media/${process.env.Instance_Name}`, {
    method: "POST",
    headers: {
      "token":        process.env.Token_Instance,
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      number:    "5511999999999",
      mediaType: "audio",
      mediaUrl:  "https://exemplo.com/audio.ogg",
      isVoice:   true
    })
  });
  ```

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

  requests.post(
      f"https://ryzeapi.cloud/api/message/media/{os.environ['Instance_Name']}",
      headers={
          "token":        os.environ["Token_Instance"],
          "Content-Type": "application/json"
      },
      json={
          "number":    "5511999999999",
          "mediaType": "audio",
          "mediaUrl":  "https://exemplo.com/audio.ogg",
          "isVoice":   True
      }
  )
  ```

  ```go Go theme={null}
  package main

  import (
      "net/http"
      "os"
      "strings"
  )

  func main() {
      body := strings.NewReader(`{
          "number":    "5511999999999",
          "mediaType": "audio",
          "mediaUrl":  "https://exemplo.com/audio.ogg",
          "isVoice":   true
      }`)
      req, _ := http.NewRequest("POST", "https://ryzeapi.cloud/api/message/media/"+os.Getenv("Instance_Name"), body)
      req.Header.Set("token", os.Getenv("Token_Instance"))
      req.Header.Set("Content-Type", "application/json")
      http.DefaultClient.Do(req)
  }
  ```
</CodeGroup>

### Documento (PDF) com `fileName`

Envia um PDF como documento. O `fileName` (`Contrato-2026.pdf`) define o nome exibido no card do anexo e o `message` aparece como texto acompanhante. Sem `fileName`, o WhatsApp mostra um nome genérico.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://ryzeapi.cloud/api/message/media/$Instance_Name" \
    -H "token: $Token_Instance" \
    -H "Content-Type: application/json" \
    -d '{
      "number":    "5511999999999",
      "mediaType": "document",
      "mediaUrl":  "https://exemplo.com/contrato.pdf",
      "fileName":  "Contrato-2026.pdf",
      "message":   "Segue o contrato anexo."
    }'
  ```

  ```javascript JavaScript theme={null}
  await fetch(`https://ryzeapi.cloud/api/message/media/${process.env.Instance_Name}`, {
    method: "POST",
    headers: {
      "token":        process.env.Token_Instance,
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      number:    "5511999999999",
      mediaType: "document",
      mediaUrl:  "https://exemplo.com/contrato.pdf",
      fileName:  "Contrato-2026.pdf",
      message:   "Segue o contrato anexo."
    })
  });
  ```

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

  requests.post(
      f"https://ryzeapi.cloud/api/message/media/{os.environ['Instance_Name']}",
      headers={
          "token":        os.environ["Token_Instance"],
          "Content-Type": "application/json"
      },
      json={
          "number":    "5511999999999",
          "mediaType": "document",
          "mediaUrl":  "https://exemplo.com/contrato.pdf",
          "fileName":  "Contrato-2026.pdf",
          "message":   "Segue o contrato anexo."
      }
  )
  ```

  ```go Go theme={null}
  package main

  import (
      "net/http"
      "os"
      "strings"
  )

  func main() {
      body := strings.NewReader(`{
          "number":    "5511999999999",
          "mediaType": "document",
          "mediaUrl":  "https://exemplo.com/contrato.pdf",
          "fileName":  "Contrato-2026.pdf",
          "message":   "Segue o contrato anexo."
      }`)
      req, _ := http.NewRequest("POST", "https://ryzeapi.cloud/api/message/media/"+os.Getenv("Instance_Name"), body)
      req.Header.Set("token", os.Getenv("Token_Instance"))
      req.Header.Set("Content-Type", "application/json")
      http.DefaultClient.Do(req)
  }
  ```
</CodeGroup>

### Vídeo com legenda e delay

Envia um vídeo MP4 com a legenda "Olha esse vídeo!" e `delay: 3`, o servidor envia o indicador de "digitando..." por 3 segundos antes de disparar o vídeo, simulando uma digitação real.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://ryzeapi.cloud/api/message/media/$Instance_Name" \
    -H "token: $Token_Instance" \
    -H "Content-Type: application/json" \
    -d '{
      "number":    "5511999999999",
      "mediaType": "video",
      "mediaUrl":  "https://exemplo.com/video.mp4",
      "message":   "Olha esse vídeo!",
      "delay":     3
    }'
  ```

  ```javascript JavaScript theme={null}
  await fetch(`https://ryzeapi.cloud/api/message/media/${process.env.Instance_Name}`, {
    method: "POST",
    headers: {
      "token":        process.env.Token_Instance,
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      number:    "5511999999999",
      mediaType: "video",
      mediaUrl:  "https://exemplo.com/video.mp4",
      message:   "Olha esse vídeo!",
      delay:     3
    })
  });
  ```

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

  requests.post(
      f"https://ryzeapi.cloud/api/message/media/{os.environ['Instance_Name']}",
      headers={
          "token":        os.environ["Token_Instance"],
          "Content-Type": "application/json"
      },
      json={
          "number":    "5511999999999",
          "mediaType": "video",
          "mediaUrl":  "https://exemplo.com/video.mp4",
          "message":   "Olha esse vídeo!",
          "delay":     3
      }
  )
  ```

  ```go Go theme={null}
  package main

  import (
      "net/http"
      "os"
      "strings"
  )

  func main() {
      body := strings.NewReader(`{
          "number":    "5511999999999",
          "mediaType": "video",
          "mediaUrl":  "https://exemplo.com/video.mp4",
          "message":   "Olha esse vídeo!",
          "delay":     3
      }`)
      req, _ := http.NewRequest("POST", "https://ryzeapi.cloud/api/message/media/"+os.Getenv("Instance_Name"), body)
      req.Header.Set("token", os.Getenv("Token_Instance"))
      req.Header.Set("Content-Type", "application/json")
      http.DefaultClient.Do(req)
  }
  ```
</CodeGroup>

### Imagem em grupo com reply e menção

Envia uma imagem em um grupo (`@g.us`) citando uma mensagem anterior via `replyTo` e mencionando um membro pelo array `mention`. O `@5511888888888` na caption fica clicável, gerando notificação para o usuário marcado.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://ryzeapi.cloud/api/message/media/$Instance_Name" \
    -H "token: $Token_Instance" \
    -H "Content-Type: application/json" \
    -d '{
      "number":    "120363406289005073@g.us",
      "mediaType": "image",
      "mediaUrl":  "https://exemplo.com/banner.jpg",
      "message":   "Olha só @5511888888888, ficou pronto!",
      "replyTo":   "3EB08FCF27E532F1B0F5",
      "mention":   ["5511888888888"]
    }'
  ```

  ```javascript JavaScript theme={null}
  await fetch(`https://ryzeapi.cloud/api/message/media/${process.env.Instance_Name}`, {
    method: "POST",
    headers: {
      "token":        process.env.Token_Instance,
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      number:    "120363406289005073@g.us",
      mediaType: "image",
      mediaUrl:  "https://exemplo.com/banner.jpg",
      message:   "Olha só @5511888888888, ficou pronto!",
      replyTo:   "3EB08FCF27E532F1B0F5",
      mention:   ["5511888888888"]
    })
  });
  ```

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

  requests.post(
      f"https://ryzeapi.cloud/api/message/media/{os.environ['Instance_Name']}",
      headers={
          "token":        os.environ["Token_Instance"],
          "Content-Type": "application/json"
      },
      json={
          "number":    "120363406289005073@g.us",
          "mediaType": "image",
          "mediaUrl":  "https://exemplo.com/banner.jpg",
          "message":   "Olha só @5511888888888, ficou pronto!",
          "replyTo":   "3EB08FCF27E532F1B0F5",
          "mention":   ["5511888888888"]
      }
  )
  ```

  ```go Go theme={null}
  package main

  import (
      "net/http"
      "os"
      "strings"
  )

  func main() {
      body := strings.NewReader(`{
          "number":    "120363406289005073@g.us",
          "mediaType": "image",
          "mediaUrl":  "https://exemplo.com/banner.jpg",
          "message":   "Olha só @5511888888888, ficou pronto!",
          "replyTo":   "3EB08FCF27E532F1B0F5",
          "mention":   ["5511888888888"]
      }`)
      req, _ := http.NewRequest("POST", "https://ryzeapi.cloud/api/message/media/"+os.Getenv("Instance_Name"), body)
      req.Header.Set("token", os.Getenv("Token_Instance"))
      req.Header.Set("Content-Type", "application/json")
      http.DefaultClient.Do(req)
  }
  ```
</CodeGroup>

## Resposta de sucesso

O `messageType` ecoa o `mediaType` enviado (`image`, `video`, `document` ou `audio`). Os metadados resolvidos pelo upload aparecem em `mediaUrl` (URL re-enviada para `mmg.whatsapp.net`), `mediaMimeType` e `mediaSize`. Para áudios PTT, o servidor também devolve `mediaDuration` quando consegue calcular.

```json 200 OK theme={null}
{
  "success": true,
  "message": "Media message sent successfully",
  "status":  "sent",
  "data": {
    "messageId":     "3EB08FCF27E532F1B0F5",
    "direction":     "outgoing",
    "messageType":   "image",
    "content":       "Confere essa foto!",
    "source":        "api",
    "timestamp":     "2026-04-30T14:30:00Z",
    "mediaUrl":      "https://mmg.whatsapp.net/v/t62.7118-24/...",
    "mediaMimeType": "image/jpeg",
    "mediaSize":     184320,
    "chat": {
      "jid":     "5511999999999@s.whatsapp.net",
      "isGroup": false
    },
    "sender": {
      "jid":      "5511777777777@s.whatsapp.net",
      "instance": "minha-instancia"
    }
  }
}
```

<Note>
  Para `mediaType: "document"`, o `fileName` aparece no card. Para `mediaType: "audio"` com `isVoice: true`, a mensagem é entregue como PTT (forma de onda + ícone de microfone). Para áudios "regulares" (faixa de música), use `isVoice: false`.
</Note>

## Parâmetros de rota

<ParamField path="instance" type="string" required>
  Nome da instância (ex.: `$Instance_Name`).
</ParamField>

## Headers

<ParamField header="token" type="string" required>
  `TokenAccount` ou `TokenInstance`.
</ParamField>

<ParamField header="Content-Type" type="string" required>
  `application/json`
</ParamField>

## Request body

<ParamField body="number" type="string" required>
  Destino: telefone (`5511999999999`) ou JID (`@s.whatsapp.net`, `@lid`, `@g.us`, `@newsletter`).
</ParamField>

<ParamField body="mediaType" type="string" required>
  Um de: `image`, `video`, `document`, `audio`. Determina como o WhatsApp renderiza a mensagem.
</ParamField>

<ParamField body="mediaUrl" type="string">
  Origem da mídia: uma **URL pública** do arquivo **ou** o **base64** da mídia (com data URI `data:<mime>;base64,...` ou base64 cru). Quando é URL, precisa ser acessível publicamente (sem autenticação) e o servidor faz o download. Obrigatório informar `mediaUrl` **ou** `mediaBase64` (nunca os dois).
</ParamField>

<ParamField body="mediaBase64" type="string">
  Base64 da mídia (alternativa ao `mediaUrl`), com data URI `data:<mime>;base64,...` ou base64 cru. **Não pode ser usado junto com `mediaUrl`**, envie um ou outro. Como não há URL, recomenda-se informar `mimeType` (e `fileName` para documentos).
</ParamField>

<ParamField body="message" type="string">
  Legenda (caption) da mídia. Para `mediaType: "document"`, aparece como texto acompanhante. Opcional para todos os tipos.
</ParamField>

<ParamField body="mimeType" type="string">
  MIME type do arquivo (ex.: `image/jpeg`, `application/pdf`). Quando omitido, o servidor detecta automaticamente a partir do download.
</ParamField>

<ParamField body="fileName" type="string">
  Nome do arquivo exibido no card. **Recomendado para `mediaType: "document"`**, sem ele, o WhatsApp mostra um nome genérico.
</ParamField>

<ParamField body="isVoice" type="boolean" default="true (para audio)">
  Aplicável apenas a `mediaType: "audio"`. Quando `true`, a mensagem é entregue como **PTT** (mensagem de voz, com forma de onda). Quando `false`, é entregue como áudio regular (faixa de música). Quando o campo é omitido em `audio`, o servidor assume `true`.
</ParamField>

<ParamField body="duration" type="uint32">
  Duração do áudio em segundos. Aplicável apenas a `mediaType: "audio"`. Opcional, quando omitido, o servidor tenta detectar automaticamente.
</ParamField>

<ParamField body="waveform" type="byte[]">
  Forma de onda pré-computada do áudio (PTT). Opcional, quando omitida, o servidor gera automaticamente uma forma de onda padrão. Aplicável apenas a `mediaType: "audio"` com `isVoice: true`.
</ParamField>

<ParamField body="delay" type="int" default="0">
  Tempo em **segundos** para aguardar antes de enviar. Durante o intervalo, o servidor envia o indicador de "digitando..." ao destinatário e dispara o "paused" antes do envio real.
</ParamField>

<ParamField body="replyTo" type="string">
  ID da mensagem a ser citada (reply). A mensagem original precisa pertencer à mesma instância e ter sido salva no banco. Erros possíveis: `reply_message_not_found`, `reply_message_instance_mismatch`.
</ParamField>

<ParamField body="replyPrivate" type="boolean" default="false">
  Quando `true` **e** `replyTo` aponta para uma mensagem originária de um grupo, a resposta é redirecionada para o **privado** do autor original (mantendo a citação). Ignorado se a mensagem original não for de grupo.
</ParamField>

<ParamField body="mention" type="string[]">
  Lista de números (ou JIDs) a mencionar. **Apenas em grupos** (`@g.us`). Para que apareçam como link clicável, inclua `@5511...` na `message` (caption). Sem isso, viram menções ocultas (apenas notificam).
</ParamField>

<ParamField body="mentionAll" type="boolean" default="false">
  Quando `true`, menciona **todos os membros do grupo** (exceto a própria instância). Equivale ao `@todos`/`@everyone`. **Apenas em grupos.**
</ParamField>

<ParamField body="source" type="string" default="api">
  Identificador de origem para rastreabilidade (ex.: `crm`, `bot-suporte`, `n8n`). Salvo no registro da mensagem no banco e propagado para webhooks. Quando omitido, assume `"api"`.
</ParamField>

## Notas

<Note>
  * **`delay` é em segundos**, não milissegundos. Valor `3` = 3 segundos de "digitando".
  * Para `mediaType: "audio"`, **`isVoice` assume `true`** automaticamente quando o campo é omitido. Para enviar como faixa de música, é necessário enviar `isVoice: false` explicitamente.
  * A mídia pode vir por **URL** ou **base64**. Use `mediaUrl` (que aceita URL ou base64) **ou** `mediaBase64`, enviar os dois retorna `400 use either mediaUrl or mediaBase64, not both`; não enviar nenhum retorna `400 mediaUrl or mediaBase64 is required`.
  * Quando `mediaUrl` é uma URL, precisa ser **publicamente acessível**. URLs com autenticação, sessão ou proteção contra bots costumam falhar com `media_download_failed`.
  * Para envio em base64, informar `mimeType` é recomendado (não há URL para inferir o tipo). O base64 aceita data URI (`data:<mime>;base64,...`) ou base64 cru.
  * Quando `mimeType` não é informado, o servidor detecta a partir dos primeiros bytes do download (`net/http` + sniff). Em casos raros (extensão atípica), informar manualmente evita problemas.
  * Para números BR (começando com `55`), o serviço tenta automaticamente variações com e sem o 9º dígito.
  * `mention` e `mentionAll` são exclusivos a grupos. Se enviados para DM/canal, retorna `400 Mentions are only supported in group chats`.
  * O campo `duration` (áudio) é informativo, `whatsmeow` ainda calcula seu próprio valor a partir do arquivo. Útil quando o servidor não consegue inferir.
  * O campo `waveform` é opcional e advisory: se omitido, o servidor gera uma forma de onda padronizada para PTT.
</Note>

## Erros

| HTTP | Status interno            | Mensagem                                                  |
| ---- | ------------------------- | --------------------------------------------------------- |
| 400  | ,                         | `Instance name is required`                               |
| 400  | ,                         | `Invalid request body: <detalhe>`                         |
| 400  | ,                         | `Number is required`                                      |
| 400  | ,                         | `MediaType is required`                                   |
| 400  | ,                         | `mediaUrl or mediaBase64 is required`                     |
| 400  | ,                         | `use either mediaUrl or mediaBase64, not both`            |
| 400  | ,                         | `MediaType must be one of: image, video, document, audio` |
| 400  | `invalid_number`          | `Invalid phone number format: <detalhe>`                  |
| 400  | `mentions_not_supported`  | `Mentions are only supported in group chats`              |
| 400  | `media_download_failed`   | `Failed to download media: <reason>`                      |
| 400  | `media_input_invalid`     | `Failed to resolve media: <reason>`                       |
| 400  | `media_validation_failed` | `Invalid media file: <reason>`                            |
| 400  | `unsupported_media_type`  | `Unsupported media type: <mime>`                          |
| 500  | `media_upload_failed`     | `Failed to upload media to WhatsApp servers`              |
| 500  | `send_failed`             | `Failed to send message: <reason>`                        |
| 404  | ,                         | `Instance not found`                                      |
| 503  | `disconnected`            | `Instance is not connected to WhatsApp`                   |

Envelope de erro:

```json theme={null}
{
  "success": false,
  "error": { "message": "mediaUrl or mediaBase64 is required" }
}
```
