---
title: How ImageStep works
url: https://base_url.placeholder/docs
group: Start
---

# How ImageStep works

ImageStep is the image step for your automations: a programmable pipeline — generate, edit, remove a background, upscale, resize, convert, render a template, read metadata — that a program calls and a person audits. The caller is a script, a workflow or an agent, so everything is built for that reader: one catalogue to read instead of a list to remember, a price before anything is spent, an error that says whether to retry, and results handed back as ids and URLs rather than bytes.

## Four ideas, one API key

**[Assets](https://base_url.placeholder/docs/assets)**

Every image is an asset with a stable id. Upload bytes or hand over a URL; carry the id from step to step; publish it and it gets a CDN URL that never changes.

**[Ops](https://base_url.placeholder/docs/ops)**

Atomic operations — one thing each, a closed parameter set, all in one live catalogue. AI ops run on a model you can override and are charged per item; deterministic ones — resize, convert, crop and the rest — are free on paid plans.

**[Presets](https://base_url.placeholder/docs/presets)**

Your own chain of ops, saved and versioned. Run a preset over a batch and every output looks the same — this month and next.

**[Jobs](https://base_url.placeholder/docs/jobs)**

Running an op or a preset over your assets makes a job: per-item progress, a dry run for the exact price, cancellation, resume, and a signed webhook when it is done.

Two more, for when you need them: [templates](https://base_url.placeholder/docs/templates) render HTML and data into images — an OG image per post, a card per row — and the [synchronous endpoints](https://base_url.placeholder/docs/sync) run a deterministic op on bytes you are holding and store nothing at all.

## How a call goes

Every call carries your key as `Authorization: ApiKey is_sk_…` — you create one on [/keys](https://base_url.placeholder/keys) — and every piece of work goes the same four steps:

1. **Get the image in** — upload it, or give the service a URL to fetch — you get an asset id
2. **Price it** — the same request with `?dryRun=true` — the exact cost, creating nothing
3. **Run it** — one op or a saved preset, over one asset or five hundred — you get a job
4. then take the result:

   - **wait** — in the same call
   - **poll** — the job, until it settles
   - **webhook** — signed, when it ends

The dry run refuses a bad request exactly as the submit would, and says whether your balance covers it. Each output is a new asset: publish it for a permanent URL, or download the bytes.

Step 3 on every surface — one op on an asset you already have, waiting for the result in the same call:

#### JavaScript

```js
// pnpm add imagestep
const job = await client.ops.removeBg("ast_1a2b", { wait: true });
const [out] = await client.jobs.outputs(job);
```

#### Python

```python
# pip install imagestep
job = client.ops.remove_bg("ast_1a2b", wait=True)
[out] = client.jobs.outputs(job)
```

#### CLI

```sh
imagestep jobs submit --op remove_bg --asset-ids ast_1a2b --wait
```

#### curl

```sh
# "wait" holds the response until the job is done (60 s at most): 200 with the finished job,
# or 202 with the handle — then GET /api/v1/jobs/<id>?wait=30 waits again
curl -sS -X POST https://api.imagestep.dev/api/v1/jobs \
  -H "Authorization: ApiKey $IMAGESTEP_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"op":"remove_bg","assetIds":["ast_1a2b"],"wait":30}'
```

#### MCP

```text
# tool call
transform  {"op":"remove_bg","asset_ids":["ast_1a2b"]}
```

#### n8n

```json
{
  "nodes": [
    {
      "parameters": {
        "resource": "op",
        "operation": "run",
        "op": "remove_bg",
        "inputMode": "assetIds",
        "assetIds": "ast_1a2b"
      },
      "name": "ImageStep",
      "type": "n8n-nodes-imagestep.imageStep",
      "typeVersion": 1,
      "position": [
        0,
        0
      ]
    }
  ],
  "connections": {}
}
```

The [quickstart](https://base_url.placeholder/docs/quickstart) does all four in five minutes — from the SDKs, the CLI, curl or an MCP client — and then shows [the one-call road](https://base_url.placeholder/docs/quickstart#one-call) for when you only want the bytes back.

## Ways to call it

Every surface enumerates the same catalogue and returns the same job and asset shapes, so what you learn in one carries to the next. Which one fits is a question of who makes the call:

### Workflows & agents — a host makes the call

[n8n node — one node whose op list is the live catalogue, and a trigger that fires when a job finishes](https://base_url.placeholder/docs/n8n)

[MCP server — Claude, Cursor and any MCP client, hosted or local](https://base_url.placeholder/docs/mcp)

[Agent skill — Claude Code, Codex, Cursor with a shell — the CLI's operating procedure](https://base_url.placeholder/docs/skill)

### Your code — you write the call

[SDKs — JavaScript / TypeScript on npm, Python on PyPI](https://base_url.placeholder/docs/sdk)

[CLI — the terminal and shell scripts; JSON out, exit codes that carry retryable](https://base_url.placeholder/docs/cli)

[REST — the API itself; every other surface is a client of it](https://base_url.placeholder/docs/api)

An AI agent choosing between them — MCP, the CLI and its skill, or REST — starts on [the agents page](https://base_url.placeholder/docs/agents).

## Reference

- [Ops & models](https://base_url.placeholder/docs/ops) — the live catalogue with every parameter and price.
- [Recipes](https://base_url.placeholder/docs/recipes) — presets to copy: social sizes, product shots, web, print, looks.
- [Preset steps](https://base_url.placeholder/docs/presets/steps) — the engine's registry, for a step no op covers.
- [Errors, retries & limits](https://base_url.placeholder/docs/errors) — the envelope, the closed code set, idempotency, rate limits.
- [Webhooks](https://base_url.placeholder/docs/webhooks) — signed job events, delivery and retries.
- [The console](https://base_url.placeholder/docs/console) — what a person signs in to do, page by page, and the API call behind each.
- [API reference](https://base_url.placeholder/docs/api) — every endpoint, generated from the service.

Plans, per-op prices and every model's price next to the provider's: [/pricing](https://base_url.placeholder/pricing).
