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

# Media

> Upload one owned WhatsApp attachment and refresh its temporary download access

Paths are relative to `https://inkbox.ai/api/v1/whatsapp`. Media belongs to the selected agent identity. A message accepts at most one media ID.

## Upload an attachment

```text theme={null}
POST /media
```

Send multipart form data with a `file` field within the current [`whatsapp.max_media_bytes` limit](https://inkbox.ai/docs/api/whatsapp/limits). Its initial fallback is 5 MiB; 20 MiB is the transport ceiling, not the default allowance. Use the `agent_identity_id` query parameter when selecting the agent with an organization-wide credential. Returns `201` with a flat media object. Uploading does not grant permission to message a recipient: before their first WhatsApp reply, sending media also requires `whatsapp.pre_reply_media_allowed` (initially `0`). The direct-message send examples below assume a recipient who has replied or an organization policy that permits opening media. Group attachments require an existing conversation where another participant’s message has been received; uploading a file does not satisfy that requirement.

```bash cURL theme={null}
curl -X POST \
  "https://inkbox.ai/api/v1/whatsapp/media?agent_identity_id=11111111-1111-4111-8111-111111111111" \
  -H "X-API-Key: YOUR_API_KEY" \
  -F "file=@project-brief.pdf;type=application/pdf"
```

```python Python theme={null}
from pathlib import Path

media = identity.upload_whatsapp_media(
    content=Path("project-brief.pdf").read_bytes(),
    filename="project-brief.pdf",
    content_type="application/pdf",
)
message = identity.send_whatsapp(
    to="+15555550123",
    text="Here is the brief.",
    media_ids=[media.id],
    idempotency_key="project-brief-file",
)
```

```typescript TypeScript theme={null}
import { readFile } from "node:fs/promises";

const media = await identity.uploadWhatsAppMedia({
  content: await readFile("project-brief.pdf"),
  filename: "project-brief.pdf",
  contentType: "application/pdf",
});
const message = await identity.sendWhatsApp({
  to: "+15555550123",
  text: "Here is the brief.",
  mediaIds: [media.id],
  idempotencyKey: "project-brief-file",
});
```

```bash CLI theme={null}
inkbox whatsapp upload-media project-brief.pdf --identity my-agent \
  --content-type application/pdf
inkbox whatsapp send --identity my-agent --to +15555550123 \
  --text "Here is the brief." \
  --media-id 44444444-4444-4444-8444-444444444444 \
  --idempotency-key project-brief-file
```

Use the returned media ID in the send, not the example UUID. Upload and send are separate operations. Save the media ID before sending and reuse it after a timeout. Do not upload again merely because the send response was lost.

## Media in existing groups

Use the same upload endpoint, then send `media_ids` with the group’s `conversation_id`. Images, videos, audio, and documents are supported. GIF playback requires SDK or CLI `0.7.29` or later and also works in eligible direct conversations. If animation is not available on the connection, a `gif_playback` send returns `409 whatsapp_capability_not_ready` without admitting a message. To show an MP4 video as an animation, set `gif_playback: true` (`gif_playback=True` in Python, `gifPlayback: true` in TypeScript, or `--gif-playback` in the CLI). Upload the MP4 with MIME type `video/mp4` (`content_type="video/mp4"`, `contentType: "video/mp4"`, or `--content-type video/mp4`). Other content types return `422`; the option does not convert arbitrary files. Preserve the flag with the original request when retrying. A raw GIF file remains a file attachment.

Add `reply_to_message_id` to quote a message in that same group. Keep the original media ID and idempotency key when recovering a send.

## Get current media access

```text theme={null}
GET /media/{media_id}
```

Reauthorizes the request and returns fresh metadata and a temporary download URL when bytes are available. URLs can expire; retain the stable media ID instead of treating a URL as permanent storage. An inaccessible or unknown media ID returns `404`.

Download the URL without forwarding your Inkbox API key to the download host.

```python Python theme={null}
current = identity.get_whatsapp_media(media.id)
if current.status == "ready" and current.url:
    print(current.url)
```

```typescript TypeScript theme={null}
const current = await identity.getWhatsAppMedia(media.id);
if (current.status === "ready" && current.url) console.log(current.url);
```

## Media object

| Field | Type | Description |
| :- | :- | :- |
| `id` | UUID | Stable owned media ID |
| `filename` | string | Attachment filename |
| `content_type` | string | MIME type |
| `size` | integer or null | Byte count when known |
| `status` | string | `pending`, `ready`, or `unavailable` |
| `url` | string or null | Temporary authorized access; null without available bytes |

Keep filename, type, size and status even when bytes are unavailable. A pending or unavailable attachment is not an empty text message and should not silently disappear from an incoming-message workflow.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.