Every API here is available over the APIs.io API and to AI agents over MCP.
openapi: 3.2.0
info:
title: ImageStep AI Models API
description: 'The image step for your automations. Store images as assets, run an op or a preset on them as a job — priced first with `?dryRun=true`, then read, waited on or delivered to a webhook — or transform one image synchronously while you wait. Send `Authorization: ApiKey `; the op catalogue (`/api/v1/ops`) needs no credential.
**Idempotency:** Endpoints that accept an `Idempotency-Key` header support optional deduplication. Supply a unique key (e.g. a UUID) per logical request. Repeating the same key with the same body replays the stored response (`Idempotency-Replayed: true`) without re-running anything; repeating it with a different body is a 409 `idempotency_key_reuse`. Omitting the header processes the request normally. Keys are retained for 24 hours.
**Errors** all share one shape: `{"error": {"code", "message", "retryable", "param", "details", "requestId"}}`. Branch on `code`, and let `retryable` — not the status code — decide whether to come back.
**Rate limits** are published on every response as `RateLimit-Limit`, `RateLimit-Remaining` and `RateLimit-Reset` (seconds). A 429 adds `Retry-After`.
**A paged list** takes `page` (from 0) and `perPage`, and every page answers `meta.nextCursor`; send it back as `cursor` to read on without counting.
**Every response carries `X-Request-Id`** — yours if you sent one, ours otherwise — and a failure repeats it as `error.requestId`. It is what finds the request in our logs.
The error-code table, idempotency, limits and pagination are at https://imagestep.dev/docs/errors; the webhook events at https://imagestep.dev/docs/webhooks; what may change inside v1, and the changelog, at https://imagestep.dev/docs/changelog.'
contact:
name: ImageStep Team
url: https://imagestep.dev/support
license:
name: Proprietary
url: https://imagestep.dev/terms
version: v1
servers:
- url: https://api.imagestep.dev
description: Production server
tags:
- name: AI Models
description: The models the AI ops run on — what `model` may name on a job or a preset step, with each model's price, its categories and how big an image it is handed
paths:
/api/v1/ai-models:
get:
tags:
- AI Models
summary: List AI models
description: 'Every model an AI op can run on, across the providers behind this API. A model runs an op when its
`categories` include the op''s `modelCategory` (`GET /api/v1/ops`); naming any other model is
`400 invalid_param`, with the models that fit in `details.allowed`. Leave `model` out and the op''s
`defaultModel` runs.
Each entry carries its price per image after markup (`priceRange`) beside the provider''s own
list price (`providerPrice`, `providerPriceRange`), the parameters it takes (`params`, in the op
catalogue''s shape), and `maxInputEdge` / `maxInputImages` — how big an input it is handed and how
many images one call takes (what bounds a preset''s reference images). The exact price of one
request is the dry run.
The snake_case names, `parameters`, `supported_parameters` and `created` are deprecated and go on
2027-01-12 (https://imagestep.dev/docs/changelog#2026-10-14-model-fields): until then every answer
carries both names, and `Deprecation` / `Sunset` / `Link` headers that say so.
USE THIS WHEN:
- Choosing a `model` for an AI op, or checking one before a submit
- Checking what a model costs, or how many reference images it takes
DO NOT USE WHEN:
- You want each op''s default model and its price → `GET /api/v1/ops`, which carries them'
operationId: getModels
parameters:
- name: mode
in: query
description: 'ai_image (the default): the models the image ops run · analyze: the models the analyze op sells, priced per image'
required: false
schema:
type: string
enum:
- ai_image
- analyze
example: ai_image
responses:
'200':
description: The models of that mode
headers:
RateLimit-Limit:
description: Requests allowed in the current window
schema:
type: integer
format: int32
RateLimit-Remaining:
description: Requests left in the current window
schema:
type: integer
format: int32
RateLimit-Reset:
description: Seconds until the window resets
schema:
type: integer
format: int32
X-Request-Id:
description: This request's id — echoed from your own `X-Request-Id` when you send one. Identical to `error.requestId` on a failure; quote it when reporting one.
schema:
type: string
content:
'*/*':
schema:
$ref: '#/components/schemas/ApiResponseListModelDTO'
'400':
description: '`invalid_param` on `mode` — neither `ai_image` nor `analyze`'
headers:
RateLimit-Limit:
description: Requests allowed in the current window
schema:
type: integer
format: int32
RateLimit-Remaining:
description: Requests left in the current window
schema:
type: integer
format: int32
RateLimit-Reset:
description: Seconds until the window resets
schema:
type: integer
format: int32
X-Request-Id:
description: This request's id — echoed from your own `X-Request-Id` when you send one. Identical to `error.requestId` on a failure; quote it when reporting one.
schema:
type: string
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'429':
description: Rate limited — `error.code` is `rate_limited` and `retryable` is true. `Retry-After` says how many seconds to wait.
headers:
Retry-After:
description: Seconds to wait before retrying
schema:
type: integer
format: int32
RateLimit-Limit:
description: Requests allowed in the current window
schema:
type: integer
format: int32
RateLimit-Remaining:
description: Requests left in the current window
schema:
type: integer
format: int32
RateLimit-Reset:
description: Seconds until the window resets
schema:
type: integer
format: int32
X-Request-Id:
description: This request's id — echoed from your own `X-Request-Id` when you send one. Identical to `error.requestId` on a failure; quote it when reporting one.
schema:
type: string
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
security:
- apiKeyAuth: []
components:
schemas:
ModelDTO:
type: object
description: A model an AI op can run on, with its price and what it accepts
properties:
id:
type: string
description: The model's id — what `model` names on a job or a preset step
example: fal-ai/bria/background/remove
series:
type: string
description: Provider family derived from the model id prefix
example: Openai
name:
type: string
description: Human readable model name
example: OpenAI GPT-4o
description:
type: string
description: Short description of the model's capabilities
example: Large multimodal model with fast responses.
mode:
type: string
description: 'Model mode: `analyze` for the models the analyze op sells, `ai_image` for the rest'
enum:
- ai_image
- analyze
example: ai_image
created:
type: integer
format: int64
deprecated: true
description: 'Deprecated, and goes on 2027-01-12 with no replacement: it was never when the model changed, only a constant per provider. https://imagestep.dev/docs/changelog#2026-10-14-model-fields'
example: 1711500000
parameters:
deprecated: true
description: 'Deprecated: read `params`, the same declaration in the op catalogue''s shape; goes on 2027-01-12. https://imagestep.dev/docs/changelog#2026-10-14-model-fields. A list of `{key, label, type, defaultValue}`, with `options` or `min` / `max` where the value is bounded'
params:
type: object
additionalProperties:
$ref: '#/components/schemas/ModelParam'
description: 'What a job''s `parameters` may carry on this model, in the op catalogue''s shape (`GET /api/v1/ops` → `params`): name → `{type, enum?, min?, max?, default?, title, description?}`. A key not here, or a value outside its `enum` or bounds, is `400 invalid_param`. Empty for an `analyze` model: its two parameters are the op''s own'
inputModalities:
type: array
description: Input modalities supported by the model
example:
- text
- image
items:
type: string
outputModalities:
type: array
description: Output modalities supported by the model
example:
- text
- image
items:
type: string
contextLength:
type: integer
format: int32
description: Maximum context window supported by the model (tokens)
example: 128000
categories:
type: array
description: What the model is sold for. It runs an op when this includes the op's `modelCategory` (GET /api/v1/ops)
example:
- image_generate
- image_edit
items:
type: string
promptPrice:
type: string
description: Price per 1M input tokens in USD
example: '5.00'
completionPrice:
type: string
description: Price per 1M output tokens in USD
example: '15.00'
providerPrice:
type: string
description: The provider's list price per image in USD, before our markup — the cheapest end when the price has a range. Every model carries one, so our multiple of it can be checked.
example: '0.039'
providerPriceRange:
type: string
description: The provider's list price range in USD across the same span as `priceRange`. Present only for models whose provider price depends on a parameter.
example: $0.12 - $0.48
imageRequired:
type: boolean
description: Whether an input image is required (true), optional (false), or not supported (null)
example: true
maxInputImages:
type: integer
format: int32
description: Maximum number of input images accepted. null = no image input, 1 = single image, >1 = multi-image
example: 1
maxInputEdge:
type: integer
format: int32
description: 'The longest edge, in pixels, of an input image this model is handed: a larger input is turned upright, scaled down to it and re-encoded as WebP with no metadata before the provider sees it. For a model billed per megapixel it is also what the quoted price assumes. Absent for a model that takes no image.'
example: 2048
deprecation:
$ref: '#/components/schemas/Deprecation'
description: 'Present while the model is being retired (apps/service/doc/models.md): when it was announced, the day this service switches, the provider''s own shutdown, what it runs as from then — absent when it is refused from then — and the changelog entry. Absent for a model that is not going. A retired model is no longer listed; naming it runs its `successor`.'
priceRange:
type: string
description: Our price per image in USD — the provider's list price plus our markup — as one figure, or min - max across sizes, qualities or scale factors
example: $0.009 - $0.133
structuredOutput:
type: boolean
description: Whether the model supports JSON schema structured output
example: true
supported_parameters:
type: array
deprecated: true
description: 'Deprecated: `params`'' keys, until 2027-01-12. https://imagestep.dev/docs/changelog#2026-10-14-model-fields'
items:
type: string
deprecated: true
input_modalities:
type: array
deprecated: true
description: 'Deprecated: `inputModalities`, until 2027-01-12. https://imagestep.dev/docs/changelog#2026-10-14-model-fields'
items:
type: string
deprecated: true
output_modalities:
type: array
deprecated: true
description: 'Deprecated: `outputModalities`, until 2027-01-12. https://imagestep.dev/docs/changelog#2026-10-14-model-fields'
items:
type: string
deprecated: true
context_length:
type: integer
format: int32
deprecated: true
description: 'Deprecated: `contextLength`, until 2027-01-12. https://imagestep.dev/docs/changelog#2026-10-14-model-fields'
prompt_price:
type: string
deprecated: true
description: 'Deprecated: `promptPrice`, until 2027-01-12. https://imagestep.dev/docs/changelog#2026-10-14-model-fields'
completion_price:
type: string
deprecated: true
description: 'Deprecated: `completionPrice`, until 2027-01-12. https://imagestep.dev/docs/changelog#2026-10-14-model-fields'
provider_price:
type: string
deprecated: true
description: 'Deprecated: `providerPrice`, until 2027-01-12. https://imagestep.dev/docs/changelog#2026-10-14-model-fields'
image_price_range:
type: string
deprecated: true
description: 'Deprecated: `priceRange`, until 2027-01-12. https://imagestep.dev/docs/changelog#2026-10-14-model-fields'
provider_price_range:
type: string
deprecated: true
description: 'Deprecated: `providerPriceRange`, until 2027-01-12. https://imagestep.dev/docs/changelog#2026-10-14-model-fields'
support_structured_output:
type: boolean
deprecated: true
description: 'Deprecated: `structuredOutput`, until 2027-01-12. https://imagestep.dev/docs/changelog#2026-10-14-model-fields'
image_required:
type: boolean
deprecated: true
description: 'Deprecated: `imageRequired`, until 2027-01-12. https://imagestep.dev/docs/changelog#2026-10-14-model-fields'
max_input_images:
type: integer
format: int32
deprecated: true
description: 'Deprecated: `maxInputImages`, until 2027-01-12. https://imagestep.dev/docs/changelog#2026-10-14-model-fields'
max_input_edge:
type: integer
format: int32
deprecated: true
description: 'Deprecated: `maxInputEdge`, until 2027-01-12. https://imagestep.dev/docs/changelog#2026-10-14-model-fields'
required:
- id
ApiError:
type: object
description: Structured error. Present on every 4xx/5xx response, absent on success.
properties:
code:
type: string
description: Machine-readable error code from a closed set
example: invalid_param
message:
type: string
description: Human-readable explanation. Never parse this — parse `code`.
example: 'format must be one of: jpeg, png, webp'
retryable:
type: boolean
description: Whether repeating the same request unchanged could succeed. The whole reason this field exists is that an agent cannot infer it from the status code.
example: false
param:
type: string
description: Which request parameter the error is about, when it is about one
example: format
details:
type: object
additionalProperties: {}
description: Extra machine-readable context, e.g. per-field validation messages
requestId:
type: string
description: 'The id of this request, identical to the `X-Request-Id` response header. Quote it when reporting a failure: it is what finds the request in our logs.'
example: 9f0c1c2e-6f2a-4f6b-9d3e-0a1b2c3d4e5f
required:
- retryable
ModelParam:
type: object
description: One parameter a model takes — the shape of an op's `params` entry
properties:
type:
type: string
description: The JSON type of the value
enum:
- integer
- number
- string
- boolean
enum:
type: array
description: The values it takes; any other is `400 invalid_param`
items: {}
min:
type: number
description: The smallest value it takes
max:
type: number
description: The largest value it takes
default:
description: What the model uses when the key is left out
title:
type: string
description: Its name, for a person
description:
type: string
description: What it does
required:
- title
- type
Deprecation:
type: object
description: A model on its way out, and what replaces it
properties:
announced:
type: string
description: When the provider announced the retirement, an ISO date
example: '2026-11-10'
retireAt:
type: string
description: 'The day this service switches, 00:00 UTC, an ISO date: from then the id runs as `successor`, or is refused when there is none'
example: '2027-02-09'
shutdown:
type: string
description: The day the provider stops serving it, an ISO date
example: '2027-02-10'
successor:
type: string
description: The model it runs as from `retireAt`, its parameters mapped; absent when it is refused from then
example: openai/gpt-image-2.6-flare
changelog:
type: string
description: 'The changelog entry: what changes, how the parameters map, how the price moves'
example: https://imagestep.dev/docs/changelog#2026-11-10-gpt-image-2
required:
- announced
- changelog
- retireAt
- shutdown
ErrorResponse:
type: object
description: 'The answer to every failed request: `error` says what went wrong and whether to retry, and nothing else rides beside it — no `data`, no `meta`.'
properties:
success:
type: boolean
description: Always `false` on a failure
error:
$ref: '#/components/schemas/ApiError'
timestamp:
type: string
format: date-time
description: When the response was generated
required:
- error
- success
ApiResponseListModelDTO:
type: object
description: Standard API response wrapper containing status, message, data and timestamp
properties:
success:
type: boolean
description: Indicates if the request was successful
example: true
message:
type: string
description: Human-readable message about the response
example: Operation completed successfully
data:
type: array
description: The response data payload
items:
$ref: '#/components/schemas/ModelDTO'
timestamp:
type: string
format: date-time
description: Timestamp when the response was generated
example: '2024-01-15T10:30:45.123Z'
error:
$ref: '#/components/schemas/ApiError'
description: Structured error; present exactly when the request failed
meta:
$ref: '#/components/schemas/PageMeta'
description: Pagination metadata for list responses
required:
- data
- success
PageMeta:
type: object
properties:
total:
type: integer
format: int64
description: 'Rows matching the filter. Page mode only: a cursor request counts nothing'
page:
type: integer
format: int32
description: The page served, from 0. Page mode only
perPage:
type: integer
format: int32
description: Rows per page actually used (out of range is clamped)
hasMore:
type: boolean
description: Whether there is another page
nextCursor:
type:
- string
- 'null'
description: Pass back as `cursor` for the rows after this page; null on the last page. Opaque — send it unchanged, with the same filters
securitySchemes:
apiKeyAuth:
type: apiKey
description: 'API Key authentication. Format: ''ApiKey <your-api-key>''. Note: Only allowlisted endpoints accept API key authentication.'
name: Authorization
in: header