openapi: 3.1.0
info:
  title: Easy Image Edit API
  version: 1.0.0
  description: |
    REST API for Easy Image Edit image-processing endpoints.

    **Security Requirements:**
    - All endpoints MUST be accessed over HTTPS (TLS 1.2 or higher)
    - HTTP connections are not supported and will be rejected

    **Authentication Options:**
    - **Bearer JWT**: Use the OAuth2 service to obtain a JWT access token and pass it as
      `Authorization: Bearer <token>`

    **Common Response Pattern:**
    - Success responses include JSON payloads
    - Error responses are JSON with `{ "error": "<code or message>" }`
  contact:
    name: AIO Tech Consulting
    url: https://aiotechconsulting.com
    email: contact@aiotechconsulting.com
  termsOfService: https://easyimgedit.com/terms
servers:
  - url: https://api.easyimgedit.com
    description: Production server (HTTPS only)
security:
  - bearerAuth: []
paths:
  /api/colorize:
    post:
      summary: Colorize a black-and-white image
      description: |
        Colorizes a black-and-white image and returns a PNG data URI.

        Requires `colorize` scope.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ColorizeDataRequest"
            example:
              imageData: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...
      responses:
        "200":
          description: Colorized image data URI
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ImageDataResponse"
              example:
                imageData: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...
        "400":
          description: Invalid or missing image data
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: Invalid base64 image data
        "401":
          description: Missing or invalid authorization
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: missing_authorization
        "403":
          description: Insufficient scope
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: insufficient_scope
        "429":
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: rate_limit_exceeded
        "500":
          description: Unexpected server error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: internal_error
  /api/remove-background:
    post:
      summary: Remove image background
      description: |
        Removes background and returns a PNG data URI with transparency.

        Requires `remove_background` scope.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/RemoveDataRequest"
            example:
              imageData: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...
      responses:
        "200":
          description: Image with background removed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ImageDataResponse"
              example:
                imageData: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...
        "400":
          description: Invalid or missing image data
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: Missing image data
        "401":
          description: Missing or invalid authorization
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: missing_authorization
        "403":
          description: Insufficient scope
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: insufficient_scope
        "429":
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: rate_limit_exceeded
        "500":
          description: Unexpected server error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: internal_error
  /api/replace-background:
    post:
      summary: Replace image background with a solid color
      description: |
        Removes the image background and composites the subject over a provided hex color.

        Requires `replace_background` scope.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ReplaceBackgroundRequest"
            example:
              imageData: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...
              color: "#00AEEF"
          multipart/form-data:
            schema:
              type: object
              required:
                - image
                - color
              properties:
                image:
                  type: string
                  format: binary
                color:
                  type: string
                  description: Hex color in `#RGB` or `#RRGGBB` format.
      responses:
        "200":
          description: Image with replaced background
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ImageDataResponse"
              example:
                imageData: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...
        "400":
          description: Invalid or missing image/color payload
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: Invalid color. Use hex format like #FFAA00
        "401":
          description: Missing or invalid authorization
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: missing_authorization
        "403":
          description: Insufficient scope
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: insufficient_scope
        "429":
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: rate_limit_exceeded
        "500":
          description: Unexpected server error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: internal_error
  /api/convert-image:
    post:
      summary: Convert image format
      description: |
        Converts an image to PNG, JPG, WEBP, or SVG.

        Requires `convert` scope.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ConvertImageRequest"
            example:
              imageData: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...
              outputFormat: png
      responses:
        "200":
          description: Converted image data URI
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ImageDataResponse"
              example:
                imageData: data:image/webp;base64,UklGRiIAAABXRUJQVlA4...
        "400":
          description: Invalid input or unsupported format
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: Unsupported output format
        "401":
          description: Missing or invalid authorization
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: missing_authorization
        "403":
          description: Insufficient scope
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: insufficient_scope
        "429":
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: rate_limit_exceeded
        "500":
          description: Unexpected server error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: internal_error
  /api/crop-image:
    post:
      summary: Crop image
      description: |
        Crops an image to the specified rectangle and returns a data URI.

        Requires `crop` scope.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CropImageRequest"
            example:
              imageData: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...
              left: 40
              top: 20
              width: 400
              height: 300
              outputFormat: webp
      responses:
        "200":
          description: Cropped image data URI
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ImageDataResponse"
              example:
                imageData: data:image/webp;base64,UklGRiIAAABXRUJQVlA4...
        "400":
          description: Invalid input
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: Missing crop size
        "401":
          description: Missing or invalid authorization
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: missing_authorization
        "403":
          description: Insufficient scope
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: insufficient_scope
        "429":
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: rate_limit_exceeded
        "500":
          description: Unexpected server error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: internal_error
  /api/compress-image:
    post:
      summary: Compress image
      description: |
        Compresses PNG, JPG, WEBP, or SVG uploads and returns a data URI.

        Requires `compress` scope.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CompressImageRequest"
            example:
              imageData: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...
              quality_level: "1"
      responses:
        "200":
          description: Compressed image data URI
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ImageDataResponse"
              example:
                imageData: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...
        "400":
          description: Invalid input or unsupported format
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: Unsupported image format.
        "401":
          description: Missing or invalid authorization
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: missing_authorization
        "403":
          description: Insufficient scope
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: insufficient_scope
        "429":
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: rate_limit_exceeded
        "500":
          description: Unexpected server error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: internal_error
  /api/watermark:
    post:
      summary: Add text watermark
      description: |
        Applies a text watermark to an image and returns a data URI in the original image format.

        Requires `watermark` scope.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/WatermarkRequest"
            example:
              imageData: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...
              text: "© Easy Image Edit"
              fontSize: 36
              opacity: 0.35
              color: "#ffffff"
              position: bottom-right
      responses:
        "200":
          description: Watermarked image data URI
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ImageDataResponse"
              example:
                imageData: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...
        "400":
          description: Invalid input
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: Missing watermark text
        "401":
          description: Missing or invalid authorization
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: missing_authorization
        "403":
          description: Insufficient scope
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: insufficient_scope
        "429":
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: rate_limit_exceeded
        "500":
          description: Unexpected server error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: internal_error
  /api/upscale-image:
    post:
      summary: Upscale image
      description: |
        Upscales an image by 2x or 4x and returns a data URI in the original image format.

        Requires `upscale` scope.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpscaleRequest"
            example:
              imageData: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...
              scale: 2
      responses:
        "200":
          description: Upscaled image data URI
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UpscaleResponse"
              example:
                imageData: data:image/jpeg;base64,/9j/4AAQSkZJRgABA...
                width: 2048
                height: 1536
                scale: 2
        "400":
          description: Invalid input
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: Scale must be 2x or 4x
        "401":
          description: Missing or invalid authorization
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: missing_authorization
        "403":
          description: Insufficient scope
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: insufficient_scope
        "429":
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: rate_limit_exceeded
        "500":
          description: Unexpected server error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error: internal_error
