Java HttpClient: POST /v1/images on Sume with a 40-second timeout
A single-file Java program that calls Sume's image API with java.net.http, branches on 200, 202 and errors, and sets a timeout longer than the 30-second wait.

Java's built-in HTTP client is a good fit for a one-off image call: no dependencies, one file.
The request is the same in every language: POST https://api.sume.com/v1/images with a bearer key from SUME_API_KEY, a JSON body with model, prompt and aspect_ratio, and a client timeout above the route's 30-second wait. The route defaults to mode: "sync", so the status code decides what you do next (docs read 2026-10-07):
Status codes to branch on
| Status | Meaning | What the code below does |
|---|---|---|
| 200 | Image finished inside the wait; data[].url holds the file | Prints the result |
| 202 | Wait expired (or mode is async or webhook); body is a job envelope with status_url and result_url | Prints the envelope; poll status_url and read result_url |
| 502 | The job failed inside the wait; error has code, retryable, next_action | Prints the error |
| 400, 404 | unsupported_parameter, or model_not_found | Prints the error |
Java code
Save as Gen.java, then run SUME_API_KEY=... java Gen.java on JDK 17 or newer (the arrow switch needs 14+, single-file launch needs 11+).
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
public class Gen {
public static void main(String[] args) throws Exception {
String key = System.getenv("SUME_API_KEY");
if (key == null || key.isEmpty()) throw new IllegalStateException("SUME_API_KEY missing");
String body = "{\"model\":\"bytedance-seed/seedream-5-lite\","
+ "\"prompt\":\"matte ceramic mug on a white sweep, soft shadow\","
+ "\"aspect_ratio\":\"16:9\"}";
HttpRequest req = HttpRequest.newBuilder(URI.create("https://api.sume.com/v1/images"))
.timeout(Duration.ofSeconds(40))
.header("Authorization", "Bearer " + key)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
HttpResponse<String> r = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
switch (r.statusCode()) {
case 200 -> System.out.println("done: " + r.body());
case 202 -> System.out.println("queued, follow status_url: " + r.body());
default -> System.out.println("error " + r.statusCode() + ": " + r.body());
}
}
}Notes
HttpClient has no request timeout unless you set one on the HttpRequest. Forty seconds leaves room above Sume's 30-second sync wait, so you see the 202 instead of your own timeout.
The body is built by string concatenation to stay dependency-free. For anything dynamic, build it with a JSON library so quotes in the prompt are escaped.
One bytedance-seed/seedream-5-lite image is $0.04375 billed (list $0.035 x 1.25). Prices here are Sume's list-times-1.25 figures. The catalog states the billable formula as "list × 1.25 → ceil usd cents", so treat the dollar amounts as the pre-rounding value and read the exact charge from billable_amount_usd_micros in the submit envelope. Failed or cancelled generations are not billed.
Sources: Sume Image API docs and Jobs and results (read 2026-10-07).
Sources
Related posts
More in Developers
- Date.now() is milliseconds: the Sume webhook timestamp is seconds
A Node webhook verifier that compares Date.now() to x-sume-webhook-timestamp rejects every delivery. The one-line fix and a four-case test around 300 s.
- A job id is not a run id: poll image and video generation via /v1/jobs
Image and video generate routes create jobs, not runs. Poll GET /v1/jobs/:id/status until terminal is true. waitForRun is for run ids only.
- Job id or run id? Which Sume endpoint to poll for each product
Jobs, Format runs, Actions and Agent Completions have different ids, poll URLs and webhook events. Which to poll for each product, and which SDK helper to call.
- terminal, result_ready or status: which check ends a Sume poll loop?
Stop on terminal, fetch on result_ready, branch on status. Three fields in the Sume status payload, three different jobs, and a Python loop that uses each once.
Written by Sume