Avatar photo 400 unsupported_image_type: PNG, JPEG, WebP, GIF only
Sume's avatar photo preflight accepts four image content types. An HTML page, AVIF or HEIC answer returns 400 unsupported_image_type and no job is created.
If creating a photo avatar on Sume returns 400 unsupported_image_type, the URL you sent as input.image_url answered with a Content-Type that is not image/png, image/jpeg, image/webp or image/gif. Sume checks the header of the response, not the file extension. A login page, an expired signed link that now returns text/html, or an iPhone HEIC file served as image/heic all fail the same way.
The check is a preflight. Sume fetches the photo before it creates the avatar job, so a rejected photo leaves no job behind. The error carries details.content_type with what the server actually sent, details.url_host with only the host, and details.suggested_input set to clear_front_facing_image. The rest of the contract is on Create new avatar and Media inputs (both read 2026-10-05).
What the preflight compares
The preflight sends a GET with Accept: image/png,image/jpeg,image/webp,image/gif. Then it normalizes the response Content-Type and compares it with the list. Parameters such as ; charset=binary are stripped before the comparison.
| Response Content-Type | Result | Why |
|---|---|---|
| image/png | Continues to the size checks | On the accepted list |
| image/jpeg or image/jpg | Continues to the size checks | On the accepted list |
| image/webp | Continues to the size checks | On the accepted list |
| image/gif | Continues to the size checks | On the accepted list |
| text/html | 400 unsupported_image_type | Not an image; often a page or an error body |
| image/avif, image/heic, image/tiff, image/svg+xml | 400 unsupported_image_type | Image types, but not on the list of four |
| Missing header | 400 unsupported_image_type, content_type null | Nothing to match |
Check the header first
Run the same request your client will make and read the header before you submit anything paid.
curl -sS -L -o /dev/null -w '%{http_code} %{content_type}\n' \
-H 'Accept: image/png,image/jpeg,image/webp,image/gif' \
'https://assets.example.com/headshot.jpg'
# want: 200 image/jpeg (or png, webp, gif)
# 200 text/html means the link is a page, not the fileHow to fix it
Fix the source, not the request. Export the picture as JPEG or PNG and host that file. If the host guesses types from the extension, make sure the file name matches the bytes. If your photos live behind a signed link, generate the link right before you call Sume, because an expired link usually answers with an HTML or JSON error page.
A photo that passes the type check can still fail on its pixels. That is a different code, invalid_image, and it is covered in the 64-pixel and aspect-ratio post.
Why a rejected photo costs nothing
A job-based API that creates a billable avatar has a reason to fail early. Avatar creation is a fixed-price step of $0.95 per avatar in Sume's pricing package, and the usage reservation is made after the photo preflight in the creation handler. So an unsupported_image_type response is free: no job exists, and no reservation was made for it. That ordering is visible in the source and is why the error is safe to retry in a loop while you fix a hosting problem.
Keep one thing in mind when you build a retry loop. A 400 from the preflight will not change by waiting. Only the host's answer changes, so retrying without changing the URL or the file at that URL just repeats the same rejection.
Where to put the check in your own flow
Put a small guard in front of your own upload flow. Fetch the URL with a HEAD or GET once, read the content type, and only then call Sume. Teams that accept photos from users can run the same check at upload time and show the person a clear message instead of a raw API error.
If your pipeline converts files, convert to JPEG or PNG at the end of the pipeline, not in the middle. Re-encoding a WebP to AVIF for size, then sending the AVIF, is the most common way to land in this error by accident.
What the error tells you, and what it hides
The error body never repeats a query string. A test in the API suite sends photo.txt?token=private and asserts that the token is absent from the response, so you can paste the error into a ticket without leaking a signed link. The shared error envelope, including request_id, is on Errors and rate limits.
Sume's canonical create route is POST /v1/avatar-1.0/generate with input: {"type": "photo", "image_url": ...}. Internally the URL is validated as file.url, which is why details.field reads file.url even when you sent input.image_url.
Sources
Related posts
More in Developers
- Avatar photo 413 image_too_large: 16,384 px and 100 MP limits
A Sume avatar photo over 16,384 px on a side, or over 100,000,000 pixels, returns 413 image_too_large before any job exists. Downscale it first.
- Avatar photo image_not_fetchable: 404, timeouts and the 15 s limit
Sume gives an avatar photo host 15 seconds for fetch and body read. A non-2xx status or a timeout returns 400 image_not_fetchable. How to fix it.
- Handle avatar photo errors in Python: read details.suggested_input
A stdlib Python handler for Sume avatar photo errors: branch on error code, print the suggested input, and never echo a private URL. Refuses an empty API key.
- Avatar photo URL redirects: five hops, then image_not_fetchable
Sume follows up to five redirects for an avatar photo and re-checks every hop. A redirect to http or a private address returns 400 image_not_fetchable.
Written by Sume