components:
  securitySchemes:
    bearerAuth:
      flows:
        clientCredentials:
          tokenUrl: https://api.easyimgedit.com/oauth/token
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: |
        JWT access token obtained from /oauth/token endpoint.

        Include in requests as: `Authorization: Bearer <token>`

        Token payload includes: iss, aud, sub, iat, nbf, exp, scope
  schemas:
    ErrorResponse:
      type: object
      required:
        - error
      properties:
        error:
          type: string
          examples:
            - missing_authorization
            - insufficient_scope
            - rate_limit_exceeded
            - internal
    ImageDataRequest:
      type: object
      required:
        - imageData
      properties:
        imageData:
          type: string
          format: data:image/<format>;base64,<base64-string>
          description: |
            Base64 image data URI
            Supported formats: PNG, JPEG/JPG, WEBP, BMP, TIFF
          examples:
            - data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...
    ImageDataResponse:
      type: object
      required:
        - imageData
      properties:
        imageData:
          type: string
          format: data:image/<format>;base64,<base64-string>
          description: |
            Base64 image data URI
            Supported formats: PNG, JPEG/JPG, WEBP, SVG
          examples:
            - data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...
    ColorizeDataRequest:
      type: object
      required:
        - imageData
      properties:
        imageData:
          type: string
          format: data:image/<format>;base64,<base64-string>
          description: |
            Base64 image data URI
            Supported formats: PNG, JPEG/JPG, WEBP, BMP
          examples:
            - data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...
    RemoveDataRequest:
      type: object
      required:
        - imageData
      properties:
        imageData:
          type: string
          format: data:image/<format>;base64,<base64-string>
          description: |
            Base64 image data URI
            Supported formats: PNG, JPEG/JPG, WEBP, BMP
          examples:
            - data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...
    ReplaceBackgroundRequest:
      type: object
      required:
        - imageData
        - color
      properties:
        imageData:
          type: string
          format: data:image/<format>;base64,<base64-string>
          description: |
            Base64 image data URI
            Supported formats: PNG, JPEG/JPG, WEBP, BMP, GIF, ICO
          examples:
            - data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...
        color:
          type: string
          description: Hex color in `#RGB` or `#RRGGBB` format.
          examples:
            - "#00AEEF"
    ConvertImageRequest:
      type: object
      required:
        - imageData
        - outputFormat
      properties:
        imageData:
          type: string
          format: data:image/<format>;base64,<base64-string>
          description: |
            Base64 image data URI
            Supported formats: PNG, JPEG/JPG, WEBP, BMP, TIFF, ICO
          examples:
            - data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...
        outputFormat:
          type: string
          default: png
          enum:
            - png
            - jpg
            - jpeg
            - webp
            - svg
          description: Desired output format
    CropImageRequest:
      type: object
      required:
        - imageData
        - left
        - top
        - width
        - height
      properties:
        imageData:
          type: string
          format: data:image/<format>;base64,<base64-string>
          description: |
            Base64 image data URI
            Supported formats: PNG, JPEG/JPG, WEBP, BMP, GIF
          examples:
            - data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...
        left:
          type: number
          description: Left offset in pixels
          examples:
            - 40
        top:
          type: number
          description: Top offset in pixels
          examples:
            - 20
        width:
          type: number
          description: Crop width in pixels
          examples:
            - 400
        height:
          type: number
          description: Crop height in pixels
          examples:
            - 300
        outputFormat:
          type: string
          description: Optional output format (defaults to input format)
          enum:
            - png
            - jpg
            - jpeg
            - webp
            - bmp
            - gif
    CompressImageRequest:
      type: object
      required:
        - imageData
      properties:
        imageData:
          type: string
          format: data:image/<format>;base64,<base64-string>
          description: |
            Base64 image data URI
            Supported formats: PNG, JPEG/JPG, WEBP, SVG
          examples:
            - data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...
        quality_level:
          type: integer
          description: "Compression quality level: 0 = High (lossless when possible), 1 = Balanced, 2 = Smallest file"
          examples:
            - 0
            - 1
            - 2
    WatermarkRequest:
      type: object
      required:
        - imageData
        - text
      properties:
        imageData:
          type: string
          format: data:image/<format>;base64,<base64-string>
          description: |
            Base64 image data URI
            Supported formats: PNG, JPEG/JPG, WEBP, BMP, GIF
          examples:
            - data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...
        text:
          type: string
          description: Watermark text to render
          examples:
            - "© Easy Image Edit"
        fontSize:
          type: integer
          description: Font size in pixels
          examples:
            - 12
        opacity:
          type: number
          description: Opacity from 0 to 1
          examples:
            - 0.35
        color:
          type: string
          description: Hex color for text
          examples:
            - "#ffffff"
        position:
          type: string
          description: Placement of the watermark
          enum:
            - top-left
            - top-right
            - bottom-left
            - bottom-right
            - center
            - oblique
    UpscaleRequest:
      type: object
      required:
        - imageData
        - scale
      properties:
        imageData:
          type: string
          format: data:image/<format>;base64,<base64-string>
          description: |
            Base64 image data URI
            Supported formats: PNG, JPEG/JPG, WEBP, BMP, GIF
          examples:
            - data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...
        scale:
          type: integer
          enum:
            - 2
            - 4
          description: Upscale factor (2 or 4)
    UpscaleResponse:
      type: object
      required:
        - imageData
        - width
        - height
        - scale
      properties:
        imageData:
          type: string
          format: data:image/<format>;base64,<base64-string>
          description: |
            Base64 image data URI
            Supported formats: PNG, JPEG/JPG, WEBP, BMP, GIF
          examples:
            - data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...
        width:
          type: integer
        height:
          type: integer
        scale:
          type: integer
