Node https.request: POST /v1/images on Sume, no fetch, no packages

Call Sume's image API from Node using only node:https: JSON body, bearer key, 40-second timeout that actually aborts, and 200 versus 202 handling.

4 min readSume
All posts

Use node:https on runtimes or old code bases where fetch is not available.

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

Sume POST /v1/images, read 2026-10-07.
StatusMeaningWhat the code below does
200Image finished inside the wait; data[].url holds the filePrints the result
202Wait expired (or mode is async or webhook); body is a job envelope with status_url and result_urlPrints the envelope; poll status_url and read result_url
502The job failed inside the wait; error has code, retryable, next_actionPrints the error
400, 404unsupported_parameter, or model_not_foundPrints the error

Node.js code

Save as nh.mjs and run SUME_API_KEY=... node nh.mjs. It uses only the built-in node:https module.

import https from "node:https";

const key = process.env.SUME_API_KEY ?? "";
const body = JSON.stringify({
  model: "bytedance-seed/seedream-5-lite",
  prompt: "matte ceramic mug on a white sweep, soft shadow",
  aspect_ratio: "16:9",
});
const req = https.request(
  "https://api.sume.com/v1/images",
  {
    method: "POST",
    timeout: 40000,
    headers: {
      Authorization: `Bearer ${key}`,
      "Content-Type": "application/json",
    },
  },
  (res) => {
    let text = "";
    res.on("data", (c) => (text += c));
    res.on("end", () => {
      if (res.statusCode === 200) console.log("done:", JSON.parse(text).data[0].url);
      else if (res.statusCode === 202) console.log("queued, follow status_url:", text);
      else console.log("error", res.statusCode, text);
    });
  },
);
req.on("timeout", () => req.destroy(new Error("client timeout")));
req.end(body);

Notes

A timeout option on https.request only emits an event. It does not abort the request, so the handler calls req.destroy().

Branch on res.statusCode. A 202 carries a job envelope; read the finished image from its result_url once the job completes.

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

All Developers posts

Written by Sume