Swift URLSession: call Sume's image API with async/await

A Swift script that posts to /v1/images with URLSession, sets a 40-second timeout and prints the result for 200, the job envelope for 202, and errors otherwise.

4 min readSume
All posts

Swift's URLSession is the natural choice for an iOS or macOS tool that needs one generated picture.

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

Swift code

Save as gen.swift and run SUME_API_KEY=... swift gen.swift. It uses top-level await, so use a recent Swift toolchain (5.7 or newer).

import Foundation

let key = ProcessInfo.processInfo.environment["SUME_API_KEY"] ?? ""
guard !key.isEmpty else { fatalError("SUME_API_KEY missing") }
var req = URLRequest(url: URL(string: "https://api.sume.com/v1/images")!)
req.httpMethod = "POST"
req.timeoutInterval = 40
req.setValue("Bearer \(key)", forHTTPHeaderField: "Authorization")
req.setValue("application/json", forHTTPHeaderField: "Content-Type")
req.httpBody = try JSONSerialization.data(withJSONObject: [
  "model": "bytedance-seed/seedream-5-lite",
  "prompt": "matte ceramic mug on a white sweep, soft shadow",
  "aspect_ratio": "16:9",
])
let (data, resp) = try await URLSession.shared.data(for: req)
let code = (resp as? HTTPURLResponse)?.statusCode ?? 0
let text = String(decoding: data, as: UTF8.self)
switch code {
case 200: print("done:", text)
case 202: print("queued, follow status_url:", text)
default: print("error", code, text)
}

Notes

URLRequest.timeoutInterval defaults to 60 seconds; the explicit 40 seconds here is mostly documentation, set it to whatever your app can bear above the 30-second sync wait.

On a phone, do not wait on the main actor. Use mode: "async" and poll status_url, so a backgrounded app does not lose a request mid-flight.

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