{
  "openapi": "3.1.0",
  "info": {
    "title": "Fast WebP Converter API",
    "version": "1.0.0",
    "summary": "Convert images to WebP over HTTPS.",
    "description": "Converts JPG, PNG, GIF, WebP, AVIF, TIFF and SVG images to WebP with libwebp. Animated GIFs come out as animated WebP. HEIC photos and BMP files are not read on the server: the browser converter handles them (HEIC in Safari).\n\nAuthenticate with an API key from https://www.fastwebpconverter.com/account as `Authorization: Bearer fwk_...` (an OAuth access token from https://www.fastwebpconverter.com's authorization server works too).\n\nSend the image as a multipart upload (field `file`, up to 4 MB), as a raw image body, or as a JSON body with a public `url`. The answer is the WebP bytes, or, with `?response=json` or `Accept: application/json`, a JSON result with an expiring download link.\n\nLimits per account, shared with the MCP server: Free: 50 conversions a month, 10 requests a minute, images by URL up to 10 MB, JSON download links kept 24 h. Pro: 10,000 conversions a month, 120 requests a minute, images by URL up to 25 MB, JSON download links kept 72 h. The monthly allowance resets on the 1st (UTC).\n\nDocumentation: https://www.fastwebpconverter.com/webp-api",
    "termsOfService": "https://www.fastwebpconverter.com/terms",
    "contact": {
      "name": "Fast WebP Converter support",
      "url": "https://www.fastwebpconverter.com/contact"
    }
  },
  "externalDocs": {
    "description": "API documentation",
    "url": "https://www.fastwebpconverter.com/webp-api"
  },
  "servers": [
    {
      "url": "https://www.fastwebpconverter.com/api/v1",
      "description": "Production"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Conversion",
      "description": "Convert images to WebP."
    },
    {
      "name": "Account",
      "description": "Plan and allowance."
    }
  ],
  "paths": {
    "/convert": {
      "post": {
        "operationId": "convertImage",
        "tags": [
          "Conversion"
        ],
        "summary": "Convert an image to WebP",
        "description": "Converts one image to WebP. Send a JSON body with a public image `url`, a multipart upload (`file`), or the raw image bytes. Options go in the body or the query string. Each successful conversion uses one conversion of the monthly allowance. Use `response=json` to get a download link instead of the bytes.",
        "parameters": [
          {
            "$ref": "#/components/parameters/response"
          },
          {
            "$ref": "#/components/parameters/quality"
          },
          {
            "$ref": "#/components/parameters/max_width"
          },
          {
            "$ref": "#/components/parameters/lossless"
          },
          {
            "$ref": "#/components/parameters/filename"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConvertUrlRequest"
              },
              "examples": {
                "photo": {
                  "summary": "A photo, 1600 px wide at most",
                  "value": {
                    "url": "https://example.com/images/hero.png",
                    "quality": 80,
                    "max_width": 1600
                  }
                },
                "logo": {
                  "summary": "A logo, lossless",
                  "value": {
                    "url": "https://example.com/logo.png",
                    "lossless": true
                  }
                }
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/ConvertUploadRequest"
              },
              "encoding": {
                "file": {
                  "contentType": "image/*"
                }
              }
            },
            "image/*": {
              "schema": {
                "type": "string",
                "contentMediaType": "image/*",
                "description": "The raw image bytes, up to 4 MB. Options go in the query string."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The converted image, or a JSON result when `response=json` or `Accept: application/json`.",
            "headers": {
              "X-Original-Bytes": {
                "$ref": "#/components/headers/X-Original-Bytes"
              },
              "X-Webp-Bytes": {
                "$ref": "#/components/headers/X-Webp-Bytes"
              },
              "X-Output-Width": {
                "$ref": "#/components/headers/X-Output-Width"
              },
              "X-Output-Height": {
                "$ref": "#/components/headers/X-Output-Height"
              },
              "X-Quota-Remaining": {
                "$ref": "#/components/headers/X-Quota-Remaining"
              },
              "X-Extra-Remaining": {
                "$ref": "#/components/headers/X-Extra-Remaining"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConvertResult"
                },
                "example": {
                  "filename": "hero.webp",
                  "download_url": "https://www.fastwebpconverter.com/dl/Qm8x2kV4nT0pLr7a",
                  "expires_at": "2026-10-10T09:14:03.000Z",
                  "original_bytes": 2493112,
                  "webp_bytes": 287401,
                  "saved_percent": 88,
                  "width": 1600,
                  "height": 1067,
                  "animated": false,
                  "quota_remaining": 9999,
                  "extra_remaining": 0
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "contentMediaType": "image/webp"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameter, invalid URL, or a URL that points to a private address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_parameter",
                    "message": "quality must be an integer from 1 to 100."
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "description": "The monthly allowance is used up.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "quota_exceeded",
                    "message": "Free includes 50 server conversions a month and they are used up."
                  }
                }
              }
            }
          },
          "413": {
            "description": "Upload over 4 MB, or image behind the URL over the plan's limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "file_too_large",
                    "message": "Uploads are limited to 4 MB. Send larger images by URL with the url field."
                  }
                }
              }
            }
          },
          "415": {
            "description": "Not an image, or a format the server does not read (HEIC, BMP).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "unsupported_format",
                    "message": "This file is not an image we can read."
                  }
                }
              }
            }
          },
          "422": {
            "description": "The URL could not be fetched or the image could not be decoded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "fetch_failed",
                    "message": "The image could not be downloaded."
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "description": "Unexpected error; the conversion is not counted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "internal_error",
                    "message": "Something went wrong on our side. Please try again."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/usage": {
      "get": {
        "operationId": "getUsage",
        "tags": [
          "Account"
        ],
        "summary": "Plan and conversions left",
        "description": "The account's plan, how many conversions are used and left this month, and when the allowance resets. Uses no conversion.",
        "responses": {
          "200": {
            "description": "Usage of the account the key belongs to.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Usage"
                },
                "example": {
                  "plan": "pro",
                  "monthly_limit": 10000,
                  "used_this_month": 126,
                  "remaining_this_month": 9874,
                  "extra_conversions": 0,
                  "resets_at": "2026-11-01T00:00:00.000Z",
                  "requests_per_minute": 120,
                  "max_url_mb": 25
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "An API key (fwk_...) from https://www.fastwebpconverter.com/account, or an OAuth access token."
      }
    },
    "parameters": {
      "response": {
        "name": "response",
        "in": "query",
        "required": false,
        "description": "`json` returns a JSON result with a download link instead of the WebP bytes.",
        "schema": {
          "type": "string",
          "enum": [
            "binary",
            "json"
          ],
          "default": "binary"
        }
      },
      "quality": {
        "name": "quality",
        "in": "query",
        "required": false,
        "description": "WebP quality (also accepted in the body). 75-85 for photos, 90+ for screenshots and text.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100,
          "default": 80
        }
      },
      "max_width": {
        "name": "max_width",
        "in": "query",
        "required": false,
        "description": "Downscale to at most this width in pixels, keeping the aspect ratio. Never upscales.",
        "schema": {
          "type": "integer",
          "minimum": 16,
          "maximum": 10000
        }
      },
      "lossless": {
        "name": "lossless",
        "in": "query",
        "required": false,
        "description": "Lossless WebP, for logos, icons and flat graphics.",
        "schema": {
          "type": "boolean",
          "default": false
        }
      },
      "filename": {
        "name": "filename",
        "in": "query",
        "required": false,
        "description": "Raw-body uploads: the source file name the output is named after.",
        "schema": {
          "type": "string"
        }
      }
    },
    "headers": {
      "X-Original-Bytes": {
        "description": "Size of the source image in bytes.",
        "schema": {
          "type": "integer"
        }
      },
      "X-Webp-Bytes": {
        "description": "Size of the WebP result in bytes.",
        "schema": {
          "type": "integer"
        }
      },
      "X-Output-Width": {
        "description": "Output width in pixels.",
        "schema": {
          "type": "integer"
        }
      },
      "X-Output-Height": {
        "description": "Output height in pixels.",
        "schema": {
          "type": "integer"
        }
      },
      "X-Quota-Remaining": {
        "description": "Conversions left in this month's allowance.",
        "schema": {
          "type": "integer"
        }
      },
      "X-Extra-Remaining": {
        "description": "Extra conversions credited on top of the monthly allowance.",
        "schema": {
          "type": "integer"
        }
      },
      "X-RateLimit-Remaining": {
        "description": "Requests left in the current minute for this key.",
        "schema": {
          "type": "integer"
        }
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Missing or invalid API key.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "unauthorized",
                "message": "Missing or invalid API key. Create one at https://www.fastwebpconverter.com/account and send it as: Authorization: Bearer fwk_..."
              }
            }
          }
        }
      },
      "RateLimited": {
        "description": "Too many requests this minute for the plan.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "rate_limited",
                "message": "Too many requests: your plan allows 10 a minute."
              }
            }
          }
        },
        "headers": {
          "Retry-After": {
            "description": "Seconds to wait before retrying.",
            "schema": {
              "type": "integer"
            }
          }
        }
      }
    },
    "schemas": {
      "ConvertUrlRequest": {
        "type": "object",
        "required": [
          "url"
        ],
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048,
            "description": "Public http(s) URL of the image. Up to 10 MB on Free, 25 MB on Pro. Private and local addresses are refused."
          },
          "quality": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100,
            "default": 80,
            "description": "WebP quality. Ignored when lossless."
          },
          "max_width": {
            "type": "integer",
            "minimum": 16,
            "maximum": 10000,
            "description": "Maximum output width in pixels. Never upscales."
          },
          "lossless": {
            "type": "boolean",
            "default": false,
            "description": "Lossless WebP."
          },
          "response": {
            "type": "string",
            "enum": [
              "binary",
              "json"
            ],
            "description": "Same as the query parameter."
          }
        }
      },
      "ConvertUploadRequest": {
        "type": "object",
        "properties": {
          "file": {
            "type": "string",
            "contentMediaType": "application/octet-stream",
            "description": "The image file, up to 4 MB (4194304 bytes)."
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Instead of file: a public image URL."
          },
          "quality": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100,
            "default": 80
          },
          "max_width": {
            "type": "integer",
            "minimum": 16,
            "maximum": 10000
          },
          "lossless": {
            "type": "boolean",
            "default": false
          },
          "response": {
            "type": "string",
            "enum": [
              "binary",
              "json"
            ]
          }
        }
      },
      "ConvertResult": {
        "type": "object",
        "required": [
          "filename",
          "download_url",
          "expires_at",
          "original_bytes",
          "webp_bytes",
          "saved_percent",
          "width",
          "height",
          "animated",
          "quota_remaining",
          "extra_remaining"
        ],
        "properties": {
          "filename": {
            "type": "string",
            "description": "Output file name."
          },
          "download_url": {
            "type": "string",
            "format": "uri",
            "description": "Link to the WebP file. Show it to the person; it expires."
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the download link stops working."
          },
          "original_bytes": {
            "type": "integer",
            "description": "Size of the source image."
          },
          "webp_bytes": {
            "type": "integer",
            "description": "Size of the WebP."
          },
          "saved_percent": {
            "type": "integer",
            "description": "Percentage saved."
          },
          "width": {
            "type": "integer"
          },
          "height": {
            "type": "integer"
          },
          "animated": {
            "type": "boolean",
            "description": "True when an animated GIF or WebP stayed animated."
          },
          "quota_remaining": {
            "type": "integer",
            "description": "Conversions left this month."
          },
          "extra_remaining": {
            "type": "integer",
            "description": "Extra conversions left."
          }
        }
      },
      "Usage": {
        "type": "object",
        "required": [
          "plan",
          "monthly_limit",
          "used_this_month",
          "remaining_this_month",
          "extra_conversions",
          "requests_per_minute",
          "max_url_mb"
        ],
        "properties": {
          "plan": {
            "type": "string",
            "enum": [
              "free",
              "pro"
            ]
          },
          "monthly_limit": {
            "type": "integer"
          },
          "used_this_month": {
            "type": "integer"
          },
          "remaining_this_month": {
            "type": "integer"
          },
          "extra_conversions": {
            "type": "integer"
          },
          "resets_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "requests_per_minute": {
            "type": "integer"
          },
          "max_url_mb": {
            "type": "integer"
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "invalid_parameter",
                  "invalid_url",
                  "blocked_address",
                  "unauthorized",
                  "quota_exceeded",
                  "file_too_large",
                  "unsupported_format",
                  "not_an_image",
                  "fetch_failed",
                  "decode_failed",
                  "rate_limited",
                  "internal_error"
                ]
              },
              "message": {
                "type": "string",
                "description": "Written for people: safe to show as is."
              }
            }
          }
        }
      }
    }
  }
}