openapi: 3.1.0
info:
  title: MetaGhost Desktop 1.0.81 Local API
  version: 1.0.81
  description: Released Desktop 1.0.81 API. Preset-driven image/video spoofing with local files or Google Drive.
    OpenAPI 3.1 describes this file format; the release uses unversioned /api routes.
servers:
- url: http://127.0.0.1:3847/api
  description: Default local Desktop server. Replace the port if changed in Settings > API.
security:
- LocalApiKey: []
paths:
  /health:
    get:
      summary: Check Desktop 1.0.81 and active jobs
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Health'
      security: []
  /presets:
    get:
      summary: List saved image and video preset names
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Presets'
        '401':
          description: Invalid or missing API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /drive/status:
    get:
      summary: Check the Desktop Google Drive connection
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DriveStatus'
        '401':
          description: Invalid or missing API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /upload:
    post:
      summary: Upload raw image or video bytes
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Upload'
        '400':
          description: Invalid request or incompatible job state
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Invalid or missing API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: Internal server or upload write error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      description: Raw bytes, not multipart. Maximum 500 MiB (524288000 bytes). Oversized uploads and write errors
        may close the connection before a JSON error arrives. There is no upload-retention guarantee in 1.0.81.
      parameters:
      - name: X-Filename
        in: header
        required: true
        schema:
          type: string
          description: Name ending in .jpg, .jpeg, .png, .webp, .heic, .bmp, .tiff, .mp4, .mov, .avi, .mkv, .webm
            or .m4v.
      requestBody:
        required: true
        content:
          application/octet-stream:
            schema:
              type: string
              format: binary
  /jobs:
    post:
      summary: Create an image/video spoofing job
      responses:
        '202':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AcceptedJob'
        '400':
          description: Invalid request or incompatible job state
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Invalid or missing API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '412':
          description: Google Drive is not configured or connected
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: Ten jobs already waiting in the queue
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: Internal server or upload write error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      description: 'Each POST creates a new job. No automatic retries or Idempotency-Key support. JSON body ceiling:
        64 KiB; exceeding it may close the connection. Local inputs are checked before acceptance; Drive inputs
        are discovered afterwards.'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SpoofJobRequest'
            example:
              filePath: C:\Media\photo.jpg
              outputFolder: C:\Media\output
              batchCount: 1
    get:
      summary: List the 50 most recent jobs and queue state
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/JobList'
        '401':
          description: Invalid or missing API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      description: In-memory history. Completed, failed and cancelled jobs become eligible for cleanup after one
        hour from completedAt, or createdAt when completedAt is absent. Cleanup runs every ten minutes. Restarting
        Desktop loses this history.
    delete:
      summary: Clear finished jobs from in-memory history
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                type: object
                properties:
                  cleared:
                    type: integer
                required:
                - cleared
        '401':
          description: Invalid or missing API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /jobs/{jobId}:
    parameters:
    - &id001
      name: jobId
      in: path
      required: true
      schema:
        type: string
        pattern: ^[a-zA-Z0-9_-]+$
    get:
      summary: Read one job's progress and results
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Job'
        '401':
          description: Invalid or missing API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Unknown job, missing output or unsupported route
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
    delete:
      summary: Request cancellation of a queued or processing job
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                type: object
                properties:
                  jobId:
                    type: string
                  status:
                    const: cancelled
                required:
                - jobId
                - status
        '400':
          description: Invalid request or incompatible job state
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Invalid or missing API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Unknown job, missing output or unsupported route
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      description: Inspect status again after cancellation. Already-produced files may remain. The currently processing
        batch file may finish before the queue stops.
  /download/{jobId}:
    parameters:
    - *id001
    get:
      summary: Download an existing local output of a completed job
      description: For batches, index addresses the successful results array, not the original input array. A Drive-delivered
        temporary output may already have been cleaned up and return 404. An unfinished job returns 400.
      parameters:
      - name: index
        in: query
        schema:
          type: integer
          minimum: 0
          default: 0
      responses:
        '200':
          description: Output bytes; Content-Type follows the file extension and Content-Disposition contains the
            filename.
          content:
            application/octet-stream:
              schema:
                type: string
                format: binary
        '400':
          description: Job is not completed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Unknown job, index or output file
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  securitySchemes:
    LocalApiKey:
      type: http
      scheme: bearer
      description: Key generated in Desktop Settings > API.
  schemas:
    Error:
      type: object
      properties:
        error:
          type: string
        skipped:
          type: array
          items:
            $ref: '#/components/schemas/FileError'
      required:
      - error
    FileError:
      type: object
      properties:
        file:
          type: string
        error:
          type: string
      required:
      - file
      - error
    Health:
      type: object
      properties:
        status:
          const: ok
        version:
          const: 1.0.81
        activeJobs:
          type: integer
          minimum: 0
      required:
      - status
      - version
      - activeJobs
    Presets:
      type: object
      properties:
        image:
          type: array
          items:
            type: string
        video:
          type: array
          items:
            type: string
      required:
      - image
      - video
    DriveStatus:
      type: object
      properties:
        clientConfigured:
          type: boolean
        connected:
          type: boolean
        email:
          type:
          - string
          - 'null'
        scope:
          type:
          - string
          - 'null'
      required:
      - clientConfigured
      - connected
      - email
      - scope
    DriveUploadResult:
      type: object
      properties:
        uploaded:
          type: integer
          minimum: 0
        errors:
          type: array
          items:
            type: object
            properties:
              name:
                type: string
              error:
                type: string
            required:
            - name
            - error
        cancelled:
          type: boolean
      required:
      - uploaded
      - errors
    Upload:
      type: object
      properties:
        filePath:
          type: string
          description: Absolute path on the Desktop computer.
        originalName:
          type: string
        size:
          type: integer
          minimum: 1
      required:
      - filePath
      - originalName
      - size
    SpoofJobRequest:
      type: object
      properties:
        filePath:
          type: string
          description: Absolute path to one existing image or video.
        files:
          type: array
          items:
            type: string
            description: Absolute path to an existing image or video.
        driveInputFolder:
          type: string
          description: Folder ID accessible to the connected Desktop Drive account.
        outputFolder:
          type: string
          description: Absolute local output directory; created when missing.
        driveOutputFolder:
          type: string
          description: Destination folder ID accessible to the Desktop Drive account.
        preset:
          type: string
          description: Exact saved preset name for each input media type. Omit for basic defaults.
        batchCount:
          type: integer
          minimum: 1
          default: 1
          description: Variations per valid input. Send a positive integer and keep batches small; increase gradually
            according to your computer's capacity.
      description: Preset-driven image/video spoofing only. Choose filePath, files OR driveInputFolder, and outputFolder
        OR driveOutputFolder. No operation selector or idempotency support. Unknown extra fields are ignored by
        1.0.81, not a way to enable another tool.
      allOf:
      - oneOf:
        - anyOf:
          - required:
            - filePath
          - required:
            - files
        - required:
          - driveInputFolder
      - oneOf:
        - required:
          - outputFolder
        - required:
          - driveOutputFolder
    AcceptedJob:
      type: object
      properties:
        jobId:
          type: string
        status:
          const: queued
        inputFiles:
          type:
          - integer
          - 'null'
        batchCount:
          type: integer
        totalOperations:
          type:
          - integer
          - 'null'
        skipped:
          type: array
          items:
            $ref: '#/components/schemas/FileError'
        position:
          type: integer
          description: May be zero when processing has already started.
        drive:
          anyOf:
          - type: 'null'
          - type: object
            properties:
              input:
                type: boolean
              output:
                type: boolean
      required:
      - jobId
      - status
      - inputFiles
      - batchCount
      - totalOperations
      - skipped
      - position
      - drive
    Output:
      type: object
      properties:
        outputPath:
          type: string
      required:
      - outputPath
    BatchOutput:
      type: object
      properties:
        file:
          type: string
        outputPath:
          type: string
      required:
      - file
      - outputPath
    Progress:
      type: object
      properties:
        phase:
          type: string
        phaseProgress:
          type: number
        totalProgress:
          type: number
        currentFile:
          type: integer
        totalFiles:
          type:
          - integer
          - 'null'
        completedFiles:
          type: integer
        fileName:
          type: string
    Job:
      type: object
      properties:
        jobId:
          type: string
        status:
          type: string
          enum:
          - queued
          - processing
          - completed
          - failed
          - cancelled
        type:
          type: string
          enum:
          - single
          - batch
        preset:
          type: string
        progress:
          $ref: '#/components/schemas/Progress'
        createdAt:
          type: string
        startedAt:
          type:
          - string
          - 'null'
        completedAt:
          type:
          - string
          - 'null'
        fileType:
          type: string
        fileName:
          type: string
        totalFiles:
          type: integer
        result:
          $ref: '#/components/schemas/Output'
        results:
          type: array
          items:
            $ref: '#/components/schemas/BatchOutput'
        error:
          type: string
          description: Single-job failure.
        errors:
          type: array
          items:
            $ref: '#/components/schemas/FileError'
        drive:
          type: object
          properties:
            inputFolderId:
              type:
              - string
              - 'null'
            outputFolderId:
              type:
              - string
              - 'null'
            uploadResult:
              anyOf:
              - type: 'null'
              - $ref: '#/components/schemas/DriveUploadResult'
            uploadError:
              type:
              - string
              - 'null'
      required:
      - jobId
      - status
      - type
      - preset
      - progress
      - createdAt
      - startedAt
      - completedAt
      description: A completed batch may include errors or have no successful results. Check errors and results,
        plus skipped from POST. For Drive output, processing can reach completed before upload finishes; keep polling
        until uploadResult or uploadError is present, and inspect uploadResult.errors and uploadResult.cancelled.
        No outcome field exists in this release.
    JobList:
      type: object
      properties:
        jobs:
          type: array
          items:
            $ref: '#/components/schemas/Job'
        queueLength:
          type: integer
        processing:
          type: boolean
      required:
      - jobs
      - queueLength
      - processing
