Skip to main content

imagestep

The image step for your automations — one API key, one job handle, one stable URL. Generate, edit, remove backgrounds, upscale, convert and read metadata from Python 3.10+. One runtime dependency (httpx), a sync and an async client, typed (TypedDicts generated from the API's OpenAPI document).

import os
from imagestep import ImageStep

client = ImageStep(api_key=os.environ["IMAGESTEP_API_KEY"])

asset = client.assets.upload("./product.jpg")                     # stage → PUT → finish → ready
job = client.ops.remove_bg(asset["id"], wait=True)                # or any op: upscale, resize, convert, generate…
[cutout] = client.jobs.outputs(job)
[published] = client.assets.publish(cutout["id"])
print(published["publicUrl"])                                     # https://cdn.imagestep.dev/<id>

Only want the image back? One call, nothing stored:

small = client.images.transform("resize", file="./product.jpg", parameters={"width": 1200})
open("out.jpg", "wb").write(small)

# One op does one thing. Resize AND re-encode is two steps — save them as a preset and run it in one call:
webp = client.images.transform(None, file="./product.jpg", preset="web-optimize")
# your own render template, then a PNG from it (pin a version with f"{card['id']}@1")
card = client.templates.create({"name": "price-card", "html": "<h1>{{ title }}</h1>", "width": 1200, "height": 630})
png = client.images.render(card["id"], {"title": "Hello"})

Two paths, and the line between them is not speed — it is who carries the retry. ops.* gives you a job: this service promises to finish it, which is what buys progress, cancellation, webhooks and an asset_id. images.* runs while you wait and stores nothing, because you are still holding the input, so a failure costs you one re-send. AI ops and batches are always jobs.

Install

pip install imagestep

ImageStep() with no arguments reads IMAGESTEP_API_KEY (and IMAGESTEP_BASE_URL, default https://api.imagestep.dev). AsyncImageStep has the identical surface with every method awaitable — async with AsyncImageStep() as client: await client.ops.upscale(...), and that includes images.* (await client.images.transform("resize", file=…, parameters={"width": 1200})).

construct_webhook_event raises WebhookSignatureError when the signature does not check out; the JavaScript SDK throws a plain Error there, and takes its key as an argument rather than from the environment (it also runs on edge runtimes that have no process.env).

What you get

client.ops.run(op, variants=[...]) one call, one asset per variant — the whole set of social sizes
client.ops list get run estimate remove_bg upscale restore_face colorize analyze generate edit resize convert compress crop pad grayscale rotate flip flop trim flatten adjust mask blur_region overlay caption read_metadata — the atomic-op vocabulary: run(op, **opts) submits any op as a job, estimate prices one without creating anything, and the rest are one helper per op
client.images sync_endpoints supports transform transform_result render metadata — the synchronous face: transform(op, file=… | url=… | asset_id=…, parameters={…}) → bytes, transform_result(…) → a BinaryResult with content_type / width / height as well, render(template_id, data) → PNG, metadata(file) → dict. Which ops may go this way is GET /api/v1/ops, never a list in this package
client.assets upload upload_many from_url wait_ready status download get list iterate collections iterate_collections rename_collection publish unpublish set_collection tag delete — upload() takes a path · bytes · a binary file object, dedupes by sha1 and waits for ingest; upload_many() does many at once (one stage and one finish call per 500, concurrency PUTs, one status call per tick); from_url() has the SERVICE fetch each link instead, 20 to a request
client.jobs submit estimate get items iterate_items list iterate cancel resume wait outputs — wait(job_id, on_progress=…) waits for completion (the service holds each read open — GET /jobs/{id}?wait= — so a five-second job costs one request, not a poll loop) and outputs(job) reads what it produced as list rows — one paged GET /assets?job_id=, not one read per item — or subscribe to job.completed webhooks instead of polling. The totals by status and type have no method — client.get("/api/v1/jobs/counts"); for one status, list(status=…, per_page=1) and read meta["total"]
client.presets list get create update delete delete_version import_ run — versioned lists of steps you save once and run by slug: presets.run(slug, asset_ids, wait=True) ("slug@3" pins version 3); presets.import_() (keyword clash); presets.create({"name": …, "steps": [{"op": "generate", "prompt": "{{subject.hero}} on a rooftop"}], "subjects": [{"name": "hero", "referenceAssetIds": [asset_id], "descriptor": "a matte black bottle…"}]}) — the images pin the geometry (max 4 across all subjects, sent with the preset's generate / edit step) and the descriptor pins the words, expanding into the prompt wherever you write {{subject.hero}}; get(slug) exports steps + subjects + version + versions. A preset whose steps mix a model with other steps runs as one chain job, the image in between handed on for you; jobs.estimate prices it per segment in steps A preset keeps 50 versions on record: at the ceiling update is 422 resource_limit_exceeded rather than dropping the oldest, and delete_version(slug, n) makes room — slug@n answers 404 from then on, so it is for versions nothing pins.
client.templates list iterate get versions create update delete import_ — HTML/CSS render templates; list is one page of rows without html / css, get the whole document; versioned: update saves version + 1, and id@version reads or renders one frozen version; a batch is a job: ops.run("render_template", template_id=…, items=[…])
client.models list — the model catalogue with prices; list("ai_image") (default) or list("analyze")
client.webhooks list get create update delete rotate_secret test deliveries iterate_deliveries verify construct_event — create() answers the signing secret once; verify(raw_body, header, secret) and construct_event(…) check a delivery's signature in your own handler
client.agent guidelines feedback reports iterate_reports — what this API expects of an agent, and the channel for telling us an op you needed is missing
client.usage get — credits charged, jobs created and items settled over a window, grouped by op, key or day
ImageStepError every failure the API answers: code (closed set), retryable (what to branch on — without the service's own, true for a 429 or a 5xx), param, details, retry_after, and request_id — error.requestId, else the X-Request-Id header; quote it when reporting a failure. Writes carry an Idempotency-Key per call, reused across the SDK's own retries; pass idempotency_key to make your own retry the same submission

Pagination

Every list takes page (from 0) and per_page (100 by default and at most) and answers a Page — items plus meta (total, page, perPage, hasMore, nextCursor). Out of range is clamped, not refused, and meta reports the page actually served. Pass cursor=meta["nextCursor"] instead of a page number to read the rows after it: the service counts nothing then (no total, no page), and page 1 000 costs what page 1 did.

Don't write the loop — each listing has an iterator that walks to the end, following the nextCursor each answer carries:

for asset in client.assets.iterate(collection="shoot-01"):
    print(asset["id"])

assets.iterate · assets.iterate_collections · jobs.iterate · jobs.iterate_items(id) · templates.iterate · webhooks.iterate_deliveries(id) · agent.iterate_reports, on both clients (async for on AsyncImageStep). Pass cursor= (or page=) to resume a walk.

Every signature, parameter and return shape: https://imagestep.dev/docs/sdk — one reference for both SDKs, held against these sources by a test.

Metadata

Release files for imagestep 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for imagestep 0.1.1
File Size Uploaded
imagestep-0.1.1.tar.gz 86.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for imagestep 0.1.1
File Interpreter ABI Platform
imagestep-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 158.5 kB

Release files / imagestep-0.1.1.tar.gz

Download URL imagestep-0.1.1.tar.gz
Size 86.5 kB
Tags Source
SHA-256 checksum
How to use checksums
7cc907b718abfcf2e97d42710a9b6d81b62cdf23e8f15034ae22c882d8a1c9c1
BLAKE2b-256 checksum
How to use checksums
d595630a94fa16b74fcf0640fec648b597c4f9826e150cf107157a038b2b50c4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.

Transparency log

Release files / imagestep-0.1.1-py3-none-any.whl

Download URL imagestep-0.1.1-py3-none-any.whl
Size 72.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a8052827e887b094037fb38b9d8b14bd572f9dc333769025bd1d4ddf7a63c755
BLAKE2b-256 checksum
How to use checksums
6559a70ef9efd33718a9e9585ac1e4b4db92cebc41913e697a52479f787978bb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page