media_upload_failed names the real cause, WebP uploads are rejected early, and the failed-sends error tables are corrected
Released: August 4, 2026
media_upload_failed explains what actually went wrong Changed
Section titled “media_upload_failed explains what actually went wrong ”Sending media by URL failed with this:
{ "status": "failed", "error": { "code": "media_upload_failed", "message": "WhatsApp could not retrieve or process the media URL.", "provider_code": 131053 }}“Could not retrieve” reads as a connectivity problem, so the natural next step was to check whether the URL was reachable. It almost always was. Meta’s own media reference documents 131053 as a mismatched MIME type, and that is what it usually is.
The message now says so:
{ "status": "failed", "error": { "code": "media_upload_failed", "message": "WhatsApp could not fetch or process the media. Check that the URL is publicly reachable and returns a supported Content-Type: images must be image/jpeg or image/png (WebP is accepted for stickers only). CDNs that auto-negotiate format can silently return WebP and trigger this error.", "provider_code": 131053 }}The code and the HTTP status are unchanged. Only the message text moved,
so nothing that branches on error.code is affected.
The trap worth knowing about
Section titled “The trap worth knowing about”WhatsApp accepts image/jpeg and image/png for image messages. WebP
is valid for stickers only.
That matters more than it sounds, because a URL can serve a different
format to WhatsApp than it serves to you. Image CDNs built on imgix and
similar services perform content negotiation: an auto=format parameter
makes them return WebP to any client that advertises support for it. The
URL opens correctly in your browser, returns 200, and still fails here.
If you pass third-party image URLs through image.link, pin the format
explicitly rather than relying on the CDN default.
Five error codes in the failed-sends guide never existed Fixed
Section titled “Five error codes in the failed-sends guide never existed ”The Handling failed sends guide documented five
error.code values that no Kirimdev endpoint has ever returned. They
appeared in the code tables and in the copy-pasteable TypeScript and
Python handlers, so anyone who followed the guide wrote switch branches
that could never match — and the failure was silent, because an
unmatched code simply fell through to the default arm.
| Documented (wrong) | Actually returned |
|---|---|
template_not_approved | template_not_found |
template_params_mismatch | template_param_mismatch |
media_invalid | media_upload_failed |
provider_error | upstream_error |
degraded | account_in_maintenance |
degraded was the subtlest of the five: it is a real value, but it is an
account status, not an error code. It never appears in
error.code.
Two further corrections in the same guide:
quota_exceededwas listed as an async send-failure code. It isn’t one — it is a synchronous402returned when your Kirimdev plan quota is exhausted, and it never appears as theerror.codeof a failed message. It has been removed from the async tables and handlers. (When a plan’s monthly message allowance runs out, the failed message carriesinvalid_requestwith a quota message, and that allowance resets at the start of the next calendar month.)template_param_format_mismatchwas missing entirely. A wrong parameter count and a wrong parameter value format are separate codes with separate fixes, and only the first was documented.
The synchronous HTTP error table was wrong too. Four of its rows named codes and even statuses the API does not use:
| Documented (wrong) | Actually returned |
|---|---|
400 invalid_request | 400 invalid_field_value |
403 phone_number_forbidden | 404 resource_not_found |
409 idempotency_conflict | 422 idempotency_key_reuse |
422 account_not_connected | 422 whatsapp_number_not_verified |
The 403 → 404 correction matters for a subtle reason: an id belonging
to another organization returns 404, identical to an id that does not
exist, so a caller cannot probe for other tenants’ phone-number ids. A
documented 403 would have advertised the opposite.
If you built error handling from this guide, check your branches against the corrected tables. No API behavior changed — only the documentation was wrong.
WebP image uploads are now rejected before they fail at Meta Fixed
Section titled “WebP image uploads are now rejected before they fail at Meta ”WhatsApp accepts WebP for sticker messages only. An image message
with a WebP body is rejected by Meta with the same 131053 above.
Our upload validation nonetheless accepted image/webp for images, in
the composer, the media library, and the connector mapping editors.
Because nothing in the pipeline transcodes WebP to PNG, the file was
sent to Meta unchanged and failed there — a silent 131053 well after
the upload appeared to succeed.
WebP is now rejected at upload time for image messages, with an immediate, actionable error instead of a delayed send failure. JPEG and PNG are unaffected. (Broadcast/template image headers already rejected WebP; this brings the chat and media-library paths in line.)
Handling failed sends Error envelope reference