user_docs/guides/media.md

# Send and Download Media

Use this guide when you need to upload or download images, video, audio, documents, or stickers.

## Quick start

Send a file by passing a media field to `BaileysEx.send_message/4`.

All outbound send examples on this page assume the connection was started with
`connect/2` with the default Signal credentials in auth state, or override the
repository explicitly with `:signal_repository` or `:signal_repository_adapter`.

```elixir
{:ok, _sent} =
  BaileysEx.send_message(connection, "15551234567@s.whatsapp.net", %{
    image: {:file, "priv/photos/launch.jpg"},
    caption: "Launch photo"
  })
```

## Options

These keys are the ones you will use most often:

- `caption:` add text to images, video, and documents
- `mimetype:` override MIME detection when the file extension is not enough
- `file_name:` set the visible document name
- `ptt:` mark audio as a voice note
- `gif_playback:` send a video as a GIF-style looping clip

→ See [Message Types Reference](../reference/message-types.md#media-content) for the complete media payload shapes.

## Common patterns

### Send a document

```elixir
{:ok, _sent} =
  BaileysEx.send_message(connection, "15551234567@s.whatsapp.net", %{
    document: {:file, "priv/spec.pdf"},
    file_name: "spec.pdf",
    mimetype: "application/pdf",
    caption: "Current API spec"
  })
```

### Send a voice note

```elixir
{:ok, _sent} =
  BaileysEx.send_message(connection, "15551234567@s.whatsapp.net", %{
    audio: {:file, "priv/audio/note.ogg"},
    ptt: true,
    mimetype: "audio/ogg"
  })
```

### Download media into memory

```elixir
{:ok, binary} = BaileysEx.download_media(image_message)
```

### Download media directly to disk

```elixir
{:ok, path} = BaileysEx.download_media_to_file(image_message, "tmp/photo.jpg")
```

The file-based download path keeps memory use lower for larger payloads.

### Refresh stale media URLs before download

If a media message has an expired `url` or `direct_path`, ask the paired device to
refresh it first:

```elixir
{:ok, refreshed} = BaileysEx.update_media_message(connection, incoming)
{:ok, binary} = BaileysEx.download_media(refreshed.message.image_message)
```

On success, BaileysEx also emits a `messages_update` event with the refreshed
message payload, matching Baileys' observable behavior.

## Limitations

- Media sending requires a live connection because BaileysEx uploads encrypted blobs before it relays the message.
- Media sending also requires the default Signal credentials in auth state, or an explicit `:signal_repository` / `:signal_repository_adapter` override.
- `download_media/2` and `download_media_to_file/3` need a valid media message with `url` or `direct_path` and a `media_key`.
- `update_media_message/3` requires the original `WebMessageInfo` for the media message, not only the nested media struct.
- Thumbnail generation depends on the available thumbnail helpers for the selected media type.

---

**See also:**
- [Send Messages](messages.md) — combine media with quoted replies and other message features
- [Message Types Reference](../reference/message-types.md)
- [Troubleshooting: Connection Issues](../troubleshooting/connection-issues.md)