Every API here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for apis
7 MCP tools reach this
find_apisBrowse and filter every API in the catalog.
get_api_artifactsOne API's artifacts, grouped by type.
get_openapiThe primary OpenAPI for this API.
find_similar_apisAPIs that look like this one.
apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
resolveTurn a domain, URL or GitHub org into the provider it belongs to.
find_cohortsEvery scored population of providers in the catalog.
All 92 tools →
Call it yourself
curl for this page
This API
curl "https://apis.io/api/v1/apis/imagestep-dev:imagestep-dev-agent-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"
Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we
store it to create your key and to recognise you if you sign in with another
provider. See our Privacy Policy and
Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: ImageStep Agent 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: Agent
description: The agent contract face. `GET /api/v1/agent-guidelines` is the operating rules as one document — public, no key needed. `POST /api/v1/feedback` reports what ImageStep could not do, instead of routing around it, and `GET /api/v1/feedback` reads your reports back.
paths:
/api/v1/feedback:
get:
tags:
- Agent
summary: Your own reports
description: Everything this account has submitted, newest first, a page at a time. Yours only; there is no cross-account read.
operationId: list_4
parameters:
- name: page
in: query
description: Page number (0-indexed). Leave it out when you send cursor
required: false
schema:
type: integer
format: int32
default: 0
- name: perPage
in: query
description: Items per page (max 100; out of range is clamped)
required: false
schema:
type: integer
format: int32
default: 100
- name: cursor
in: query
description: 'The meta.nextCursor of the previous page: the rows after it, read without counting — the way to walk a long listing. Send it unchanged, with the same filters; it cannot be combined with page'
required: false
schema:
type: string
responses:
'200':
description: OK
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/ApiResponseListFeedback'
'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: []
post:
tags:
- Agent
summary: Report something ImageStep could not do
description: 'USE THIS WHEN: an op you needed does not exist, a parameter did not behave the
way the contract describes, or you were about to work around ImageStep with
something local. Reporting the gap is the alternative to routing around it.
Free: no credit, no job, no rate-limit budget beyond the shared API one, and at most 200 reports per account per UTC day — past that, `429 rate_limited` until midnight UTC.
`kind` is `capability_gap` (ImageStep cannot do it at all), `bug` (it did not
behave the way the contract says) or `other`; `message` says what you were trying
to do. `op` names the operation when there is one and is **not** checked against
the catalogue — the most useful report is about an op that does not exist yet.
`context` is any JSON object worth keeping.
The report comes back (`201`) with the `apiKeyId` it was filed under, so an account
running one key per agent can tell whose report it is. It is your account''s data:
exported with it, and deleted with it or 365 days after it was filed, whichever comes first.'
operationId: submit_1
parameters:
- name: Idempotency-Key
in: header
description: 'Optional. A client-generated unique key (typically a UUID). Same key + the same request (method, path, query string and body) replays the first response verbatim with `Idempotency-Replayed: true`, without executing again. Same key + a different one returns 409 `idempotency_key_reuse`. A repeat that arrives while the first is still running returns 409 `request_in_progress`, which is retryable. Keys are retained 24 hours. At most 255 characters; a longer one is a 400 `invalid_param` with `param: "Idempotency-Key"`.'
required: false
schema:
type: string
maxLength: 255
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/FeedbackRequest'
required: true
responses:
'201':
description: Logged
headers:
Idempotency-Replayed:
description: '`true` when this is the stored answer to an earlier request with the same `Idempotency-Key`, replayed without running it again; absent otherwise'
schema:
type: string
enum:
- 'true'
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/ApiResponseFeedback'
'400':
description: 'Nothing is stored when any of these is refused:
- `invalid_param` on `kind` — missing, or not one of the three (matched case-insensitively)
- `invalid_param` on `message` — missing, blank, or over 4000 characters once trimmed
- `invalid_param` on `op` — over 64 characters
- `invalid_param` on `context` — over 4000 characters once encoded as JSON'
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.
Here also: `rate_limited` — this account filed 200 reports today (UTC). Retryable: `details.resetAt` is the next midnight UTC, `Retry-After` the seconds until it; nothing is stored'
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'
'409':
description: Conflict — `error.code` is `idempotency_key_reuse` (the key already means a different request) or `request_in_progress` (the first request under this key has not settled yet; retryable).
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'
security:
- apiKeyAuth: []
components:
schemas:
ApiResponseFeedback:
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:
$ref: '#/components/schemas/Feedback'
description: The response data payload
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
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
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
Feedback:
type: object
properties:
id:
type: string
description: The report's id, `fbk_…`
kind:
type: string
description: What kind of report it is, stored lower-case
enum:
- capability_gap
- bug
- other
op:
type: string
description: The op this is about, when it is about one.
example: remove_bg
apiKeyId:
type: string
description: The API key this was reported with; absent when it came from a signed-in console session.
message:
type: string
description: What the reporter wrote, trimmed
context:
type: object
additionalProperties: {}
description: 'Anything structured worth keeping: the parameters tried, the client, the model.'
createdAt:
type: string
format: date-time
description: When it was filed
required:
- createdAt
- id
- kind
- message
ApiResponseListFeedback:
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/Feedback'
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
FeedbackRequest:
type: object
description: A report from an agent about something ImageStep could not do.
properties:
kind:
type: string
description: What kind of report it is, matched case-insensitively
enum:
- capability_gap
- bug
- other
op:
type: string
description: The op this is about, when it is about one — any name up to 64 characters; not checked against the catalogue.
example: remove_bg
message:
type: string
description: What you were trying to do and what stopped you; at most 4000 characters.
context:
type: object
additionalProperties: {}
description: Anything structured worth keeping — the parameters tried, the client, the model; at most 4000 characters once encoded as JSON.
required:
- kind
- message
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