Presigned URL expiry for image edit references on Sume
Sume downloads reference images from a public HTTPS URL. A presigned link that expires mid-queue gives input_media_unreachable. How to set a safe expiry.

Reference images must be reachable by Sume's servers. The docs say the URL must be public HTTPS; localhost, private networks and non-HTTPS are rejected before submission. A private bucket with a presigned URL is the usual workaround, and it adds one risk: the link can expire before the job fetches it.
When the download fails, the failed job reports input_media_unreachable with the message "Could not download an input media URL (image_url). Verify the URL is publicly reachable, then retry." It is classed as validation, retryable: false and next_action: fix_input. A retry with the same dead URL will not help.
Choosing the expiry
POST /v1/images waits up to 30 seconds and falls back to a job for slow requests. With mode: "async" or webhook mode, the job can sit in a queue. The docs do not publish when the reference is fetched, so give the link more time than your longest expected wait.
| Mode | Suggested minimum link lifetime |
|---|---|
| sync (default, 30 s wait) | 5 minutes |
| async or webhook | 1 hour |
| Batch with retries | Longer than the whole batch window |
Generating the link
With boto3, generate_presigned_url takes an ExpiresIn value in seconds:
import boto3
s3 = boto3.client("s3")
url = s3.generate_presigned_url(
"get_object",
Params={"Bucket": "my-private-bucket", "Key": "refs/product.jpg"},
ExpiresIn=3600,
)
print(url)
Verify first
A presigned URL is a long https link, which is allowed. Fetch it once with a plain HTTP client from outside your network before you send it. If the link only works from your account or VPN, Sume will not reach it. Rotate to a fresh link per attempt rather than reusing one.
How this was checked
Vendor facts come from the pages listed in the sources, read on 2026-10-05. Sume facts come from the Image API docs and the catalog code on main on the same date. Catalogs and limits change, so read the descriptors from GET /v1/images/models before you pin a number in production code.
Sources
Related posts
More in Developers
- Preview a 3-minute Short with 24 stills, one every 7.5 seconds
Video frames returns up to 24 stills per call, which spaces a 180-second Short at 7.5 seconds. Build the at[] list in Python and submit it to /v1/video-frames.
- Price a multi-shot Wan 3.0 job first: Timeline plan is unbilled
Before you pay to join Wan 3.0 shots, call POST /v1/timeline-1.0/plan: it compiles the timeline and returns segment count, billable minutes and an estimate.
- Price guard: refuse a 30-second Seedance 2.5 render over your cap
Compute the Sume price of a clip from model, resolution and seconds before you POST, and refuse over a cap. Python code, the rates, and the 1080p cent rounding.
- Product photo to a 9:16 Reel clip in Python: 6 seconds for $0.75
POST /v1/videos with one product photo as frame_images first_frame on gemini-omni-flash-1.1: 6 seconds at 720p costs $0.75. Python polls and saves the MP4.
Written by Sume