H3 Max Recast request rejected: every field Sume refuses
Sume refuses H3 Max Recast bodies with aspect_ratio, generate_audio, bitrate_mode, frame or audio references, or a duration outside 5-30 s. The full list.

If a Sume H3 Max Recast request fails before it starts, the cause is almost always one of the fields or values the model row refuses: a missing or non-public video_url, zero or more than four photos, resolution other than 768p or 1080p, a duration outside 5 to 30 seconds, a prompt over 2000 characters, or any of the frame, audio, aspect and bitrate fields that belong to other models.
The refusals come from Sume's request builder before the request goes to fal. That is the point of the narrow contract: Recast keeps the source video's framing, cuts and soundtrack, so there is nothing for an aspect ratio or an audio switch to control. fal's H3 Max Recast page (read 2026-10-02) lists a video, reference images and a 768p or 1080p output; Sume's Video Router docs add the 1 to 4 photo cap and the 5 to 30 second range.
Which fields are always refused?
The table groups what the request builder in the Sume API checks. The messages quoted are the ones the code raises, so you can match them in a client log.
A pattern worth noticing: most refusals are fields that are normal on other Sume video models. If you built a client around minimax-h3-max or seedance-2.5 and swapped only the model id, that is exactly how you will hit them.
| Field or value | Rule | Message theme |
|---|---|---|
| video_url missing, not https, localhost or with credentials | One public source URL required | requires one source video URL |
| reference_image_urls empty, more than 4, or a non-public URL | 1 to 4 photos, one per new person | requires 1-4 reference image URLs |
| resolution 480p, 720p, 2K | Only 768p (default) or 1080p | resolution must be 768p or 1080p |
| duration missing, under 5 or over 30 | Inspected source length, 5 to 30 s | requires the inspected source duration |
| prompt over 2000 characters | Optional, capped | prompt must be at most 2000 characters |
| aspect_ratio, generate_audio, bitrate_mode | Not supported | does not support <field> |
| image_url, first_frame_url, end_image_url, last_frame_url | Not supported | does not support <field> |
| reference_video_urls, reference_audio_urls | Not supported | does not support <field> |
Why is generate_audio refused instead of ignored?
Because the audio is the source's. Per fal's page the model preserves the source audio, and Sume's Video generation docs say h3-max-recast accepts video references but not audio. Silently accepting generate_audio: true would suggest a new soundtrack that never arrives, so the request fails instead.
The same logic covers aspect_ratio: the output follows the source frame. If you need a different shape, change the source first, then recast.
Why does duration trip people up?
On other models duration is what you want. On Recast it is a fact about the source, 5 to 30 seconds, used to price and reserve the job and never forwarded to fal. Sume's API reference also notes a shot rule: the person swap works on sources with no shot over 15 seconds, so a single unbroken 25 second take is within the duration range but outside that shot rule.
Probe the clip before you submit. Video inspect is unbilled for probe and stills, and it returns the facts that tell you the length and whether the clip has audio.
Can you check a body before you send it?
Yes, and it is cheap. This preflight mirrors the rules above and runs as is. It does not call Sume; it only tells you which rule a body would break, so a bad body never costs a round trip.
It cannot know whether your URLs are reachable or whether a clip has a shot over 15 seconds. Those need the inspect step.
BANNED = {"aspect_ratio", "generate_audio", "bitrate_mode", "image_url",
"first_frame_url", "end_image_url", "last_frame_url",
"reference_video_urls", "reference_audio_urls"}
def recast_problems(body):
out = [f"{k} is not supported" for k in BANNED if k in body]
if not str(body.get("video_url", "")).startswith("https://"):
out.append("video_url must be public https")
photos = body.get("reference_image_urls") or []
if not 1 <= len(photos) <= 4:
out.append("1 to 4 reference_image_urls")
if body.get("resolution", "768p") not in ("768p", "1080p"):
out.append("resolution must be 768p or 1080p")
d = body.get("duration")
if not isinstance(d, (int, float)) or not 5 <= d <= 30:
out.append("duration must be 5 to 30")
if len((body.get("prompt") or "").strip()) > 2000:
out.append("prompt over 2000 characters")
return out
print(recast_problems({"video_url": "https://a.test/v.mp4", "duration": 4,
"aspect_ratio": "16:9"}))How should a client guard against these?
Build the Recast body from a small allowlist rather than copying a generic video body. Keep exactly model, video_url, reference_image_urls, duration, resolution, optional prompt, plus the communication fields (mode, Idempotency-Key). Everything else goes through a different model row.
If a refusal still appears, read the message first: each one names the field. Do not retry the same body; a refused request will be refused again. Once the body is clean, submit async and follow the jobs flow in Jobs and results. The prompt post covers the one field that is optional.
Sources
Related posts
More in Developers
- Genjutsu missing from /v1/video-router/models: when it is listed
If higgsfield-genjutsu is not in GET /v1/video-router/models, Sume hides it when its provider is not configured. How to check, and what to use instead.
- Instagram media_audio_type: MUSIC vs ORIGINAL_SOUND on Reels
Instagram added a media_audio_type field on June 1, 2026 that tells licensed MUSIC from ORIGINAL_SOUND. What it means for a Reel you build with Sume.
- Instagram Reel container status_code: wait for FINISHED, not 200
An Instagram Reel container is not publishable until status_code is FINISHED, and it EXPIRES after 24 hours. A polling loop and the 100-post daily limit.
- Clickable transcript from Sume STT word timestamps in Python
Turn a Sume speech-to-text result into HTML where each word seeks the audio player to its start time. Runnable Python, with the result envelope handled safely.
Written by Sume