openapi: 3.1.0 info: title: ashim API version: 0.9.0 description: | REST API for ashim, a self-hosted image processing platform with 30+ tools. ## Authentication Most endpoints require authentication via one of two methods: 1. **Session cookie** — Call `POST /api/auth/login` with username and password. The response includes a `token` field. Pass it as `Authorization: Bearer ` on subsequent requests. 2. **API key** — Generate a key via the Settings UI or `POST /api/v1/api-keys`. Keys are prefixed with `si_`. Pass as `Authorization: Bearer si_...`. Endpoints marked with a lock icon require authentication. Admin-only endpoints are noted in their description. license: name: AGPL-3.0 url: https://github.com/ashim-hq/ashim/blob/main/LICENSE servers: - url: / description: Current instance tags: - name: Tools description: Image processing tools. Each accepts a multipart file upload and returns a download URL. - name: Batch description: Process multiple images through a tool in one request. - name: Pipelines description: Chain multiple tools into reusable workflows. - name: Files description: Upload, download, and manage processed images. - name: Auth description: Login, logout, session management, and user administration. - name: API Keys description: Create and manage API keys for programmatic access. - name: Settings description: System-wide configuration (admin only for writes). - name: Teams description: Organize users into teams. - name: Branding description: Custom logo management. - name: System description: Health checks, configuration, and job progress. components: securitySchemes: bearerAuth: type: http scheme: bearer description: Session token from login or API key (prefixed with si_) schemas: Error: type: object properties: statusCode: type: integer example: 400 error: type: string example: Bad Request message: type: string example: Invalid image format ToolResponse: type: object properties: jobId: type: string description: Unique job identifier downloadUrl: type: string description: URL to download the processed image example: /api/v1/download/abc123/output.png originalSize: type: integer description: Original file size in bytes processedSize: type: integer description: Processed file size in bytes HealthResponse: type: object properties: status: type: string enum: [healthy, degraded] version: type: string uptime: type: string database: type: string enum: [ok, error] security: - bearerAuth: [] paths: /api/v1/health: get: tags: [System] summary: Health check description: Returns server health status. Used by Docker HEALTHCHECK. Public endpoint. security: [] responses: "200": description: Server health content: application/json: schema: $ref: "#/components/schemas/HealthResponse" /api/v1/tools/resize: post: tags: [Tools] summary: Resize description: Resize an image to specific dimensions or by percentage. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file, settings] properties: file: type: string format: binary description: Image file to process settings: type: string description: | JSON string with options: - `width` (number, optional) — Target width in pixels - `height` (number, optional) — Target height in pixels - `fit` (string, default "contain") — One of: contain, cover, fill, inside, outside - `withoutEnlargement` (boolean, default false) — Prevent upscaling - `percentage` (number, optional) — Scale by percentage instead of fixed dimensions responses: "200": description: Processed image content: application/json: schema: $ref: "#/components/schemas/ToolResponse" "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/content-aware-resize: post: tags: [Tools] summary: Content-aware resize description: Resize an image using seam carving to intelligently remove or insert content while preserving important features. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file] properties: file: type: string format: binary description: Image file to process settings: type: string description: | JSON string with options: - `width` (number, optional) — Target width in pixels - `height` (number, optional) — Target height in pixels - `protectFaces` (boolean, default false) — Detect and protect faces from distortion - `blurRadius` (number 0-20, default 4) — Blur radius for energy map - `sobelThreshold` (number 1-20, default 2) — Edge detection threshold - `square` (boolean, default false) — Crop to square aspect ratio At least one of `width`, `height`, or `square` must be provided. responses: "200": description: Processed image content: application/json: schema: allOf: - $ref: "#/components/schemas/ToolResponse" - type: object properties: width: type: integer height: type: integer "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/crop: post: tags: [Tools] summary: Crop description: Crop an image to a specific region. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file, settings] properties: file: type: string format: binary description: Image file to process settings: type: string description: | JSON string with options: - `left` (integer, required) — Left offset in pixels - `top` (integer, required) — Top offset in pixels - `width` (integer, required) — Width of crop region in pixels - `height` (integer, required) — Height of crop region in pixels responses: "200": description: Processed image content: application/json: schema: $ref: "#/components/schemas/ToolResponse" "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/rotate: post: tags: [Tools] summary: Rotate and flip description: Rotate an image by angle or flip horizontally/vertically. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file, settings] properties: file: type: string format: binary description: Image file to process settings: type: string description: | JSON string with options: - `angle` (number, default 0) — Rotation angle in degrees - `horizontal` (boolean, default false) — Flip horizontally - `vertical` (boolean, default false) — Flip vertically responses: "200": description: Processed image content: application/json: schema: $ref: "#/components/schemas/ToolResponse" "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/convert: post: tags: [Tools] summary: Convert format description: Convert an image to a different format. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file, settings] properties: file: type: string format: binary description: Image file to process settings: type: string description: | JSON string with options: - `format` (string, required) — One of: jpg, png, webp, avif, tiff, gif, heic - `quality` (number 1-100, optional) — Output quality responses: "200": description: Processed image content: application/json: schema: $ref: "#/components/schemas/ToolResponse" "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/compress: post: tags: [Tools] summary: Compress description: Reduce image file size by quality level or target size. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file, settings] properties: file: type: string format: binary description: Image file to process settings: type: string description: | JSON string with options: - `mode` (string, default "quality") — One of: quality, targetSize - `quality` (number 1-100, optional) — Compression quality level - `targetSizeKb` (number, optional) — Target file size in kilobytes responses: "200": description: Processed image content: application/json: schema: $ref: "#/components/schemas/ToolResponse" "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/strip-metadata: post: tags: [Tools] summary: Strip metadata description: Remove EXIF, GPS, ICC, or XMP metadata from an image. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file, settings] properties: file: type: string format: binary description: Image file to process settings: type: string description: | JSON string with options: - `stripExif` (boolean, default false) — Remove EXIF data - `stripGps` (boolean, default false) — Remove GPS data - `stripIcc` (boolean, default false) — Remove ICC profile - `stripXmp` (boolean, default false) — Remove XMP data - `stripAll` (boolean, default true) — Remove all metadata responses: "200": description: Processed image content: application/json: schema: $ref: "#/components/schemas/ToolResponse" "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/border: post: tags: [Tools] summary: Border and frame description: Add a border, rounded corners, padding, or shadow to an image. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file, settings] properties: file: type: string format: binary description: Image file to process settings: type: string description: | JSON string with options: - `borderWidth` (number 0-200, default 10) — Border thickness in pixels - `borderColor` (hex string, default "#000000") — Border color - `cornerRadius` (number 0-500, default 0) — Corner rounding radius - `padding` (number 0-200, default 0) — Inner padding in pixels - `shadowBlur` (number 0-50, default 0) — Drop shadow blur radius - `shadowColor` (hex string, default "#00000080") — Drop shadow color responses: "200": description: Processed image content: application/json: schema: $ref: "#/components/schemas/ToolResponse" "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/brightness-contrast: post: tags: [Tools] summary: Brightness and contrast description: Adjust brightness, contrast, saturation, color channels, and effects. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file, settings] properties: file: type: string format: binary description: Image file to process settings: type: string description: | JSON string with options: - `brightness` (number -100 to 100, default 0) — Brightness adjustment - `contrast` (number -100 to 100, default 0) — Contrast adjustment - `saturation` (number -100 to 100, default 0) — Saturation adjustment - `red` (number 0-200, default 100) — Red channel multiplier - `green` (number 0-200, default 100) — Green channel multiplier - `blue` (number 0-200, default 100) — Blue channel multiplier - `effect` (string, default "none") — One of: none, grayscale, sepia, invert responses: "200": description: Processed image content: application/json: schema: $ref: "#/components/schemas/ToolResponse" "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/saturation: post: tags: [Tools] summary: Saturation and exposure description: Adjust color saturation and exposure settings. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file, settings] properties: file: type: string format: binary description: Image file to process settings: type: string description: | JSON string with options: - `brightness` (number -100 to 100, default 0) — Brightness adjustment - `contrast` (number -100 to 100, default 0) — Contrast adjustment - `saturation` (number -100 to 100, default 0) — Saturation adjustment - `red` (number 0-200, default 100) — Red channel multiplier - `green` (number 0-200, default 100) — Green channel multiplier - `blue` (number 0-200, default 100) — Blue channel multiplier - `effect` (string, default "none") — One of: none, grayscale, sepia, invert responses: "200": description: Processed image content: application/json: schema: $ref: "#/components/schemas/ToolResponse" "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/color-channels: post: tags: [Tools] summary: Color channels description: Adjust individual RGB color channels. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file, settings] properties: file: type: string format: binary description: Image file to process settings: type: string description: | JSON string with options: - `brightness` (number -100 to 100, default 0) — Brightness adjustment - `contrast` (number -100 to 100, default 0) — Contrast adjustment - `saturation` (number -100 to 100, default 0) — Saturation adjustment - `red` (number 0-200, default 100) — Red channel multiplier - `green` (number 0-200, default 100) — Green channel multiplier - `blue` (number 0-200, default 100) — Blue channel multiplier - `effect` (string, default "none") — One of: none, grayscale, sepia, invert responses: "200": description: Processed image content: application/json: schema: $ref: "#/components/schemas/ToolResponse" "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/color-effects: post: tags: [Tools] summary: Color effects description: Apply color effects like grayscale, sepia, or invert. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file, settings] properties: file: type: string format: binary description: Image file to process settings: type: string description: | JSON string with options: - `brightness` (number -100 to 100, default 0) — Brightness adjustment - `contrast` (number -100 to 100, default 0) — Contrast adjustment - `saturation` (number -100 to 100, default 0) — Saturation adjustment - `red` (number 0-200, default 100) — Red channel multiplier - `green` (number 0-200, default 100) — Green channel multiplier - `blue` (number 0-200, default 100) — Blue channel multiplier - `effect` (string, default "none") — One of: none, grayscale, sepia, invert responses: "200": description: Processed image content: application/json: schema: $ref: "#/components/schemas/ToolResponse" "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/watermark-text: post: tags: [Tools] summary: Text watermark description: Add a text watermark to an image. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file, settings] properties: file: type: string format: binary description: Image file to process settings: type: string description: | JSON string with options: - `text` (string 1-500, required) — Watermark text - `fontSize` (number 8-200, default 48) — Font size in pixels - `color` (hex string, default "#000000") — Text color - `opacity` (number 0-100, default 50) — Opacity percentage - `position` (string, default "center") — One of: center, top-left, top-right, bottom-left, bottom-right, tiled - `rotation` (number -360 to 360, default 0) — Text rotation angle responses: "200": description: Processed image content: application/json: schema: $ref: "#/components/schemas/ToolResponse" "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/text-overlay: post: tags: [Tools] summary: Text overlay description: Add styled text overlay with optional background box. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file, settings] properties: file: type: string format: binary description: Image file to process settings: type: string description: | JSON string with options: - `text` (string 1-500, required) — Overlay text - `fontSize` (number 8-200, default 48) — Font size in pixels - `color` (hex string, default "#FFFFFF") — Text color - `position` (string, default "bottom") — One of: top, center, bottom - `backgroundBox` (boolean, default false) — Show background box behind text - `backgroundColor` (hex string, default "#000000") — Background box color - `shadow` (boolean, default true) — Add text shadow responses: "200": description: Processed image content: application/json: schema: $ref: "#/components/schemas/ToolResponse" "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/replace-color: post: tags: [Tools] summary: Replace color description: Replace a specific color in an image with another color or transparency. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file, settings] properties: file: type: string format: binary description: Image file to process settings: type: string description: | JSON string with options: - `sourceColor` (hex string, default "#FF0000") — Color to replace - `targetColor` (hex string, default "#00FF00") — Replacement color - `makeTransparent` (boolean, default false) — Make matched pixels transparent instead - `tolerance` (number 0-255, default 30) — Color matching tolerance responses: "200": description: Processed image content: application/json: schema: $ref: "#/components/schemas/ToolResponse" "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/gif-tools: post: tags: [Tools] summary: GIF tools description: Resize, extract frames from, or optimize animated GIFs. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file, settings] properties: file: type: string format: binary description: GIF file to process settings: type: string description: | JSON string with options: - `width` (number 1-4096, optional) — Target width in pixels - `height` (number 1-4096, optional) — Target height in pixels - `extractFrame` (number, optional) — Extract specific frame index - `optimize` (boolean, default false) — Optimize GIF file size responses: "200": description: Processed image content: application/json: schema: $ref: "#/components/schemas/ToolResponse" "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/gif-tools/info: post: tags: [Tools] summary: GIF info description: Get metadata about an animated GIF including dimensions, frame count, delays, and duration. security: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file] properties: file: type: string format: binary description: GIF file to inspect responses: "200": description: GIF metadata content: application/json: schema: type: object properties: width: type: integer height: type: integer pages: type: integer description: Number of frames delay: type: array items: type: integer description: Per-frame delay in milliseconds loop: type: integer description: Loop count (0 = infinite) fileSize: type: integer duration: type: integer description: Total duration in milliseconds "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" /api/v1/tools/smart-crop: post: tags: [Tools] summary: Smart crop description: Smart crop with three modes - subject focus, face focus, or auto trim. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file, settings] properties: file: type: string format: binary description: Image file to process settings: type: string description: | JSON string with options: - `mode` (string) — "subject" (default), "face", or "trim" - `strategy` (string) — "attention" (default) or "entropy" (subject mode) - `width` (integer) — Target width in pixels (default 1080) - `height` (integer) — Target height in pixels (default 1080) - `padding` (integer 0-50) — Padding percentage around focus area - `facePreset` (string) — "closeup", "head-shoulders", "upper-body", "half-body" (face mode) - `sensitivity` (number 0-1) — Face detection sensitivity (face mode) - `threshold` (integer 0-255) — Trim tolerance (trim mode) - `padToSquare` (boolean) — Pad to square after trimming (trim mode) - `padColor` (string) — Hex color for padding (trim mode) - `targetSize` (integer) — Target size for padded output (trim mode) - `quality` (integer 1-100) — Output quality responses: "200": description: Processed image content: application/json: schema: $ref: "#/components/schemas/ToolResponse" "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/vectorize: post: tags: [Tools] summary: Image to SVG description: Convert a raster image to SVG vector format using potrace (B&W) or VTracer (color). security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file, settings] properties: file: type: string format: binary description: Image file to process settings: type: string description: | JSON string with options: - `colorMode` (string, default "bw") - One of: bw, color - `threshold` (number 0-255, default 128) - B&W binarization threshold - `colorPrecision` (number 1-8, default 6) - Color bits per channel - `layerDifference` (number 1-64, default 6) - Color gradient step - `filterSpeckle` (number 1-128, default 4) - Noise filter size - `pathMode` (string, default "spline") - One of: none, polygon, spline - `cornerThreshold` (number 0-180, default 60) - Corner detection angle - `invert` (boolean, default false) - Invert colors before tracing responses: "200": description: Processed image (downloadUrl points to .svg file) content: application/json: schema: $ref: "#/components/schemas/ToolResponse" "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/svg-to-raster: post: tags: [Tools] summary: SVG to raster description: Convert an SVG file to a raster image format at custom scale and DPI. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file, settings] properties: file: type: string format: binary description: SVG file to convert settings: type: string description: | JSON string with options: - `width` (number 1-16384, optional) — Output width in pixels - `height` (number 1-16384, optional) — Output height in pixels - `dpi` (number 36-1200, default 300) — Render density for SVG rasterization - `quality` (number 1-100, default 90) — Output quality for lossy formats - `backgroundColor` (hex string, default "#00000000") — Background color - `outputFormat` (string, default "png") — One of: png, jpg, webp, avif, tiff, gif, heif responses: "200": description: Processed image content: application/json: schema: $ref: "#/components/schemas/ToolResponse" "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/svg-to-raster/batch: post: tags: [Tools] summary: SVG to raster (batch) description: Convert multiple SVG files to raster images. Returns a ZIP archive. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file, settings] properties: file: type: array items: type: string format: binary description: SVG files to convert settings: type: string description: Same settings as single-file endpoint clientJobId: type: string description: Optional client-generated job ID for progress tracking responses: "200": description: ZIP archive containing processed images content: application/zip: schema: type: string format: binary "400": description: Invalid input "401": description: Authentication required "422": description: All files failed processing /api/v1/tools/image-to-pdf: post: tags: [Tools] summary: Image to PDF description: Convert one or more images into a PDF document. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file, settings] properties: file: type: array items: type: string format: binary description: One or more image files to include in the PDF settings: type: string description: | JSON string with options: - `pageSize` (string, default "A4") — One of: A4, Letter, A3, A5 - `orientation` (string, default "portrait") — One of: portrait, landscape - `margin` (number 0-100, default 20) — Page margin in points responses: "200": description: Generated PDF (downloadUrl points to .pdf file) content: application/json: schema: $ref: "#/components/schemas/ToolResponse" "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/pdf-to-image: post: tags: [Tools] summary: PDF to image description: Convert PDF pages to images. Returns individual page downloads and a ZIP of all pages. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file] properties: file: type: string format: binary description: PDF file to convert settings: type: string description: | JSON string with options: - `format` (string, default "png") — Output format: png, jpg, webp, avif, tiff, gif, heic, heif - `dpi` (number 36-1200, default 150) — Resolution in dots per inch - `quality` (number 1-100, default 85) — Output quality - `colorMode` (string, default "color") — One of: color, grayscale, bw - `pages` (string, default "all") — Page selection, e.g. "all", "1-3", "1,3,5" responses: "200": description: Converted pages content: application/json: schema: type: object properties: jobId: type: string pageCount: type: integer description: Total pages in the PDF selectedPages: type: array items: type: integer format: type: string pages: type: array items: type: object properties: page: type: integer downloadUrl: type: string size: type: integer zipUrl: type: string description: URL to download all pages as ZIP zipSize: type: integer "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/pdf-to-image/info: post: tags: [Tools] summary: PDF page count description: Get the number of pages in a PDF file. security: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file] properties: file: type: string format: binary description: PDF file to inspect responses: "200": description: PDF info content: application/json: schema: type: object properties: pageCount: type: integer "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" /api/v1/tools/pdf-to-image/preview: post: tags: [Tools] summary: PDF page thumbnails description: Generate thumbnail previews for each page in a PDF (max 200 pages, JPEG 300px wide). security: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file] properties: file: type: string format: binary description: PDF file to preview responses: "200": description: Page thumbnails content: application/json: schema: type: object properties: pageCount: type: integer thumbnails: type: array items: type: object properties: page: type: integer dataUrl: type: string description: Base64-encoded JPEG data URL width: type: integer height: type: integer "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" /api/v1/tools/split: post: tags: [Tools] summary: Split image description: Split an image into a grid of tiles. Returns a ZIP file. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file, settings] properties: file: type: string format: binary description: Image file to split settings: type: string description: | JSON string with options: - `columns` (number 1-10, default 2) — Number of columns - `rows` (number 1-10, default 2) — Number of rows responses: "200": description: ZIP archive with results content: application/zip: schema: type: string format: binary "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/bulk-rename: post: tags: [Tools] summary: Bulk rename description: Rename multiple images using a pattern template. Supports {{index}}, {{padded}}, and {{original}} tokens. Returns a ZIP file. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file, settings] properties: file: type: array items: type: string format: binary description: Multiple image files to rename settings: type: string description: | JSON string with options: - `pattern` (string 1-200, default "image-{{index}}") — Naming pattern template - `startIndex` (number, default 1) — Starting index number responses: "200": description: ZIP archive with results content: application/zip: schema: type: string format: binary "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/favicon: post: tags: [Tools] summary: Favicon generator description: Generate a complete favicon set (16px to 512px PNGs, ICO, and manifest.json) from an image. Returns a ZIP file. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file] properties: file: type: string format: binary description: Image file to use as favicon source responses: "200": description: ZIP archive with results content: application/zip: schema: type: string format: binary "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/watermark-image: post: tags: [Tools] summary: Image watermark description: Add an image watermark overlay. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file, watermark, settings] properties: file: type: string format: binary description: Main image file watermark: type: string format: binary description: Watermark overlay image settings: type: string description: | JSON string with options: - `position` (string, default "bottom-right") — One of: center, top-left, top-right, bottom-left, bottom-right - `opacity` (number 0-100, default 50) — Watermark opacity percentage - `scale` (number 1-100, default 25) — Watermark size as percentage of base image responses: "200": description: Processed image content: application/json: schema: $ref: "#/components/schemas/ToolResponse" "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/compose: post: tags: [Tools] summary: Image composition description: Composite an overlay image onto a base image with blend modes. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file, overlay, settings] properties: file: type: string format: binary description: Base image file overlay: type: string format: binary description: Overlay image file settings: type: string description: | JSON string with options: - `x` (number, default 0) — Horizontal offset of overlay - `y` (number, default 0) — Vertical offset of overlay - `opacity` (number 0-100, default 100) — Overlay opacity percentage - `blendMode` (string, default "over") — One of: over, multiply, screen, overlay, darken, lighten, hard-light, soft-light, difference, exclusion responses: "200": description: Processed image content: application/json: schema: $ref: "#/components/schemas/ToolResponse" "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/compare: post: tags: [Tools] summary: Image compare description: Compare two images and generate a visual difference report. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file1, file2] properties: file1: type: string format: binary description: First image to compare file2: type: string format: binary description: Second image to compare responses: "200": description: Processed image content: application/json: schema: $ref: "#/components/schemas/ToolResponse" "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/erase-object: post: tags: [Tools] summary: Object eraser description: Erase objects from an image using a mask. White areas in the mask indicate regions to erase. Uses LaMa inpainting. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [image, mask] properties: image: type: string format: binary description: Source image file mask: type: string format: binary description: Mask image (white areas will be erased) responses: "200": description: Processed image content: application/json: schema: $ref: "#/components/schemas/ToolResponse" "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/collage: post: tags: [Tools] summary: Collage / grid description: Combine multiple images into a grid collage. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file, settings] properties: file: type: array items: type: string format: binary description: Multiple image files to combine settings: type: string description: | JSON string with options: - `layout` (string, default "2x2") — One of: 2x2, 3x3, 1x3, 2x1, 3x1, 1x2 - `gap` (number 0-50, default 4) — Gap between images in pixels - `backgroundColor` (hex string, default "#FFFFFF") — Background fill color responses: "200": description: Processed image content: application/json: schema: $ref: "#/components/schemas/ToolResponse" "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/stitch: post: tags: [Tools] summary: Stitch images description: Join multiple images horizontally, vertically, or in a grid layout. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file] properties: file: type: array items: type: string format: binary description: Two or more image files to stitch together settings: type: string description: | JSON string with options: - `direction` (string, default "horizontal") — One of: horizontal, vertical, grid - `gridColumns` (integer 2-10, default 2) — Columns when direction is grid - `resizeMode` (string, default "fit") — One of: fit, original, stretch, crop - `alignment` (string, default "center") — One of: start, center, end - `gap` (number 0-200, default 0) — Gap between images in pixels - `border` (number 0-50, default 0) — Border width in pixels - `cornerRadius` (number 0-50, default 0) — Corner radius in pixels - `backgroundColor` (string, default "#FFFFFF") — Hex color for background and gap fill - `format` (string, default "png") — One of: png, jpeg, webp - `quality` (number 1-100, default 90) — Output quality responses: "200": description: Stitched image content: application/json: schema: $ref: "#/components/schemas/ToolResponse" "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/remove-background: post: tags: [Tools] summary: Remove background description: Remove the background from an image using AI (rembg). Runs locally. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file] properties: file: type: string format: binary description: Image file to process settings: type: string description: | JSON string with options: - `model` (string, optional) — AI model name - `backgroundColor` (string, optional) — Hex color to replace removed background with responses: "200": description: Processed image content: application/json: schema: $ref: "#/components/schemas/ToolResponse" "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/remove-background/effects: post: tags: [Tools] summary: Apply background effects description: > Apply background replacement or effects to a previously processed remove-background result. Requires a jobId from a prior POST /api/v1/tools/remove-background call. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [settings] properties: backgroundImage: type: string format: binary description: Custom background image (required when backgroundType is "image") settings: type: string description: | JSON string with options: - `jobId` (string, required) — Job ID from the initial remove-background call - `filename` (string, required) — Original filename - `backgroundType` (string) — One of: transparent, color, gradient, blur, image - `backgroundColor` (string) — Hex color for solid background - `gradientColor1` (string) — First gradient color - `gradientColor2` (string) — Second gradient color - `gradientAngle` (number) — Gradient angle in degrees - `blurEnabled` (boolean) — Enable background blur effect - `blurIntensity` (number 0-100) — Blur strength - `shadowEnabled` (boolean) — Enable drop shadow - `shadowOpacity` (number 0-100) — Shadow opacity responses: "200": description: Image with applied effects content: application/json: schema: type: object properties: jobId: type: string downloadUrl: type: string processedSize: type: integer "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/upscale: post: tags: [Tools] summary: Image upscaling description: Upscale an image using AI (Real-ESRGAN). Runs locally. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file, settings] properties: file: type: string format: binary description: Image file to upscale settings: type: string description: | JSON string with options: - `scale` (number, default 2) — Upscale factor responses: "200": description: Processed image content: application/json: schema: $ref: "#/components/schemas/ToolResponse" "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/blur-faces: post: tags: [Tools] summary: Face blur description: Detect and blur faces in an image for privacy. Uses OpenCV. Runs locally. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file, settings] properties: file: type: string format: binary description: Image file to process settings: type: string description: | JSON string with options: - `blurRadius` (number, default 30) — Blur strength radius - `sensitivity` (number 0-1, default 0.5) — Face detection sensitivity responses: "200": description: Processed image content: application/json: schema: $ref: "#/components/schemas/ToolResponse" "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/ocr: post: tags: [Tools] summary: OCR / text extraction description: Extract text from an image using OCR. Runs locally. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file, settings] properties: file: type: string format: binary description: Image file to extract text from settings: type: string description: | JSON string with options: - `engine` (string, default "tesseract") — One of: tesseract, paddleocr - `language` (string, default "en") — One of: en, de, fr, es, zh, ja, ko responses: "200": description: Extracted text content: application/json: schema: type: object properties: text: type: string description: Extracted text content engine: type: string confidence: type: number "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/info: post: tags: [Tools] summary: Image info description: Get detailed metadata about an image including dimensions, format, color space, and EXIF data. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file] properties: file: type: string format: binary description: Image file to inspect responses: "200": description: Image metadata content: application/json: schema: type: object properties: width: type: integer height: type: integer format: type: string space: type: string channels: type: integer depth: type: string density: type: integer hasAlpha: type: boolean fileSize: type: integer exif: type: object "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/color-palette: post: tags: [Tools] summary: Color palette description: Extract the dominant colors from an image. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file] properties: file: type: string format: binary description: Image file to analyze responses: "200": description: Dominant colors content: application/json: schema: type: object properties: colors: type: array items: type: string description: Hex color strings "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/barcode-read: post: tags: [Tools] summary: Barcode reader description: Read QR codes and barcodes from an image. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file] properties: file: type: string format: binary description: Image file containing barcode or QR code responses: "200": description: Decoded barcode data content: application/json: schema: type: object properties: data: type: string location: type: object "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/find-duplicates: post: tags: [Tools] summary: Find duplicates description: Find duplicate images in a set using perceptual hashing. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file] properties: file: type: array items: type: string format: binary description: Multiple image files to check for duplicates responses: "200": description: Duplicate groups content: application/json: schema: type: object properties: groups: type: array items: type: object properties: files: type: array items: type: string similarity: type: number "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/qr-generate: post: tags: [Tools] summary: QR code generator description: Generate a QR code image from text. This tool accepts a JSON body, not multipart. security: - bearerAuth: [] requestBody: required: true content: application/json: schema: type: object required: [text] properties: text: type: string maxLength: 2000 description: Text to encode in the QR code size: type: integer minimum: 100 maximum: 2000 default: 400 description: Image size in pixels errorCorrection: type: string enum: [L, M, Q, H] default: M foreground: type: string default: "#000000" description: Foreground color (hex) background: type: string default: "#FFFFFF" description: Background color (hex) responses: "200": description: Generated QR code content: application/json: schema: $ref: "#/components/schemas/ToolResponse" "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/strip-metadata/inspect: post: tags: [Tools] summary: Inspect metadata description: View all metadata (EXIF, GPS, ICC, XMP) in an image without removing it. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file] properties: file: type: string format: binary description: Image file to inspect responses: "200": description: Image metadata content: application/json: schema: type: object properties: exif: type: object description: EXIF metadata gps: type: object description: GPS metadata icc: type: object description: ICC profile metadata xmp: type: object description: XMP metadata "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/edit-metadata: post: tags: [Tools] summary: Edit metadata description: Edit EXIF, IPTC, GPS, and other metadata fields in an image using ExifTool. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file] properties: file: type: string format: binary description: Image file to process settings: type: string description: | JSON string with options: - `artist` (string) — Artist or author name - `copyright` (string) — Copyright notice - `imageDescription` (string) — Image description - `software` (string) — Software used - `dateTime` (string) — Date/time string - `dateTimeOriginal` (string) — Original capture date/time - `clearGps` (boolean, default false) — Remove all GPS data - `fieldsToRemove` (string[]) — Specific metadata fields to remove - `gpsLatitude` (number -90 to 90) — GPS latitude - `gpsLongitude` (number -180 to 180) — GPS longitude - `gpsAltitude` (number) — GPS altitude in meters - `keywords` (string[]) — Keywords or tags - `keywordsMode` (string, default "add") — One of: add, set - `dateShift` (string) — Shift dates by offset, e.g. "+2:00" or "-1:30" - `setAllDates` (string) — Set all date fields to this value - `iptcTitle` (string) — IPTC title - `iptcHeadline` (string) — IPTC headline - `iptcCity` (string) — IPTC city - `iptcState` (string) — IPTC state or province - `iptcCountry` (string) — IPTC country responses: "200": description: Image with updated metadata content: application/json: schema: $ref: "#/components/schemas/ToolResponse" "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/tools/edit-metadata/inspect: post: tags: [Tools] summary: Inspect metadata (ExifTool) description: Read all metadata from an image using ExifTool. Returns all embedded EXIF, IPTC, XMP, and GPS fields. security: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file] properties: file: type: string format: binary description: Image file to inspect responses: "200": description: Full metadata object (keys vary by image) content: application/json: schema: type: object additionalProperties: true "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" # ─── Batch ──────────────────────────────────────────────────────────────── /api/v1/tools/{toolId}/batch: post: tags: [Batch] summary: Batch process images description: > Send multiple images through a single tool. Returns a ZIP file. The response includes an X-Job-Id header for progress tracking. security: - bearerAuth: [] parameters: - name: toolId in: path required: true schema: type: string description: Tool identifier (e.g. resize, crop) requestBody: required: true content: multipart/form-data: schema: type: object required: [file] properties: file: type: array items: type: string format: binary description: Image files to process (one or more) settings: type: string description: JSON string of tool settings applied to all images responses: "200": description: ZIP archive of processed images headers: X-Job-Id: schema: type: string description: Job identifier for progress tracking content: application/zip: schema: type: string format: binary "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required # ─── Pipelines ──────────────────────────────────────────────────────────── /api/v1/pipeline/execute: post: tags: [Pipelines] summary: Execute a pipeline description: Run an image through a chain of tools. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file, steps] properties: file: type: string format: binary description: Image file to process steps: type: string description: JSON array string of {toolId, settings} objects responses: "200": description: Pipeline result content: application/json: schema: type: object properties: jobId: type: string downloadUrl: type: string stepsCompleted: type: integer "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/pipeline/save: post: tags: [Pipelines] summary: Save a pipeline security: - bearerAuth: [] requestBody: required: true content: application/json: schema: type: object required: [name, steps] properties: name: type: string description: type: string steps: type: array items: type: object properties: toolId: type: string settings: type: object responses: "200": description: Saved pipeline content: application/json: schema: type: object properties: id: type: string name: type: string "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/pipeline/list: get: tags: [Pipelines] summary: List saved pipelines security: - bearerAuth: [] responses: "200": description: List of pipelines content: application/json: schema: type: object properties: pipelines: type: array items: type: object properties: id: type: string name: type: string description: type: string steps: type: array items: type: object createdAt: type: string format: date-time "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/pipeline/{id}: delete: tags: [Pipelines] summary: Delete a pipeline security: - bearerAuth: [] parameters: - name: id in: path required: true schema: type: string responses: "204": description: Pipeline deleted "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/pipeline/tools: get: tags: [Pipelines] summary: List pipeline-compatible tools description: Returns all tool IDs that can be used as pipeline steps. security: [] responses: "200": description: Tool IDs content: application/json: schema: type: object properties: toolIds: type: array items: type: string /api/v1/pipeline/batch: post: tags: [Pipelines] summary: Run pipeline on multiple files description: Execute a pipeline across multiple images. Returns a ZIP file with all processed results. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file, pipeline] properties: file: type: array items: type: string format: binary description: Image files to process pipeline: type: string description: | JSON string with pipeline definition: - `steps` (array, required, 1-20 items) — Pipeline steps - `steps[].toolId` (string, required) — Tool ID for this step - `steps[].settings` (object, optional) — Tool-specific settings clientJobId: type: string description: Optional client-provided job ID for progress tracking via SSE responses: "200": description: ZIP file with processed images headers: X-Job-Id: schema: type: string description: Job ID for progress tracking X-File-Results: schema: type: string description: JSON mapping of input index to output filename content: application/zip: schema: type: string format: binary "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required # ─── Files ──────────────────────────────────────────────────────────────── /api/v1/upload: post: tags: [Files] summary: Upload an image security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file] properties: file: type: string format: binary responses: "200": description: Upload result content: application/json: schema: type: object properties: jobId: type: string filename: type: string "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/download/{jobId}/{filename}: get: tags: [Files] summary: Download a processed image security: [] parameters: - name: jobId in: path required: true schema: type: string - name: filename in: path required: true schema: type: string responses: "200": description: Image binary content: image/*: schema: type: string format: binary "404": description: File not found /api/v1/preview: post: tags: [Files] summary: Generate image preview description: Convert any image (including HEIC/HEIF) to a WebP preview, resized to fit within 1200x1200 pixels. security: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file] properties: file: type: string format: binary description: Image file to preview responses: "200": description: WebP preview image content: image/webp: schema: type: string format: binary "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" /api/v1/files: get: tags: [Files] summary: List saved files security: - bearerAuth: [] responses: "200": description: List of saved files content: application/json: schema: type: object properties: files: type: array items: type: object properties: id: type: string filename: type: string size: type: integer contentType: type: string createdAt: type: string format: date-time "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required delete: tags: [Files] summary: Bulk delete saved files description: Delete files and their entire version chains. Non-admin users can only delete their own files. security: - bearerAuth: [] requestBody: required: true content: application/json: schema: type: object required: [ids] properties: ids: type: array items: type: string description: File IDs to delete (deletes entire version chain for each) responses: "200": description: Deletion result content: application/json: schema: type: object properties: deleted: type: integer description: Total number of records deleted across all version chains "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/files/upload: post: tags: [Files] summary: Save file to library security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [file] properties: file: type: string format: binary responses: "200": description: Saved file content: application/json: schema: type: object properties: id: type: string filename: type: string "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/files/save-result: post: tags: [Files] summary: Save a processing result to library security: - bearerAuth: [] requestBody: required: true content: application/json: schema: type: object required: [jobId, filename] properties: jobId: type: string filename: type: string responses: "200": description: Saved file content: application/json: schema: type: object properties: id: type: string filename: type: string "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/files/{id}: get: tags: [Files] summary: Get file metadata security: - bearerAuth: [] parameters: - name: id in: path required: true schema: type: string responses: "200": description: File metadata content: application/json: schema: type: object properties: id: type: string filename: type: string size: type: integer contentType: type: string "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/files/{id}/download: get: tags: [Files] summary: Download a saved file security: - bearerAuth: [] parameters: - name: id in: path required: true schema: type: string responses: "200": description: Image binary content: image/*: schema: type: string format: binary "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/files/{id}/thumbnail: get: tags: [Files] summary: Get file thumbnail security: - bearerAuth: [] parameters: - name: id in: path required: true schema: type: string responses: "200": description: Image binary content: image/*: schema: type: string format: binary "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required # ─── Auth ───────────────────────────────────────────────────────────────── /api/auth/login: post: tags: [Auth] summary: Log in security: [] requestBody: required: true content: application/json: schema: type: object required: [username, password] properties: username: type: string password: type: string format: password responses: "200": description: Login successful content: application/json: schema: type: object properties: token: type: string user: type: object properties: id: type: string username: type: string role: type: string "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Invalid credentials /api/auth/logout: post: tags: [Auth] summary: Log out security: - bearerAuth: [] responses: "204": description: Logged out "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/auth/session: get: tags: [Auth] summary: Get current session security: [] responses: "200": description: Session info content: application/json: schema: type: object properties: user: type: object properties: id: type: string username: type: string role: type: string authenticated: type: boolean /api/auth/change-password: post: tags: [Auth] summary: Change password security: - bearerAuth: [] requestBody: required: true content: application/json: schema: type: object required: [currentPassword, newPassword] properties: currentPassword: type: string format: password newPassword: type: string format: password responses: "204": description: Password changed "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/auth/users: get: tags: [Auth] summary: List users (admin) security: - bearerAuth: [] responses: "200": description: List of users content: application/json: schema: type: object properties: users: type: array items: type: object properties: id: type: string username: type: string role: type: string team: type: string createdAt: type: string format: date-time maxUsers: type: integer "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required "403": description: Admin access required post: tags: [Auth] summary: Create user (admin) security: - bearerAuth: [] requestBody: required: true content: application/json: schema: type: object required: [username, password] properties: username: type: string password: type: string format: password role: type: string enum: [admin, user] default: user team: type: string default: Default responses: "201": description: User created content: application/json: schema: type: object properties: id: type: string username: type: string role: type: string "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required "403": description: Admin access required "409": description: Username already exists /api/auth/users/{id}: put: tags: [Auth] summary: Update user (admin) security: - bearerAuth: [] parameters: - name: id in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object properties: role: type: string enum: [admin, user] team: type: string responses: "200": description: User updated content: application/json: schema: type: object properties: id: type: string username: type: string role: type: string "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required "403": description: Admin access required delete: tags: [Auth] summary: Delete user (admin) security: - bearerAuth: [] parameters: - name: id in: path required: true schema: type: string responses: "204": description: User deleted "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required "403": description: Admin access required /api/auth/users/{id}/reset-password: post: tags: [Auth] summary: Reset user password (admin) security: - bearerAuth: [] parameters: - name: id in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object required: [newPassword] properties: newPassword: type: string format: password responses: "204": description: Password reset "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required "403": description: Admin access required # ─── API Keys ───────────────────────────────────────────────────────────── /api/v1/api-keys: post: tags: [API Keys] summary: Create an API key description: > Generate a new API key. The full key (prefixed with si_) is returned only once. security: - bearerAuth: [] requestBody: required: true content: application/json: schema: type: object required: [name] properties: name: type: string maxLength: 100 responses: "201": description: API key created content: application/json: schema: type: object properties: id: type: string name: type: string key: type: string prefix: type: string "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required get: tags: [API Keys] summary: List API keys description: Returns key metadata but not the full key. security: - bearerAuth: [] responses: "200": description: List of API keys content: application/json: schema: type: object properties: keys: type: array items: type: object properties: id: type: string name: type: string prefix: type: string createdAt: type: string format: date-time "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required /api/v1/api-keys/{id}: delete: tags: [API Keys] summary: Delete an API key security: - bearerAuth: [] parameters: - name: id in: path required: true schema: type: string responses: "204": description: API key deleted "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required # ─── Settings ───────────────────────────────────────────────────────────── /api/v1/settings: get: tags: [Settings] summary: Get all settings security: - bearerAuth: [] responses: "200": description: All settings as key-value pairs content: application/json: schema: type: object additionalProperties: type: string "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required put: tags: [Settings] summary: Update settings (admin) security: - bearerAuth: [] requestBody: required: true content: application/json: schema: type: object additionalProperties: type: string responses: "200": description: Settings updated "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required "403": description: Admin access required /api/v1/settings/{key}: get: tags: [Settings] summary: Get a single setting security: - bearerAuth: [] parameters: - name: key in: path required: true schema: type: string responses: "200": description: Setting value content: application/json: schema: type: object properties: key: type: string value: type: string "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required # ─── Teams ──────────────────────────────────────────────────────────────── /api/v1/teams: get: tags: [Teams] summary: List teams security: - bearerAuth: [] responses: "200": description: List of teams content: application/json: schema: type: object properties: teams: type: array items: type: object properties: id: type: integer name: type: string "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required post: tags: [Teams] summary: Create a team security: - bearerAuth: [] requestBody: required: true content: application/json: schema: type: object required: [name] properties: name: type: string responses: "201": description: Team created content: application/json: schema: type: object properties: id: type: integer name: type: string "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required "409": description: Team name already exists /api/v1/teams/{id}: put: tags: [Teams] summary: Rename a team security: - bearerAuth: [] parameters: - name: id in: path required: true schema: type: integer requestBody: required: true content: application/json: schema: type: object required: [name] properties: name: type: string responses: "200": description: Team updated content: application/json: schema: type: object properties: id: type: integer name: type: string "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required delete: tags: [Teams] summary: Delete a team security: - bearerAuth: [] parameters: - name: id in: path required: true schema: type: integer responses: "204": description: Team deleted "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required # ─── Branding ───────────────────────────────────────────────────────────── /api/v1/settings/logo: get: tags: [Branding] summary: Get custom logo security: [] responses: "200": description: Logo image content: image/*: schema: type: string format: binary "404": description: No custom logo set post: tags: [Branding] summary: Upload custom logo (admin) security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: [logo] properties: logo: type: string format: binary description: Logo image file responses: "200": description: Logo uploaded "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required "403": description: Admin access required delete: tags: [Branding] summary: Remove custom logo (admin) security: - bearerAuth: [] responses: "204": description: Logo removed "400": description: Invalid input content: application/json: schema: $ref: "#/components/schemas/Error" "401": description: Authentication required "403": description: Admin access required # ─── System (additional) ────────────────────────────────────────────────── /api/v1/config/auth: get: tags: [System] summary: Auth configuration security: [] responses: "200": description: Auth config content: application/json: schema: type: object properties: authEnabled: type: boolean /api/v1/jobs/{jobId}/progress: get: tags: [System] summary: Job progress (SSE) description: > Server-Sent Events stream for tracking long-running jobs. Closes automatically 5 seconds after completion. security: [] parameters: - name: jobId in: path required: true schema: type: string responses: "200": description: SSE stream of job progress events content: text/event-stream: schema: type: object properties: status: type: string enum: [processing, completed, failed] progress: type: integer minimum: 0 maximum: 100 completedFiles: type: array items: type: string failedFiles: type: array items: type: string