mochify-app Image API

Compress, convert, resize, crop, and transform a single image

Operations 2

POST /v1/squish Compress and/or convert an image #
GET /v1/checkTokens Check remaining quota #

Work with this as data

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/mochify-app:mochify-app-image-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

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 Specification

mochify-app-image-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Mochify Image API
  version: 1.0.0
  description: Mochify's REST API for zero-retention image compression, PDF page extraction/splitting, and AI image generation. Images and PDFs are streamed into RAM at api.mochify.app, processed, and returned; the original bytes are never written to disk. Authenticate with an x-api-key header (dashboard-issued key) for quota tracking, or omit auth entirely for anonymous, IP-metered use on the free tier.
  contact:
    url: https://mochify.app/docs
servers:
- url: https://api.mochify.app
  description: Production
security:
- bearerAuth: []
- apiKeyAuth: []
- {}
tags:
- name: Image
  description: Compress, convert, resize, crop, and transform a single image
paths:
  /v1/squish:
    post:
      operationId: squishImage
      tags:
      - Image
      summary: Compress and/or convert an image
      description: 'Accepts raw image bytes as the request body (no multipart wrapper) and returns the transformed image, or a ZIP when multiple format/size variants are requested via `types`/`sizes`. Every request is metered against the caller''s quota (25/mo free, 300/mo Seller, 1200/mo Pro, anonymous callers get 3 per session/batch, IP-based). File size ceilings: 20 MB on the free tier, 75 MB on paid plans.'
      parameters:
      - name: type
        in: query
        schema:
          type: string
          enum:
          - jpg
          - png
          - webp
          - avif
          - jxl
          default: jpg
        description: Output format. Ignored if `types` is also present.
      - name: width
        in: query
        schema:
          type: integer
          minimum: 0
        description: Target width in pixels. 0 or omitted preserves aspect ratio from height, or leaves the original size if both are omitted.
      - name: height
        in: query
        schema:
          type: integer
          minimum: 0
        description: Target height in pixels. Same rules as width.
      - name: types
        in: query
        schema:
          type: string
        description: CSV of output formats for a multi-variant response, e.g. `webp,avif`. Combines with `sizes` to produce the full formats × sizes matrix, returned as a ZIP.
      - name: sizes
        in: query
        schema:
          type: string
        description: CSV of target widths for a multi-variant response, e.g. `500,1200`. See `types`.
      - name: quality
        in: query
        schema:
          type: integer
          minimum: 1
          maximum: 100
          default: 65
        description: Output quality. Under `smartCompress` it is the quality of the SUBJECT — smartCompress saves bytes by softening the background, not by lowering this. `quality=100` is the best LOSSY setting, not lossless — use `lossless` for that.
      - name: lossless
        in: query
        schema:
          type: boolean
          default: false
        description: 'Pixel-exact output. Only `jxl`, `webp` and `png` can honour it; any other format (including a `types` list containing one) is a 400. Overrides `quality`, and disables `smartCompress` softening. A source that is already lossy (JPEG, AVIF, HEIC) is downgraded to the best lossy encode instead of rejected — see the X-Mochify-Lossless response header. A `png` output always reports true: pngsave is pixel-exact regardless. Expect output LARGER than the input: lossless preserves pixels, not file size.'
        example: true
      - name: quantize
        in: query
        schema:
          type: boolean
          default: false
        description: 'Lossy PNG: reduce to a dithered palette of at most 256 colors and emit an indexed PNG — typically 15-25% of the lossless size. Applies to `png` outputs only (a request with no png output is a 400) and cannot be combined with `lossless` (400). With no `quality` the palette is the full 256 colors; an explicit `quality` picks fewer (100 = 256, 80 ≈ 108, 65 ≈ 56, 50 ≈ 28, 20 = 8). Without this flag a png is always pixel-exact — `quality` alone never makes it lossy.'
        example: true
      - name: targetBytes
        in: query
        schema:
          type: integer
          minimum: 1024
        description: 'Ceiling on the emitted file size, in bytes. Nothing can predict an encoded size without encoding — libvips has no estimator and no saver takes a byte target — so this runs a short measured search (typically 1–3 encodes, at most 5) rather than a single guess. A quality guessed up front cannot work: bytes at a fixed quality are a property of the PIXELS, and span ~3x (JPEG) to ~10x (AVIF) between a flat graphic and a noisy photo at the same dimensions. Treated as an upper bound, never a quota to fill — if the requested (or default) quality already fits, that encode is the answer and the quality is left alone. Cannot be combined with `lossless` (400). Minimum 1024. See the X-Mochify-Target response header for whether the ceiling was actually reached.'
        example: 1000000
      - name: targetLever
        in: query
        schema:
          type: string
          enum:
          - quality
          - dimensions
          - both
          default: both
        description: 'Which knob `targetBytes` may turn. `quality` re-encodes lower but never resizes ("under 1MB but do not resize"); `dimensions` downscales but leaves quality alone ("1MB, don''t change the quality"); `both` lowers quality first and only then downscales. Requires `targetBytes` (a lever alone is a 400). For `png` the quality lever is palette quantization: the lossless encode is tried first and the file is quantized only if that misses the ceiling (see `quantize` and the X-Mochify-Quantize response header); `dimensions` keeps a png lossless. The `dimensions` lever is withheld when an HDR gain map is being carried (`hdr=1` on an Ultra HDR source), because resizing the base would invalidate the map: quality alone is used and the target may report `floor`.'
      - name: smartCompress
        in: query
        schema:
          type: boolean
          default: false
        description: 'Saliency-guided background softening (ONNX U²-Net-p subject mask): the background is lightly low-passed before the encode so it costs fewer bytes, while the subject is left pixel-identical and encoded at `quality` (or the default). Skipped when there is no clear subject, the subject fills the frame, the background was removed, HDR is being carried, or `lossless` is set — see the X-Mochify-SmartCompress response header.'
      - name: smartCrop
        in: query
        schema:
          type: boolean
          default: false
        description: Saliency/face-anchored crop centred on the subject; requires `width` and `height`. Alias of `crop` — either flag triggers the same behavior.
      - name: crop
        in: query
        schema:
          type: boolean
          default: false
        description: Alias of `smartCrop`.
      - name: region
        in: query
        schema:
          type: string
          example: 0.02,0.35,0.74,0.46
        description: Crop to a rectangle given as four comma-separated fractions of the image, `x,y,w,h` from the top-left corner, each 0 to 1. Measured on the upright image (after EXIF orientation) and applied before `width`/`height`, `smartCrop` and `rotate`. A box past an edge is trimmed; any value above 1 is rejected with 400. The pixel rectangle actually cut is returned in `X-Mochify-Region`.
      - name: redact
        in: query
        schema:
          type: string
          example: faces;0.155,0.54,0.205,0.075
        description: 'Hide areas of the image: a `;`-separated list of boxes in the same `x,y,w,h` fraction convention as `region`, and/or `faces` to find and hide faces with Mochify''s own detector (best-effort; it can miss small or side-on faces). Boxes are fractions of the whole upright image even when `region` is set; redaction runs before the crop. Up to 64 areas. A redacted image always has its metadata stripped, even with `stripExif=false`, and never carries an HDR gain map. See `X-Mochify-Redacted` and `X-Mochify-Redacted-Faces`.'
      - name: redactStyle
        in: query
        schema:
          type: string
          enum:
          - fill
          - blur
          default: fill
        description: 'How hidden areas look: `fill` (solid black, for anything that must stay secret) or `blur` (cosmetic; blurred text and faces can sometimes be partly recovered). Requires `redact`.'
      - name: erase
        in: query
        schema:
          type: string
          example: 0.62,0.55,0.12,0.2
        description: 'Paint objects out with plausible background (inpainting): a `;`-separated list of up to 8 boxes in the same `x,y,w,h` fraction convention as `region`, measured on the whole upright image. Draw each box around the whole object with a margin; any part of the object left outside the box can be regrown. Applied before `redact` and `region`. Erase invents content, so it is not a way to hide anything sensitive; use `redact`. Requires a paid plan (403 otherwise). The output always has its metadata stripped and carries no HDR gain map. See `X-Mochify-Erased`.'
      - name: recolor
        in: query
        schema:
          type: string
          example: 0.4,0.5,0.3,0.2:#2563eb
        description: 'Change the color of objects YOU locate, keeping their shading and texture: a `;`-separated list of up to 8 `x,y,w,h:#rrggbb` entries (box as fractions of the upright image, same convention as `region`; target color as hex). The object''s outline is found automatically inside each box and only the object is recolored; a box with no clear object is skipped and reported, never recolored as a rectangle. Box the part to recolor (e.g. the jacket, not the whole person), since everything in the outline takes the color. Not generative. Requires a paid plan (403 otherwise); 503 when the outline model is unavailable. Output metadata is stripped and HDR dropped. See `X-Mochify-Recolored` and `X-Mochify-Recolor-Skipped`.'
      - name: removeBackground
        in: query
        schema:
          type: boolean
          default: false
        description: AI background removal (ONNX BiRefNet-lite). Available on every plan, including anonymous/Free — not gated to a paid tier. Output retains alpha for PNG/WebP; JPEG flattens to `background` (default white).
      - name: generate
        in: query
        schema:
          type: string
          enum:
          - ''
          - shadow
          - background
        description: 'AI scene composition after subject isolation: `shadow` adds a drop shadow under the subject; `background` composites a described/generated scene. Empty/omitted skips this step. Distinct from `POST /v1/generate` (text-to-image from scratch).'
      - name: background
        in: query
        schema:
          type: string
        description: Flatten/composite background color (used when flattening alpha to JPEG, or as the base under `generate`).
      - name: rotate
        in: query
        schema:
          type: integer
          enum:
          - 0
          - 90
          - 180
          - 270
          default: 0
        description: Clockwise rotation in degrees.
      - name: stripExif
        in: query
        schema:
          type: boolean
          default: true
        description: 'Strip EXIF/metadata (GPS, device identifiers, timestamps). Defaults to true at the API level — pass `false` or `0` to preserve metadata. Note: the mochify.app browser UI does not uniformly default this toggle the same way across its upload components, so surface-level defaults can differ from this API default.'
      - name: optimizeForWeb
        in: query
        schema:
          type: boolean
          default: false
        description: Progressive encoding + 4:2:0 chroma subsampling for the smallest browser-delivered file.
      - name: brightness
        in: query
        schema:
          type: integer
          minimum: -100
          maximum: 100
          default: 0
        description: Exposure adjustment.
      - name: clarity
        in: query
        schema:
          type: boolean
          default: false
        description: Midtone contrast enhancement.
      - name: hdr
        in: query
        schema:
          type: boolean
          default: false
        description: Preserve an HDR gain map as Ultra HDR / ISO 21496-1 JPEG. Silently ignored if the source has no HDR gain map.
      - name: dpi
        in: query
        schema:
          type: integer
          minimum: 8
          maximum: 4800
          default: 96
        description: Output DPI metadata.
      requestBody:
        required: true
        content:
          image/jpeg:
            schema:
              type: string
              format: binary
          image/png:
            schema:
              type: string
              format: binary
          image/webp:
            schema:
              type: string
              format: binary
          image/avif:
            schema:
              type: string
              format: binary
          image/heic:
            schema:
              type: string
              format: binary
          application/octet-stream:
            schema:
              type: string
              format: binary
              description: Raw bytes; format is detected from magic bytes, not the Content-Type header.
      responses:
        '200':
          description: Transformed image (single variant) or a ZIP archive (multi-variant, when `types`/`sizes` resolve to more than one output).
          headers:
            X-Latency-Ms:
              schema:
                type: integer
              description: Server-side processing time in milliseconds.
            X-Mochify-Optimized:
              schema:
                type: boolean
              description: Whether the output is smaller than the input.
            X-Mochify-Saliency:
              schema:
                type: number
              description: Subject coverage 0.000–1.000 (mean of the saliency mask). Present only when smartCompress was used.
            X-Mochify-SmartCompress:
              schema:
                type: string
                enum:
                - background
                - skipped:no-subject
                - skipped:subject-fills-frame
                - skipped:background-removed
                - skipped:hdr
                - skipped:lossless
              description: 'Present only when smartCompress was used. Describes the emitted bytes: `background` = the background was softened; `skipped:<reason>` = the pixels were left alone and why. One value for a multi-variant ZIP.'
            X-Mochify-Quality:
              schema:
                type: integer
              description: The quality the returned bytes were encoded at. Present when `smartCompress` was used, or when a `targetBytes` search did — in which case it is the value the search settled on, not the one that was requested.
            X-Mochify-BgRemoved:
              schema:
                type: boolean
              description: Present and true only when background removal ran.
            X-Mochify-HDR:
              schema:
                type: boolean
              description: Present when the output format supports HDR gain maps; true if one was carried through.
            X-Mochify-Quantize:
              schema:
                type: string
                enum:
                - 'true'
                - 'false'
              description: 'Present for a png output when `quantize` or `targetBytes` was requested. Describes the emitted bytes: `true` = a palette (lossy) png, `false` = pixel-exact. With only `targetBytes`, `false` means the lossless encode already fit. For a multi-variant ZIP, `true` if any png entry was quantized.'
            X-Mochify-Lossless:
              schema:
                type: string
                enum:
                - 'true'
                - downgraded
              description: Present only when `lossless` was requested. `true` = the bytes are pixel-exact. `downgraded` = they are the best lossy encode instead, because the source was already lossy or because HDR reconstruction replaced the submitted pixels.
            X-Mochify-Target:
              schema:
                type: string
                enum:
                - hit
                - floor
              description: Present only when `targetBytes` was set. `hit` = the returned bytes are at or under the ceiling. `floor` = the levers ran out first and this is the smallest output that could honestly be produced — still the best available file, not an error. For a multi-variant ZIP, `hit` means every entry fits.
            X-Mochify-Target-Encodes:
              schema:
                type: integer
              description: Encodes the target search spent, including the first one the pipeline would have performed anyway. Summed across variants for a ZIP.
            X-Mochify-Target-Scale:
              schema:
                type: number
              description: Extra downscale the dimensions lever applied, relative to the geometry that was requested (e.g. 0.710). Omitted when the lever did not move, i.e. the output is exactly the size asked for.
            X-Mochify-Region:
              schema:
                type: string
              description: Present only when `region` was set. The pixel rectangle actually cut, as `x,y,w,h` in the upright source; fractions round and an over-the-edge box is trimmed, so it may differ from the box sent.
            X-Mochify-Redacted:
              schema:
                type: integer
              description: 'Present only when `redact` was set. How many areas were hidden: the boxes sent plus any faces found.'
            X-Mochify-Redacted-Faces:
              schema:
                type: integer
              description: Present only when `redact` includes `faces`. How many faces the detector found. 0 is a successful response that hid no faces, so check it rather than assuming.
            X-Mochify-Erased:
              schema:
                type: integer
              description: Present only when `erase` was set. How many boxes were painted out.
            X-Mochify-Erase-Outlined:
              schema:
                type: integer
              description: Present only when `erase` was set. Of the erased boxes, how many were repainted along the object's detected outline rather than the whole box (fewer invented pixels). 0 means every box was repainted whole.
            X-Mochify-Erase-Coverage:
              schema:
                type: number
              description: 'Present only when `erase` was set. Approximate share of the frame repainted, 0-1 (e.g. 0.112). Large removals are softer: the model paints at a fixed 512x512, so a hole covering much of a large image is filled at reduced detail.'
            X-Mochify-Recolored:
              schema:
                type: integer
              description: Present only when `recolor` was set. How many boxes had their object recolored.
            X-Mochify-Recolor-Skipped:
              schema:
                type: integer
              description: Present only when `recolor` was set. How many boxes were left alone because no clear object outline was found in them.
          content:
            image/jpeg: {}
            image/png: {}
            image/webp: {}
            image/avif: {}
            image/jxl: {}
            application/zip:
              schema:
                type: string
                format: binary
                description: Returned instead of a single image when the request resolves to multiple format/size variants.
        '400':
          description: Empty body, or an invalid types/sizes/type/width/height combination.
          content:
            text/plain: {}
        '401':
          description: x-api-key was present but not resolvable.
          content:
            text/plain: {}
        '413':
          description: File exceeds the plan's size ceiling (20 MB free, 75 MB paid), or the image's pixel dimensions / megapixels exceed the decompression-bomb ceiling.
          content:
            text/plain: {}
        '415':
          description: Unrecognized image format (magic-byte check failed).
          content:
            text/plain: {}
        '422':
          description: 'Image could not be processed: corrupt or truncated (unreadable header), or dimensions below the minimum. X-Mochify-Reject carries the taxonomy slug (e.g. corrupt-image, image-too-small).'
          content:
            text/plain: {}
        '429':
          description: Monthly quota exhausted.
          content:
            text/plain: {}
        '503':
          description: Worker pool at capacity; retry after the Retry-After header (1s).
          headers:
            Retry-After:
              schema:
                type: integer
          content:
            text/plain: {}
  /v1/checkTokens:
    get:
      operationId: checkTokens
      tags:
      - Image
      summary: Check remaining quota
      description: Read-only — does not consume a token. Works anonymously (IP-based) or with an x-api-key.
      responses:
        '200':
          description: Quota status.
          content:
            application/json:
              schema:
                type: object
                properties:
                  available:
                    type: boolean
                  remaining:
                    type: integer
                    description: Omitted on a cache miss (unseeded bucket, i.e. a caller who hasn't made a request yet).
                  quota:
                    type: integer
                  plan:
                    type: string
                  error:
                    type: string
                    description: Present only when x-api-key was supplied but invalid ("invalid_api_key"); available is then false.
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: 'Dashboard-issued API key sent as `Authorization: Bearer <key>`. This is the header documented on /docs and in the dashboard, and the one to prefer. A signed-in session token is accepted here too. Note: a bearer token that cannot be resolved does not fail the request, it falls through to anonymous IP-based free-tier limits, so a wrong key behaves exactly like sending no key at all. Send the key as x-api-key instead if you want an unusable key reported back to you.'
    apiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: The same dashboard-issued API key, sent in the x-api-key header. Used by /v1/squish, /v1/pdf, /v1/generate, /v1/checkTokens, /v1/upload/*. Unlike the bearer header, a key that cannot be resolved is reported as invalid rather than silently downgraded. If no credential is sent at all, these endpoints fall back to anonymous IP-based rate limiting on the free tier rather than rejecting the request.