{
  "openapi": "3.0.3",
  "info": {
    "title": "PaperClean API",
    "version": "1.0.0",
    "description": "Document image cleanup and enhancement API. PaperClean removes shadows, fixes contrast, corrects perspective, and produces clean, high-quality scans from photos of documents taken with any camera or phone.\n\nFeatures:\n- **2-pass enhancement** for superior quality (shadows removed, contrast optimized)\n- **Perspective correction** with 4-corner coordinates\n- **Configurable pipeline** (combine crop + enhance in one call)\n- **Fast processing** powered by Rust backend\n- **Multiple formats** supported: JPG, PNG, WebP, TIFF",
    "contact": {
      "email": "rvalentinkann@gmail.com"
    },
    "license": {
      "name": "Proprietary"
    }
  },
  "servers": [
    {
      "url": "https://paperclean.ip1.cc",
      "description": "Production server"
    }
  ],
  "security": [
    {
      "ApiKeyHeader": []
    }
  ],
  "paths": {
    "/api/v1/clean": {
      "post": {
        "operationId": "cleanDocument",
        "summary": "Full document cleanup",
        "description": "Applies the full PaperClean pipeline: 2-pass enhancement that removes shadows, fixes contrast and produces a clean document scan. This is the recommended endpoint for most use cases.",
        "tags": ["Processing"],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": ["image"],
                "properties": {
                  "image": {
                    "type": "string",
                    "format": "binary",
                    "description": "Document image file (JPG, PNG, WebP, or TIFF). Max 32MB."
                  },
                  "passes": {
                    "type": "string",
                    "enum": ["1", "2"],
                    "default": "2",
                    "description": "Number of enhancement passes. 2 gives best results (default), 1 is faster."
                  },
                  "scales": {
                    "type": "string",
                    "default": "4",
                    "description": "Number of scales for enhancement algorithm. Higher = more detail but slower. Range: 1-8."
                  },
                  "gamma": {
                    "type": "string",
                    "default": "1.0",
                    "description": "Gamma correction value. Lower values darken, higher values lighten. Range: 0.1-3.0."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Cleaned document image",
            "content": {
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Monthly request limit for your plan",
                "schema": { "type": "integer" }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests remaining this period",
                "schema": { "type": "integer" }
              },
              "X-RateLimit-Reset": {
                "description": "When the rate limit resets (ISO 8601)",
                "schema": { "type": "string", "format": "date-time" }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitExceeded"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/enhance": {
      "post": {
        "operationId": "enhanceDocument",
        "summary": "Single-pass enhancement",
        "description": "Applies a single enhancement pass with customizable parameters. Use this for fine-tuned control over the enhancement process. Supports custom scales, gamma, and input level adjustments.",
        "tags": ["Processing"],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": ["image"],
                "properties": {
                  "image": {
                    "type": "string",
                    "format": "binary",
                    "description": "Document image file (JPG, PNG, WebP, or TIFF). Max 32MB."
                  },
                  "scales": {
                    "type": "string",
                    "default": "4",
                    "description": "Number of scales for enhancement. Range: 1-8."
                  },
                  "gamma": {
                    "type": "string",
                    "default": "1.0",
                    "description": "Gamma correction. Range: 0.1-3.0."
                  },
                  "low_input": {
                    "type": "string",
                    "description": "Low input level for contrast adjustment (0-255). Pixels below this become black."
                  },
                  "high_input": {
                    "type": "string",
                    "description": "High input level for contrast adjustment (0-255). Pixels above this become white."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Enhanced document image",
            "content": {
              "image/jpeg": {
                "schema": { "type": "string", "format": "binary" }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "429": { "$ref": "#/components/responses/RateLimitExceeded" },
          "500": { "$ref": "#/components/responses/InternalError" }
        }
      }
    },
    "/api/v1/crop": {
      "post": {
        "operationId": "cropDocument",
        "summary": "Perspective correction",
        "description": "Corrects perspective distortion using 4-corner coordinates. Provide the coordinates of the document corners as fractions (0-1) relative to image dimensions. The image will be transformed to a flat, rectangular view.",
        "tags": ["Processing"],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": ["image", "tl_x", "tl_y", "tr_x", "tr_y", "br_x", "br_y", "bl_x", "bl_y"],
                "properties": {
                  "image": {
                    "type": "string",
                    "format": "binary",
                    "description": "Document image file (JPG, PNG, WebP, or TIFF). Max 32MB."
                  },
                  "tl_x": {
                    "type": "string",
                    "description": "Top-left corner X coordinate (fraction 0-1)"
                  },
                  "tl_y": {
                    "type": "string",
                    "description": "Top-left corner Y coordinate (fraction 0-1)"
                  },
                  "tr_x": {
                    "type": "string",
                    "description": "Top-right corner X coordinate (fraction 0-1)"
                  },
                  "tr_y": {
                    "type": "string",
                    "description": "Top-right corner Y coordinate (fraction 0-1)"
                  },
                  "br_x": {
                    "type": "string",
                    "description": "Bottom-right corner X coordinate (fraction 0-1)"
                  },
                  "br_y": {
                    "type": "string",
                    "description": "Bottom-right corner Y coordinate (fraction 0-1)"
                  },
                  "bl_x": {
                    "type": "string",
                    "description": "Bottom-left corner X coordinate (fraction 0-1)"
                  },
                  "bl_y": {
                    "type": "string",
                    "description": "Bottom-left corner Y coordinate (fraction 0-1)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Cropped and perspective-corrected image",
            "content": {
              "image/jpeg": {
                "schema": { "type": "string", "format": "binary" }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "429": { "$ref": "#/components/responses/RateLimitExceeded" },
          "500": { "$ref": "#/components/responses/InternalError" }
        }
      }
    },
    "/api/v1/pipeline": {
      "post": {
        "operationId": "pipelineDocument",
        "summary": "Configurable pipeline",
        "description": "Combines crop and enhance in a single call. The pipeline first applies perspective correction (if coordinates are provided), then enhancement. Use passes=0 to skip enhancement and only crop.",
        "tags": ["Processing"],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": ["image"],
                "properties": {
                  "image": {
                    "type": "string",
                    "format": "binary",
                    "description": "Document image file (JPG, PNG, WebP, or TIFF). Max 32MB."
                  },
                  "tl_x": {
                    "type": "string",
                    "description": "Top-left corner X (fraction 0-1). Optional: omit all coordinates to skip crop."
                  },
                  "tl_y": { "type": "string", "description": "Top-left corner Y (fraction 0-1)" },
                  "tr_x": { "type": "string", "description": "Top-right corner X (fraction 0-1)" },
                  "tr_y": { "type": "string", "description": "Top-right corner Y (fraction 0-1)" },
                  "br_x": { "type": "string", "description": "Bottom-right corner X (fraction 0-1)" },
                  "br_y": { "type": "string", "description": "Bottom-right corner Y (fraction 0-1)" },
                  "bl_x": { "type": "string", "description": "Bottom-left corner X (fraction 0-1)" },
                  "bl_y": { "type": "string", "description": "Bottom-left corner Y (fraction 0-1)" },
                  "passes": {
                    "type": "string",
                    "enum": ["0", "1", "2"],
                    "default": "2",
                    "description": "Enhancement passes: 0 = crop only, 1 = single pass, 2 = full quality (default)"
                  },
                  "scales": {
                    "type": "string",
                    "default": "4",
                    "description": "Enhancement scales (1-8)"
                  },
                  "gamma": {
                    "type": "string",
                    "default": "1.0",
                    "description": "Gamma correction (0.1-3.0)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Processed document image",
            "content": {
              "image/jpeg": {
                "schema": { "type": "string", "format": "binary" }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "429": { "$ref": "#/components/responses/RateLimitExceeded" },
          "500": { "$ref": "#/components/responses/InternalError" }
        }
      }
    },
    "/api/v1/usage": {
      "get": {
        "operationId": "getUsage",
        "summary": "Check usage and limits",
        "description": "Returns your current plan, usage count, remaining requests, and period end date.",
        "tags": ["Account"],
        "responses": {
          "200": {
            "description": "Usage information",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "plan": {
                          "type": "string",
                          "enum": ["free", "starter", "pro", "enterprise"],
                          "description": "Current subscription plan"
                        },
                        "limit": {
                          "type": "integer",
                          "description": "Monthly request limit"
                        },
                        "used": {
                          "type": "integer",
                          "description": "Requests used this period"
                        },
                        "remaining": {
                          "type": "integer",
                          "description": "Requests remaining this period"
                        },
                        "period_end": {
                          "type": "string",
                          "format": "date-time",
                          "description": "When the current billing period ends"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": {
                    "plan": "free",
                    "limit": 50,
                    "used": 12,
                    "remaining": 38,
                    "period_end": "2026-04-28T00:00:00Z"
                  }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/api/v1/register": {
      "post": {
        "operationId": "registerKey",
        "summary": "Register for a free API key",
        "description": "Self-service registration. Provide your email to get a free API key with 50 images/month. If a key already exists for the email, it returns the existing key.",
        "tags": ["Account"],
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["email"],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email",
                    "description": "Your email address"
                  }
                }
              },
              "example": {
                "email": "developer@example.com"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "API key created or retrieved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "api_key": { "type": "string", "description": "Your API key (starts with pc_)" },
                        "email": { "type": "string" },
                        "plan": { "type": "string" },
                        "limit": { "type": "integer" },
                        "message": { "type": "string" }
                      }
                    }
                  }
                },
                "example": {
                  "data": {
                    "api_key": "pc_a1b2c3d4e5f6g7h8",
                    "email": "developer@example.com",
                    "plan": "free",
                    "limit": 50,
                    "message": "API key created! You have 50 free images per month."
                  }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" }
        }
      }
    },
    "/api/health": {
      "get": {
        "operationId": "healthCheck",
        "summary": "Health check",
        "description": "Returns API health status and system checks.",
        "tags": ["System"],
        "security": [],
        "responses": {
          "200": {
            "description": "Health status",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": { "type": "string", "enum": ["ok", "degraded"] },
                    "timestamp": { "type": "string", "format": "date-time" },
                    "checks": {
                      "type": "object",
                      "properties": {
                        "paperclean_binary": { "type": "string" },
                        "api_keys_loaded": { "type": "string" }
                      }
                    }
                  }
                },
                "example": {
                  "status": "ok",
                  "timestamp": "2026-03-28T12:00:00-04:00",
                  "checks": {
                    "paperclean_binary": "ok",
                    "api_keys_loaded": "2"
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyHeader": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "API key obtained via /api/v1/register or the developer portal. Also supports X-RapidAPI-Key header."
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Bad request - missing or invalid parameters",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "error": { "type": "string" }
              }
            },
            "example": {
              "error": "Missing coordinate: tl_x. Provide all 4 corners (tl, tr, br, bl) as fractions 0-1."
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Invalid or missing API key",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "error": { "type": "string" }
              }
            },
            "example": {
              "error": "Invalid API key."
            }
          }
        }
      },
      "RateLimitExceeded": {
        "description": "Monthly rate limit exceeded",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "error": { "type": "string" }
              }
            },
            "example": {
              "error": "Rate limit exceeded. Upgrade your plan for more requests."
            }
          }
        },
        "headers": {
          "X-RateLimit-Limit": {
            "description": "Monthly request limit",
            "schema": { "type": "integer" }
          },
          "X-RateLimit-Remaining": {
            "description": "Always 0 when rate limited",
            "schema": { "type": "integer" }
          },
          "X-RateLimit-Reset": {
            "description": "When the rate limit resets",
            "schema": { "type": "string", "format": "date-time" }
          }
        }
      },
      "InternalError": {
        "description": "Processing error",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "error": { "type": "string" }
              }
            },
            "example": {
              "error": "Enhancement error: paperclean binary failed"
            }
          }
        }
      }
    }
  },
  "tags": [
    {
      "name": "Processing",
      "description": "Document image processing endpoints"
    },
    {
      "name": "Account",
      "description": "API key management and usage tracking"
    },
    {
      "name": "System",
      "description": "System health and monitoring"
    }
  ]
}
