This operation is permanent. Deleting a media object removes it from Meta's servers immediately. Any message that currently displays that media will show a broken attachment to the recipient. Always archive the content with media/download before deleting.
When to Use
- GDPR right-to-erasure: A data subject requests deletion of all data associated with their account. After downloading and archiving the relevant media locally, a workflow calls this node to remove each media object from Meta's infrastructure.
- Post-campaign cleanup: A marketing workflow uploads promotional images for a seasonal campaign. Once the campaign ends, an automated cleanup workflow iterates over stored media IDs and deletes them to free capacity and remove outdated assets.
- Sensitive document disposal: A financial services workflow processes inbound identity documents. After successful archival and processing, it deletes the originals from WhatsApp's servers to reduce the attack surface.
- Storage quota management: An operations workflow monitors media storage utilisation and deletes media objects older than 7 days that have already been archived, ensuring the 30-day limit is not reached passively.
- Failed upload cleanup: A workflow that uploaded media as part of a transaction that subsequently failed calls this node to delete the orphaned media object and prevent resource leakage.
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 that owns the media object. |
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 delete. Must have been uploaded by or received on the same phone number account. Deletion of another account's media returns a 100 error. |
Sample Configuration
{
"resource": "media",
"operation": "delete",
"accessToken": "{{ $credentials.whatsAppToken }}",
"phoneNumberId": "123456789012345",
"mediaId": "{{ $input.mediaIdToDelete }}"
}
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. |
100 (Meta) | Media ID not found or the calling account does not have permission to delete it. |
190 (Meta) | Access token expired or invalid. |
parse_error | Meta returned a non-JSON response. Treat as transient and retry once. |
Output
Success Port
Fires when Meta confirms the media has been deleted. The status field will be "deleted".
| Field | Type | Description |
status | string | "deleted" on success. |
errorCode | string | Empty on success. |
errorMessage | string | Empty on success. |
rawResponse | string | Full raw JSON response from Meta, typically {"success":true}. |
Error Port
Fires when the deletion fails. Inspect the errorCode to distinguish between a not-found error (100) and an authentication error (190).
| Field | Type | Description |
status | string | "failed" or "error". |
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
{
"status": "deleted",
"errorCode": null,
"errorMessage": null,
"rawResponse": "{\"success\":true}"
}
Expression Reference
| Value | Expression | Notes |
| Status | {{ $output.deleteMedia.status }} | "deleted" on success. Use in an IfCondition to confirm before updating a database record. |
| Error code | {{ $output.deleteMedia.errorCode }} | Non-null on error port. Code 100 means already deleted or never existed. |
| Error message | {{ $output.deleteMedia.errorMessage }} | Human-readable reason for failure. Log for audit trail. |
| Raw response | {{ $output.deleteMedia.rawResponse }} | Full JSON confirmation string from Meta. |
Node Policies & GuardRails
| Policy Area | Recommendation |
| Archive before delete | Always call media/download and confirm archival success before calling this node. A deletion cannot be undone. |
| Idempotency | Attempting to delete an already-deleted media ID returns error 100. In cleanup workflows, treat 100 as a success condition (already deleted) to prevent false alarms. |
| Credential storage | Store the access token in BizFirst Credentials Manager. Never expose it in node configuration as plain text. |
| Audit logging | Record the mediaId, timestamp, and the identity of the triggering user or process in an immutable audit log before and after deletion. This is essential for GDPR compliance. |
| Batch operations | For bulk deletion (e.g. post-campaign cleanup), use a Loop node to iterate over a list of media IDs, with a Delay node between calls to respect Meta API rate limits. |
| Error port handling | Always connect the error port. Failure to delete should be logged and escalated — silently ignoring delete failures can result in data residency policy violations. |
Examples
GDPR Erasure Workflow
{
"resource": "media",
"operation": "delete",
"accessToken": "{{ $credentials.whatsAppToken }}",
"phoneNumberId": "123456789012345",
"mediaId": "{{ $loop.currentItem.mediaId }}"
}
A data erasure workflow retrieves all media IDs associated with a departing customer from a database, loops through them, archives each one (via media/download), and then calls this node. On success, the workflow marks each record as deleted in the audit log. On error with code 100, it marks the record as already-deleted and continues.
Post-Campaign Cleanup
{
"resource": "media",
"operation": "delete",
"accessToken": "{{ $credentials.whatsAppToken }}",
"phoneNumberId": "123456789012345",
"mediaId": "{{ $loop.currentItem.campaignMediaId }}"
}
A scheduled workflow fires the day after a marketing campaign ends. It queries the campaign_assets table for all media IDs associated with the completed campaign and loops through them, calling this node for each. Successful deletions are logged; failures are collected into an error list and emailed to the campaign manager.
Transactional Rollback
{
"resource": "media",
"operation": "delete",
"accessToken": "{{ $credentials.whatsAppToken }}",
"phoneNumberId": "123456789012345",
"mediaId": "{{ $input.orphanedMediaId }}"
}
A payment workflow uploads a receipt image, then attempts to send it. If the send fails for a business reason (e.g. payment reversal), the workflow branches to this node to delete the orphaned upload, preventing it from taking up media storage quota and eliminating any risk of the receipt being associated with the wrong transaction.