{"openapi":"3.1.0","info":{"title":"Ecom Image Optimizer API","version":"1.0.0","summary":"Resize, compress and watermark product images from your own code.","description":"A small, synchronous API. Send an image, get an optimized one back.\n\n### Authentication\n\nEvery request needs `Authorization: Bearer iok_live_...`. Keys are issued per\naccount and carry scopes; a key missing the scope for an endpoint gets 403 rather\nthan 401, so you can tell \"wrong key\" from \"key cannot do this\".\n\nA `iok_test_...` key runs the same pipeline against the same image processor and\nreturns a real optimized file. It never spends credits, never counts against the\nfree monthly allowance, and its output is deleted after an hour.\n\n### What a call costs\n\n500 calls a month are free per account, then each call spends one\ncredit. Re-sending the same image within 24 hours is free: the credit unit is a\nunique source image, not a request, so retries and reprocessing are not billed\ntwice. `billable` in the response says which happened.\n\n### Rate limits\n\n60 requests a minute per key by default. Every response carries\n`X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset`, and they\nreport the real window rather than a fixed ceiling, so backing off on them works.\n\n### Errors\n\nOn the resource endpoints, every failure is an RFC 9457 problem document with\n`content-type: application/problem+json`. `type` is a stable URL you can switch\non; `title` is for humans and may change.\n\n`/v1/device/code` and `/v1/token` are the exception, and deliberately so. They\nimplement RFC 8628, whose error vocabulary is normative, so they answer with\nOAuth errors: `application/json`, and a body whose first member is `error`. A\nstock device-flow client reads that member and would see nothing in a problem\ndocument.\n\n### Connecting an agent\n\nAn agent with no browser uses the Device Authorization Grant (RFC 8628). It posts\nto `/v1/device/code`, shows the returned `user_code` to a human, and polls\n`/v1/token` until that human approves it at the verification URI. On approval it\nreceives a normal scoped key.\n\n**The happy path while waiting is HTTP 400 `authorization_pending`.** That is what\nRFC 6749 section 5.2 specifies and it is not an error in your integration. Honour\nthe `interval`, add five seconds permanently on `slow_down`, and stop on any other\nerror code. On a connection failure or a 503, back off exponentially: that is a\ndifferent rule from `slow_down` and the two are easy to conflate.\n\nKeys issued this way do not expire. Revoke them at `/account`.\n\n### Model Context Protocol\n\nThe same key authenticates an MCP server at `https://ecommerceimageoptimizer.com/api/mcp`, Streamable HTTP\ntransport, which exposes `optimize_image`, `list_presets` and `check_account` to an\nagent without a client being written. A key only sees the tools its scopes allow.\n\nIt is not described in this document, and that is deliberate: MCP is JSON-RPC over\none endpoint and carries its own version header, so an OpenAPI operation for it\nwould produce one useless method in every generated client. Discovery lives at\n`/.well-known/oauth-protected-resource/api/mcp` instead, which is where the protocol\nsays to look.\n\n`optimize_image` takes `image_url` rather than base64, because tool arguments are\nproduced by a language model and 3 MB of image is over a million output tokens.\n\n### CORS\n\nThere is none, deliberately. This API is not callable from a browser, because a\nkey in browser JavaScript is a published key. Call it from your server.","contact":{"name":"Support","url":"https://ecommerceimageoptimizer.com/contact"},"license":{"name":"Proprietary","url":"https://ecommerceimageoptimizer.com/terms"}},"servers":[{"url":"https://ecommerceimageoptimizer.com","description":"Production"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"Images","description":"The endpoint the API exists for."},{"name":"Presets","description":"Saved settings, so a call need not carry a full config."},{"name":"Account","description":"Balance, allowance and what a key may do."},{"name":"Device","description":"Connecting an agent that has no browser (RFC 8628)."}],"paths":{}}