How this works: The node automatically calls the metadata endpoint to retrieve the temporary download URL, then immediately fetches the binary content in a single operation. You do not need to call media/get first.
When to Use
- Inbound document archival: A customer sends a signed contract as a PDF on WhatsApp. A webhook workflow downloads the file via this node and saves it to a document management system or S3-compatible store for long-term retention.
- Image processing pipeline: A KYC onboarding workflow downloads the ID document image sent by the user and passes the base64 content to an OCR node for identity extraction.
- Voice message transcription: A support workflow downloads an incoming audio message (OGG format) and routes it to a speech-to-text service to create a searchable transcript.
- Forwarding media between channels: A multi-channel workflow downloads a media file received on WhatsApp and re-sends it as an email attachment or uploads it to a Slack channel.
- Compliance archival: A regulated industry workflow downloads all inbound media within 30 seconds of receipt and stores it in an immutable archive before Meta's 30-day deletion window begins.
Configuration
Connection
| Field | Required | Description |
accessToken | Required | Permanent System User access token from Meta Business Manager. Store in BizFirst Credentials Manager. |
phoneNumberId | Required | Numeric string ID of the WhatsApp Business phone number associated with the media. |
apiVersion | Optional | Meta Graph API version, e.g. v18.0. Defaults to v18.0. |
Operation
| Field | Required | Description |
mediaId | Required | The ID of the media object to download. Sourced from a webhook trigger payload or from a previous media/upload or media/get node. |
Memory considerations: The node streams the binary into memory. For very large files (video up to 16 MB, documents up to 100 MB), ensure the workflow execution environment has sufficient available memory. The node enforces a safe download limit of twice the configured max upload size.
Sample Configuration
{
"resource": "media",
"operation": "download",
"accessToken": "{{ $credentials.whatsAppToken }}",
"phoneNumberId": "123456789012345",
"mediaId": "{{ $trigger.message.document.id }}"
}
Validation Errors
| Error | Cause |
accessToken is required | The accessToken field is empty or missing. |
phoneNumberId is required | The phoneNumberId field is empty or missing. |
mediaId is required | The mediaId field is empty or missing. |
file_too_large | The media file exceeds the configured safe download limit (2x the max upload size). |
100 (Meta) | Media ID does not exist or belongs to a different phone number account. |
190 (Meta) | Access token expired or invalid. |
timeout | The download request timed out. Retry once; if persistent, check network connectivity. |
Output
Success Port
Fires when the binary content has been fully downloaded. The data field contains the file as a base64 string, ready to be saved to storage or passed to a processing node.
| Field | Type | Description |
data | string | Base64-encoded binary content of the downloaded file. |
mimeType | string | MIME type of the downloaded file as reported by the response headers (e.g. image/jpeg). |
fileSize | number | Actual byte count of the downloaded content. |
mediaUrl | string | The temporary signed URL that was used to fetch the content. |
status | string | "downloaded" on success. |
errorCode | string | Empty on success. |
errorMessage | string | Empty on success. |
Error Port
Fires when the metadata fetch or the binary download fails.
| Field | Type | Description |
status | string | "failed", "error", or "timeout". |
errorCode | string | Meta error code or BizFirst internal code. |
errorMessage | string | Human-readable description of the failure. |
rawResponse | string | Raw API error JSON for diagnostics. |
Sample Output
{
"data": "JVBERi0xLjQKJcOkw7zDtsOfCjIgMCBvYmoK...",
"mimeType": "application/pdf",
"fileSize": 143360,
"mediaUrl": "https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=1234...",
"status": "downloaded",
"errorCode": null,
"errorMessage": null
}
Expression Reference
| Value | Expression | Notes |
| File content (base64) | {{ $output.downloadMedia.data }} | Pass directly to a storage node, an HTTP upload node, or decode in a Function node. |
| MIME type | {{ $output.downloadMedia.mimeType }} | Use to set the correct Content-Type header when forwarding the file. |
| File size (bytes) | {{ $output.downloadMedia.fileSize }} | Log alongside the media ID for audit records. |
| Status | {{ $output.downloadMedia.status }} | "downloaded" on success. |
| Error code | {{ $output.downloadMedia.errorCode }} | Non-null on error port. Check for "file_too_large" to handle size overruns. |
Node Policies & GuardRails
| Policy Area | Recommendation |
| Archival timing | WhatsApp media objects are deleted from Meta's servers 30 days after they are created. For compliance use cases, trigger downloads within hours of receipt, not days. |
| Memory management | For high-volume workflows handling large video or document files, add a size gate using media/get before calling this node to prevent memory exhaustion. |
| Credential storage | Store the access token in BizFirst Credentials Manager. Never expose it in plain text in node configuration. |
| Data residency | Downloaded media content passes through the BizFirstAI workflow engine. Ensure your data residency policies allow this before processing sensitive documents. |
| Error port handling | Always connect the error port. A file_too_large error needs an alternative handling path such as notifying the sender that the file cannot be processed. |
| Do not store base64 in logs | The data field is a full base64 binary. Do not log it — route it directly to a storage node and discard after persistence is confirmed. |
Examples
Download and Archive an Inbound Document
{
"resource": "media",
"operation": "download",
"accessToken": "{{ $credentials.whatsAppToken }}",
"phoneNumberId": "123456789012345",
"mediaId": "{{ $trigger.message.document.id }}"
}
A webhook workflow fires when a customer sends a document. This node downloads the binary. A subsequent S3-Upload node saves the base64 content to cloud storage using the customer's phone number and a timestamp as the key. A confirmation text message is sent back to the customer with a reference number.
Download Voice Message for Transcription
{
"resource": "media",
"operation": "download",
"accessToken": "{{ $credentials.whatsAppToken }}",
"phoneNumberId": "123456789012345",
"mediaId": "{{ $trigger.message.audio.id }}"
}
A support workflow detects an inbound audio message via webhook. This node downloads the OGG-encoded audio. The base64 content is decoded in a Function node, then posted to a speech-to-text API. The resulting transcript is attached to the support ticket and used to auto-classify the issue category.
Multi-Channel Media Forwarding
{
"resource": "media",
"operation": "download",
"accessToken": "{{ $credentials.whatsAppToken }}",
"phoneNumberId": "123456789012345",
"mediaId": "{{ $input.mediaId }}"
}
A media relay workflow downloads an image received on WhatsApp and forwards it as an email attachment. The data (base64) and mimeType fields are passed to an Email node configured to send the file as an attachment to the assigned case manager's inbox.