whatsapp scope. Meta credentials and temporary download URLs stay on the server.
Upload
POST /whatsapp/media requires the same sending permission and active Starter, Creator or Pro platform plan as messages. Submit exactly one file and the 60db number UUID as multipart form data:
201 response has success: true and data containing provider_id, type, mime_type, filename, file_size and expires_at. Use provider_id in the matching message content object. Uploaded IDs expire after 30 days. Uploading does not send a message or open the 24-hour reply window.
Set the file’s MIME type accurately. The API checks its size and content; Meta may reject files that do not meet its additional media requirements. Audio voice notes require mono Ogg/Opus. Sticker upload/sending is not exposed.
Download
GET /whatsapp/numbers/{number_uuid}/media/{provider_id} requires read permission for the connected number. Media must already be recorded by an upload or a verified inbound message for that number and workspace. Inbound IDs expire after seven days.
Cache-Control: private, no-store. It is not a JSON envelope. The server obtains a fresh provider URL for each request and verifies size and SHA-256 before returning the file. API keys stay in request headers; do not put them in image or audio URLs.
A provider HTTP 401/403 during the binary download triggers the shared access probe. A confirmed invalid token stops the captured connection and returns META_TOKEN_REVOKED. A valid, matching-app probe with a verified missing management or messaging grant stops it with META_PERMISSIONS_MISSING. Granted permissions, indeterminate/malformed responses and failed probes preserve the connection and return the sanitized download failure. Download URLs, provider response bodies and authorization headers are not exposed. An old download failure cannot disable a replacement token.
In the dashboard, select an attachment to load its preview, play audio/video with native controls, or save it. Reply attachments retain the same send idempotency key after an interrupted 60db API response.