For n8n workflows, MCP agents and plain REST
The image step
for your automations.
Remove a background, put it on white, compress it to size, render a template — one node in your workflow, one tool for your agent. No server to run, no sharp to compile, no five provider keys to hold.
Free plan: 200 assets · 200 deterministic ops a month, then $0.002 each · $3 welcome credit for AI ops. No card.

remove_bg$0.0227 / image
trimfree
flattenfree
compress7.3 KB out
Four things your workflow can't do on its own
Run it
A hosted workflow or an agent runtime has no libvips, no Chromium, no GPU and no memory for a RAW. ImageStep runs the step; your flow keeps the result.
Keep it
A call is one-shot; a pipeline is not. Assets keep a stable id and a URL that outlives the run, a job carries state and a signed webhook, and a retry with the same idempotency key is safe.
Pay for it once
One key, one bill. Every AI op is priced per image in USD, and a dry run returns the exact number before anything is spent.
Keep it consistent
A preset is your chain, versioned, with reference subjects locked in — so batch four hundred looks like batch one.
One catalogue, two kinds of op
An op does one thing, takes a closed set of parameters and an asset id, and is priced per image. AI ops and deterministic ops chain in one preset, run in one job and settle on one bill.
AI ops
USD per image · model you can override- generate
- edit
- remove_bg
- upscale
- restore_face
- colorize
- analyze
Deterministic ops
free on paid plans- resize
- convert
- compress
- crop
- pad
- trim
- flatten
- adjust
- caption
- overlay
- blur_region
HTML and a row of data in, one PNG per row out — an OG image per post, a card per product.
EXIF, GPS, dimensions, hash and type, read on every asset at ingest. Free, on every plan.
- In
- JPEG, PNG, WebP, AVIF, HEIC, RAW from most cameras, PSD, JPEG XL
- Out
- WebP, JPEG, PNG, AVIF, GIF, TIFF
Every parameter and today's price, no credential needed: GET /api/v1/ops
How a call goes
- 1Get the image in
Upload it, or hand over a URL and the service fetches it. You get an asset id.
- 2Price it
The same request with ?dryRun=true validates everything and returns the exact cost, creating nothing.
- 3Run it
One op, or a saved preset, over one asset or five hundred. You get a job with per-item progress.
- 4Take the result
Wait, poll, or let a signed webhook tell you. Each output is an asset — publish it for a permanent URL, or download the bytes.
Holding the bytes and only want the result back? A resize, a convert or a crop is one call that stores nothing — image in, image out.
JavaScript
// 1. get the image in — or client.assets.fromUrl(url)
const { id } = await client.assets.upload("./product.jpg");
// 2. price it — same call, nothing created
const price = await client.presets.run("marketplace-cutout", id, { dryRun: true });
// → costPerItem: 227, steps: [
// { op: "remove_bg", costPerItem: 227 },
// { op: "process", costPerItem: 0 }]
// 3. run it — drop dryRun; wait holds on for the result
const job = await client.presets.run("marketplace-cutout", id, { wait: true });
const [output] = await client.jobs.outputs(job);Python
# 1. get the image in — or client.assets.from_url(url)
asset = client.assets.upload("./product.jpg")
# 2. price it — same call, nothing created
price = client.presets.run("marketplace-cutout", asset["id"], dry_run=True)
# → costPerItem: 227, steps: [
# {"op": "remove_bg", "costPerItem": 227},
# {"op": "process", "costPerItem": 0}]
# 3. run it — drop dry_run; wait holds on for the result
job = client.presets.run("marketplace-cutout", asset["id"], wait=True)
[output] = client.jobs.outputs(job)CLI
# 1. get the image in — imagestep asset upload, or asset from-url — you have an asset id
# 2. price it — same flags, nothing created
imagestep jobs estimate --preset-id marketplace-cutout \
--asset-ids ast_20fc11fbe9c74cacb4d007734a2ccfe9
# → costPerItem 227: remove_bg 227, process 0
# 3. run it — --wait blocks until the job is done; the exit code says whether to retry
imagestep jobs submit --preset-id marketplace-cutout \
--asset-ids ast_20fc11fbe9c74cacb4d007734a2ccfe9 --wait -o jsoncurl
# 1. get the image in — upload it, or POST /api/v1/assets/from-url — you have an asset id
# 2. price it — same body, nothing created
curl -s "https://api.imagestep.dev/api/v1/jobs?dryRun=true" \
-H "Authorization: ApiKey $IMAGESTEP_API_KEY" \
-H "Content-Type: application/json" \
-d '{"presetId": "marketplace-cutout",
"assetIds": ["ast_20fc11fbe9c74cacb4d007734a2ccfe9"]}'
# → "costPerItem": 227, "steps": [
# {"op": "remove_bg", "costPerItem": 227},
# {"op": "process", "costPerItem": 0}]
# 3. run it — drop dryRun; a signed webhook fires when the job is done
curl -s "https://api.imagestep.dev/api/v1/jobs" \
-H "Authorization: ApiKey $IMAGESTEP_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"presetId": "marketplace-cutout",
"assetIds": ["ast_20fc11fbe9c74cacb4d007734a2ccfe9"]}'marketplace-cutout is a preset you save yourself — its four steps are a recipe to copy. The dry run is produced by the same resolution the real submit runs, so it cannot drift from what you are charged. The five-minute version, from the SDKs, the CLI, curl or an MCP client: the quickstart.
Where it plugs in
Clients of one API. Every one of them enumerates the same catalogue and returns the same job and asset shapes, so what you learn in one carries to the next.
n8n node
n8n-nodes-imagestepOne node whose op list is the live catalogue, a trigger that fires when a job finishes, importable templates. No runtime dependencies.MCP server
npx -y @imagestep/mcpSeven tools for Claude, Cursor and any MCP client, hosted or local. Images never enter the context — the agent gets ids and URLs.Agent skill
imagestep skill --install claude-codeA SKILL.md that teaches Claude Code, Codex or Cursor to drive the CLI: price before spending, read errors as JSON, branch on the exit code.REST
api.imagestep.dev/api/v1The API itself — every other surface is a client of it. Idempotency keys, rate-limit headers, structured errors, signed webhooks.SDKs
npm i imagestep · pip install imagestepJavaScript and Python, typed from the OpenAPI document. Errors carry code, retryable and param; wait() holds on until a job is done.CLI
npx imagestep-cliThe terminal, shell scripts and CI. JSON out, exit codes that carry retryable, --wait to hold on until a job is done.Readable before you sign up
Everything a client needs in order to decide is public; the key is only for spending.
/llms.txt— the product, for a language model/.well-known/mcp/server-card.json— the MCP server, for a registryGET /api/v1/ops— every op, parameter and priceGET /api/v1/agent-guidelines— how an agent should behave here
Questions
- Do I need a card to start?
- No. The Free plan comes with 200 assets, 200 deterministic ops a month — past them each op is $0.002, paid from your balance — and a $3 welcome credit, and every feature is open on every plan: paid plans buy quota, retention and support.
- What happens when step three of a chain fails?
- You pay for the AI steps that finished, the item says which step failed, and POST /jobs/{id}/resume restarts each failed item from that step without paying twice for what already succeeded.
- Can I choose the model?
- Yes. Every AI op has a default model and takes a model parameter; the catalogue lists each model with its price per image.
- Does it work with Make or Zapier?
- Not as a native app today. Anything with an HTTP step can call the REST API, and n8n has a native node with a trigger.
- Is this a photo library or an editor?
- No. There is no album, no canvas and no chat, and it does not do video or PDF. It is the step a program calls and a person audits.
- Not on the list?
- Write to support@imagestep.dev. The long answers — every op, every error code — are in the docs.
Add the step.
Free plan: 200 assets · 200 deterministic ops a month, then $0.002 each · $3 welcome credit for AI ops. No card.