Ruby Net::HTTP: POST /v1/images and handle 200 and 202

A Ruby script for Sume's Images API: send the request with Net::HTTP, print data[].url on 200, and read status_url when a slow job returns 202.

5 min readSume
All posts

In Ruby, call Sume's Images API with Net::HTTP: POST JSON to https://api.sume.com/v1/images, then branch on the status code. A 200 carries data[].url with the finished images, and a 202 carries a job envelope with status_url and result_url for polling. Set the read timeout above 30 seconds so the sync wait can finish.

The script

It reads the key from the environment, which fails fast if the variable is missing. Net::HTTP is in the standard library, so there are no gems to install.

require "net/http"
require "json"
require "uri"

key = ENV.fetch("SUME_API_KEY")
uri = URI("https://api.sume.com/v1/images")
req = Net::HTTP::Post.new(uri, "Authorization" => "Bearer #{key}", "Content-Type" => "application/json")
req.body = { model: "openai/gpt-image-2.5", prompt: "A red kettle on a wooden table", quality: "medium" }.to_json
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true, read_timeout: 45) { |h| h.request(req) }
body = JSON.parse(res.body)
case res.code.to_i
when 200 then puts body["data"].map { |i| i["url"] }
when 202 then puts "poll: #{body.dig("data", "status_url")}"
else abort "#{res.code}: #{res.body}"
end

Why the status code decides

The two successful responses have different shapes. The 200 body is the image response with created, model, data and usage. The 202 body is the standard job envelope. Parsing both as one type fails, so check res.code first, then read the fields for that case.

Polling a 202

On 202, call GET /v1/jobs/{id}/status until the job is terminal, then fetch GET /v1/jobs/{id}/result. Use the URLs in the envelope instead of building them. High resolution, high quality and large n are the likeliest to cross the 30 second wait. You can also send mode: "async" to always take the job path.

Errors to handle

Sume rejects a parameter that the model does not list with 400 unsupported_parameter, rather than ignoring it. A provider failure returns 502, and a failed generation is not billed. Print the body on any other status so you can read the error code.

Sume docs and catalog, read 2026-10-05
StatusMeaningAction
200images readydownload data[].url
202job envelopepoll status_url, then result_url
400unsupported field or valuefix the request
502provider failure, not billedretry or try another model

Next steps

Add an Idempotency-Key header when you retry the same payload after a timeout. For the timeout details, see the Images API route guide.

Related posts

More in Developers

All Developers posts

Written by Sume