Documentation

Download WhatsApp Media

Last updated on October 30, 2026

Download WhatsApp Media

Download a media file (image, video, audio, document, or sticker) that a lead sent to your WhatsApp Business number. You can identify the file by its WhatsApp media ID or by its WhatsApp media URL.

The API returns the file bytes directly. It does not return a JSON body on success.

Common use cases include saving customer documents to your own system, showing received images in your CRM, or processing voice notes.


Endpoint

text
GET  /engage/v1/wa-messages/media
POST /engage/v1/wa-messages/media
PropertyValue
MethodsGET (query string) or POST (JSON body)
Base path/engage/v1/wa-messages
Full URLhttps://client-api.e-so.in/engage/v1/wa-messages/media
AuthenticationRequired
Rate limit10 requests per second

Both methods behave the same. Use POST if you do not want the media URL to appear in request logs or proxies.


Authentication

All requests must include a business access token. You can send it in either header — if both are present, Authorization is used.

HeaderFormatExample
AuthorizationBearer <token>Authorization: Bearer abc123...
auth-key<token>auth-key: abc123...

- Tokens are issued per business and are scoped to that business. You can only download media that your business's WhatsApp number received. - If the token is missing, invalid, or expired the API returns 401 Unauthorized. - Keep your token secret. Do not expose it in client-side code or public repositories.


Parameters

Send one of id or url. If you send both, url is used.

ParameterTypeRequiredDescription
idstringYes, if no urlWhatsApp media ID (numeric string, e.g. "1234567890123456"), as received in the message payload.
urlstringYes, if no idWhatsApp media URL. Must start with https://lookaside.fbsbx.com/. Other hosts are rejected.

- For GET, send the parameter in the query string. URL-encode the url value. - For POST, send the parameter in a JSON body with Content-Type: application/json.

Which one to use

- id — Recommended. A media ID stays valid for about 30 days after the message is received. The API gets a fresh download URL for you. - url — A WhatsApp media URL expires about 5 minutes after it is issued. Use it only if you download the file immediately.


Request Examples

http
GET /engage/v1/wa-messages/media?id=1234567890123456 HTTP/1.1
Host: client-api.e-so.in
Authorization: Bearer YOUR_TOKEN
http
POST /engage/v1/wa-messages/media HTTP/1.1
Host: client-api.e-so.in
Authorization: Bearer YOUR_TOKEN
Content-Type: application/json

{ "id": "1234567890123456" }

Responses

Success — 200 OK

The body is the raw file. Use the response headers to save it correctly.

HeaderDescription
Content-TypeMIME type of the file (e.g. image/jpeg, application/pdf, audio/ogg). application/octet-stream if unknown.
Content-LengthFile size in bytes, when known.
Content-Dispositionattachment, and the file name when WhatsApp provides one.

Error Responses

Errors return a JSON body in this shape:

json
{
  "status": 404,
  "success": false,
  "message": "Media not found."
}
HTTP StatusmessageWhen it happensWhat to do
400WhatsApp Business Platform details are not configured for this account.Your business has no connected WhatsApp Business number.Connect WhatsApp in EasySocial, or contact your account manager.
400–404_Message from WhatsApp_ (e.g. Unsupported get request...)The media ID is wrong, belongs to a different WhatsApp number, or has expired.Check the ID. Media older than about 30 days cannot be downloaded.
401Unauthorized Access Token: The provided token is missing, invalid, or expired.Token not sent, has a typo, or has expired.Verify the header name and token value.
401/404_Message from WhatsApp_The url has expired (older than about 5 minutes).Download by id instead.
404Media not found.WhatsApp returned no download URL for the media ID.Check the ID and try again.
422VALIDATION_FAILURENeither id nor url was sent, id is not numeric, or url is not a WhatsApp media URL.Fix the parameter. See the messages.errors array for details.
429Rate limit exceeded. Please try again later.More than 10 requests per second.Retry with backoff.
500_Server error_Unexpected server error.Retry with exponential backoff. If it persists, contact support.

Validation error example:

json
{
  "status": 422,
  "success": false,
  "message": "VALIDATION_FAILURE",
  "messages": {
    "errors": [{ "rule": "requiredIfNotExists", "field": "id", "message": "Either id or url is required." }]
  }
}

> Always check the HTTP status before you save the body. On an error, the body is JSON, not the file.


Code Examples

> Replace YOUR_TOKEN with your business access token.

cURL

bash
# GET by media ID — saves to file using the server-provided name
curl -G "https://client-api.e-so.in/engage/v1/wa-messages/media" \
  --data-urlencode "id=1234567890123456" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -o media.bin

# POST by media URL
curl -X POST "https://client-api.e-so.in/engage/v1/wa-messages/media" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=..."}' \
  -o media.bin

JavaScript — fetch (Node.js)

javascript
import { writeFile } from "node:fs/promises";

const response = await fetch("https://client-api.e-so.in/engage/v1/wa-messages/media", {
  method: "POST",
  headers: { Authorization: "Bearer YOUR_TOKEN", "Content-Type": "application/json" },
  body: JSON.stringify({ id: "1234567890123456" }),
});

if (!response.ok) {
  const body = await response.json();
  throw new Error(`Error ${body.status}: ${body.message}`);
}

const contentType = response.headers.get("content-type");
await writeFile("media.bin", Buffer.from(await response.arrayBuffer()));
console.log(`Saved ${contentType}`);

Python — requests

python
import requests

resp = requests.post(
    "https://client-api.e-so.in/engage/v1/wa-messages/media",
    headers={"Authorization": "Bearer YOUR_TOKEN"},
    json={"id": "1234567890123456"},
    stream=True,
)

if resp.ok:
    with open("media.bin", "wb") as f:
        for chunk in resp.iter_content(chunk_size=65536):
            f.write(chunk)
    print("Saved", resp.headers.get("Content-Type"))
else:
    body = resp.json()
    print(f"Error {body['status']}: {body['message']}")

MethodPathPurpose
POST/engage/v1/wa-messages/sendSend a WhatsApp text or media message to a lead.

Support

If you have a problem with this endpoint, include this in your support request:

- The method and full request URL - The media id (do not send the access token) - The status and message from the error response - The time of the request (UTC)