Skip to main content
Media is uploaded before it is sent. The resulting id can be reused across messages until Meta’s copy expires. Unlike social APIs that give you a presigned URL and leave you talking to object storage, LazyApp uploads into WhatsApp Cloud API for you. You never hold a Meta access token or proxy bytes to Graph.

Upload flow

1

Upload the file

Multipart to POST /v1/media, or JSON to POST /v1/media/url when the file already has a public URL.
2

Keep the media id

The response includes LazyApp’s uuid and Meta’s provider_media_id. Either works as media_id when sending.
3

Send with it

Pass media_id on POST /v1/messages for image, video, audio, document, or sticker.
The URL form is usually what you want: LazyApp fetches the file and uploads it to Meta, so you do not proxy bytes through your own servers. Every upload is virus-scanned and MIME-checked. Images are optimised and a thumbnail is generated when enabled. Identical bytes in the same workspace and mode reuse the existing asset when Meta’s copy is still valid — a retry of the same file cannot create a duplicate row.

Supported formats

Default limit is 16 MB per file (MEDIA_MAX_SIZE_KB). Meta may still refuse a type or size that WhatsApp does not accept for that message kind even when LazyApp accepted the upload.

Meta expires media after about 30 days

This catches people out. Meta’s copy of an uploaded file is temporary — roughly 30 days — so a media_id you stored last quarter will not send today. provider_expires_at tells you when Meta’s copy goes. retention decides whether LazyApp keeps its own: For anything you will resend — a catalogue, a logo, a standard form — use managed. See Media & limits for MIME allow-list, Meta error codes, and messaging caps.

Sending it

You can also pass media_url on some sends so LazyApp imports and uploads in one step — prefer an explicit upload when you will reuse the same file.

Access history

Every read, upload and delete is recorded with who did it, when, and from which IP:
The history outlives the asset, so deleting media does not erase the record of who deleted it — which is the entry you most want when someone asks.

Inbound media

When a contact sends you a file, the message.received webhook carries a media id. LazyApp downloads and retains it according to your retention policy, so you are not racing Meta’s expiry to fetch it. Download the bytes with GET /v1/messages/{message}/media, where {message} is the message uuid from the webhook. The response is the raw file. If the download is still queued, you get 409 — retry after a short pause rather than treating it as missing.