{
  "openapi": "3.1.0",
  "info": {
    "title": "Compresto Image Compression API",
    "description": "High-performance image compression API with support for JPEG, PNG, and WebP formats.",
    "version": "1.0.0",
    "contact": {
      "email": "support@compresto.app"
    }
  },
  "servers": [
    {
      "url": "https://api.compresto.app",
      "description": "Production server"
    }
  ],
  "security": [
    {
      "ApiKeyAuth": []
    }
  ],
  "paths": {
    "/health": {
      "get": {
        "summary": "Health check",
        "description": "Check API status. No authentication required.",
        "operationId": "getHealth",
        "security": [],
        "responses": {
          "200": {
            "description": "API is healthy",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                }
              }
            }
          }
        },
        "tags": [
          "Health"
        ]
      }
    },
    "/v1/compress": {
      "post": {
        "summary": "Compress image",
        "description": "Compress an image using file upload, URL, or base64-encoded data. Returns the compressed image binary with metadata in response headers.",
        "operationId": "compressImage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CompressRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/CompressMultipartRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Compressed image binary",
            "headers": {
              "X-Original-Size": {
                "description": "Original file size in bytes",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Compressed-Size": {
                "description": "Compressed file size in bytes",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Savings-Percent": {
                "description": "Compression savings percentage",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Output-Format": {
                "description": "Output image format",
                "schema": {
                  "type": "string",
                  "enum": [
                    "jpeg",
                    "png",
                    "webp"
                  ]
                }
              }
            },
            "content": {
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "missing_input": {
                    "summary": "Missing image input",
                    "value": {
                      "error": "bad_request",
                      "message": "Missing image: provide file upload, url, or base64 image field"
                    }
                  },
                  "invalid_quality": {
                    "summary": "Invalid quality parameter",
                    "value": {
                      "error": "bad_request",
                      "message": "Quality must be between 1 and 100"
                    }
                  },
                  "url_invalid": {
                    "summary": "Invalid URL format",
                    "value": {
                      "error": "url_invalid",
                      "message": "Invalid URL format"
                    }
                  },
                  "url_blocked": {
                    "summary": "URL blocked (SSRF protection)",
                    "value": {
                      "error": "url_blocked",
                      "message": "URL resolves to private/internal address"
                    }
                  },
                  "url_invalid_content": {
                    "summary": "URL did not return an image",
                    "value": {
                      "error": "url_invalid_content",
                      "message": "URL did not return an image"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "File too large",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "url_too_large": {
                    "summary": "URL image too large",
                    "value": {
                      "error": "url_too_large",
                      "message": "Image exceeds maximum size of 10MB"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or quota exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Failed to fetch image from URL",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "url_fetch_failed": {
                    "summary": "URL fetch failed",
                    "value": {
                      "error": "url_fetch_failed",
                      "message": "Failed to fetch image from URL after 3 attempts"
                    }
                  }
                }
              }
            }
          },
          "504": {
            "description": "URL fetch timed out",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "url_timeout": {
                    "summary": "URL timeout",
                    "value": {
                      "error": "url_timeout",
                      "message": "URL fetch timed out after 5000ms"
                    }
                  }
                }
              }
            }
          }
        },
        "tags": [
          "Compression"
        ]
      }
    },
    "/v1/demo-compress": {
      "post": {
        "summary": "Demo compression",
        "description": "Compress an image without authentication. Rate limited to 5 requests per hour per IP. Max file size 5MB.",
        "operationId": "demoCompressImage",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "image": {
                    "type": "string",
                    "format": "binary",
                    "description": "Image file to compress"
                  }
                },
                "required": [
                  "image"
                ]
              }
            },
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "image": {
                    "type": "string",
                    "description": "Base64-encoded image (with or without data URI prefix)"
                  }
                },
                "required": [
                  "image"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Compressed image binary",
            "headers": {
              "X-Original-Size": {
                "description": "Original file size in bytes",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Compressed-Size": {
                "description": "Compressed file size in bytes",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Savings-Percent": {
                "description": "Compression savings percentage",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Output-Format": {
                "description": "Output image format",
                "schema": {
                  "type": "string"
                }
              },
              "X-Demo-Remaining": {
                "description": "Remaining demo requests this hour",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "image/*": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "File too large (>5MB for demo)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Demo rate limit exceeded (5/hour)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RateLimitError"
                }
              }
            }
          }
        },
        "tags": [
          "Compression"
        ]
      }
    },
    "/v1/usage": {
      "get": {
        "summary": "Get usage statistics",
        "description": "Get current month's usage statistics for the authenticated API key.",
        "operationId": "getUsage",
        "responses": {
          "200": {
            "description": "Usage statistics",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsageResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "tags": [
          "Usage"
        ]
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "API key for authentication. Get your key at https://compresto.app/dashboard"
      }
    },
    "schemas": {
      "HealthResponse": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "example": "ok"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "example": "2025-12-29T10:00:00.000Z"
          }
        },
        "required": [
          "status",
          "timestamp"
        ]
      },
      "CompressMultipartRequest": {
        "type": "object",
        "description": "File upload with compression options as form fields.",
        "properties": {
          "file": {
            "type": "string",
            "format": "binary",
            "description": "Image file to compress (PNG, JPEG, or WebP)"
          },
          "quality": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100,
            "default": 80,
            "description": "Compression quality (1-100)"
          },
          "format": {
            "type": "string",
            "enum": [
              "auto",
              "jpeg",
              "png",
              "webp"
            ],
            "default": "auto",
            "description": "Output format"
          },
          "maxWidth": {
            "type": "integer",
            "minimum": 1,
            "description": "Maximum width in pixels (maintains aspect ratio)"
          },
          "maxHeight": {
            "type": "integer",
            "minimum": 1,
            "description": "Maximum height in pixels (maintains aspect ratio)"
          }
        },
        "required": [
          "file"
        ]
      },
      "CompressRequest": {
        "type": "object",
        "description": "Provide either 'image' (base64) or 'url'. If both are provided, 'url' takes priority.",
        "properties": {
          "image": {
            "type": "string",
            "description": "Base64-encoded image (with or without data URI prefix)"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Public image URL (https)"
          },
          "quality": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100,
            "default": 80,
            "description": "Compression quality (1-100)"
          },
          "format": {
            "type": "string",
            "enum": [
              "auto",
              "jpeg",
              "png",
              "webp"
            ],
            "default": "auto",
            "description": "Output format"
          },
          "maxWidth": {
            "type": "integer",
            "minimum": 1,
            "description": "Maximum width in pixels (maintains aspect ratio)"
          },
          "maxHeight": {
            "type": "integer",
            "minimum": 1,
            "description": "Maximum height in pixels (maintains aspect ratio)"
          }
        }
      },
      "UsageResponse": {
        "type": "object",
        "properties": {
          "plan": {
            "type": "string",
            "enum": [
              "free",
              "pro",
              "business"
            ],
            "description": "Current subscription tier"
          },
          "usage": {
            "type": "object",
            "properties": {
              "current": {
                "type": "integer",
                "description": "Number of requests this month"
              },
              "limit": {
                "type": "integer",
                "description": "Monthly request limit"
              },
              "resetAt": {
                "type": "string",
                "format": "date-time",
                "description": "When the monthly quota resets"
              }
            },
            "required": [
              "current",
              "limit",
              "resetAt"
            ]
          },
          "totals": {
            "type": "object",
            "properties": {
              "bytesIn": {
                "type": "integer",
                "description": "Total bytes uploaded this month"
              },
              "bytesOut": {
                "type": "integer",
                "description": "Total bytes returned this month"
              },
              "savedBytes": {
                "type": "integer",
                "description": "Total bytes saved (bytesIn - bytesOut)"
              },
              "savedPercent": {
                "type": "integer",
                "description": "Overall savings percentage"
              }
            },
            "required": [
              "bytesIn",
              "bytesOut",
              "savedBytes",
              "savedPercent"
            ]
          }
        },
        "required": [
          "plan",
          "usage",
          "totals"
        ]
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "description": "Error code"
          },
          "message": {
            "type": "string",
            "description": "Human-readable error message"
          }
        },
        "required": [
          "error",
          "message"
        ]
      },
      "RateLimitError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "example": "rate_limited"
          },
          "message": {
            "type": "string",
            "example": "Demo limit reached (5/hour). Sign up for free to get 500/month."
          },
          "resetAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the rate limit resets"
          }
        },
        "required": [
          "error",
          "message",
          "resetAt"
        ]
      }
    }
  },
  "tags": [
    {
      "name": "Health",
      "description": "API health check"
    },
    {
      "name": "Compression",
      "description": "Image compression endpoints"
    },
    {
      "name": "Usage",
      "description": "Usage statistics"
    }
  ]
}