{
  "openapi": "3.0.3",
  "info": {
    "title": "PrivyTranslate Local API",
    "version": "0.5.2",
    "description": "Swagger/OpenAPI JSON for the localhost translation API exposed by the PrivyTranslate macOS app. Enable Local API in Settings, then use the Settings API token as X-Privy-Token, Authorization: Bearer, or the documented WebSocket token mechanism."
  },
  "servers": [
    {
      "url": "http://127.0.0.1:49321/v1",
      "description": "PrivyTranslate macOS Local API HTTP server"
    }
  ],
  "tags": [
    {
      "name": "System",
      "description": "Health and runtime capability endpoints."
    },
    {
      "name": "Translation",
      "description": "Language detection and translation endpoints."
    },
    {
      "name": "WebSocket",
      "description": "Low-latency translation over WebSocket."
    }
  ],
  "paths": {
    "/health": {
      "get": {
        "tags": [
          "System"
        ],
        "summary": "Check local API health",
        "description": "Returns service health and readiness. This endpoint does not require an API token.",
        "operationId": "getHealth",
        "security": [],
        "responses": {
          "200": {
            "description": "Service health",
            "headers": {
              "Privy-API-Version": {
                "$ref": "#/components/headers/PrivyAPIVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                },
                "example": {
                  "status": "ok",
                  "app": "PrivyTranslate",
                  "version": "0.5.2 (11)",
                  "api_version": "v1",
                  "uptime_ms": 12345,
                  "ready": true
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/capabilities": {
      "get": {
        "tags": [
          "System"
        ],
        "summary": "Get local API capabilities",
        "description": "Returns supported engines, language codes, feature flags, and request limits. This endpoint does not require an API token.",
        "operationId": "getCapabilities",
        "security": [],
        "responses": {
          "200": {
            "description": "Runtime capabilities",
            "headers": {
              "Privy-API-Version": {
                "$ref": "#/components/headers/PrivyAPIVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CapabilitiesResponse"
                },
                "example": {
                  "app": "PrivyTranslate",
                  "version": "0.5.2 (11)",
                  "api_version": "v1",
                  "engines": [
                    {
                      "id": "local-llm",
                      "name": "Built-in Local",
                      "ready": true,
                      "models": [
                        {
                          "id": "translategemma-4b-it.Q4_K_M.gguf",
                          "name": "translategemma-4b-it.Q4_K_M.gguf",
                          "ready": true
                        }
                      ]
                    },
                    {
                      "id": "ollama",
                      "name": "Ollama",
                      "ready": false,
                      "models": null
                    },
                    {
                      "id": "lm-studio",
                      "name": "LM Studio",
                      "ready": false,
                      "models": null
                    },
                    {
                      "id": "openai-compatible",
                      "name": "OpenAI-compatible",
                      "ready": false,
                      "models": null
                    }
                  ],
                  "languages": [
                    "en",
                    "zh-Hans",
                    "zh-Hant",
                    "vi",
                    "th",
                    "id",
                    "ms",
                    "fil",
                    "my",
                    "km",
                    "lo",
                    "ja",
                    "ko",
                    "fr",
                    "de",
                    "es"
                  ],
                  "features": {
                    "detect": true,
                    "batch": true,
                    "stream": false,
                    "websocket": true,
                    "html": false,
                    "markdown": false,
                    "glossary": false,
                    "memory": false,
                    "offline": true
                  },
                  "limits": {
                    "max_items": 128,
                    "max_chars_per_item": 8000,
                    "max_total_chars": 50000
                  }
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/detect": {
      "post": {
        "tags": [
          "Translation"
        ],
        "summary": "Detect source languages",
        "description": "Detects the likely language for each text item. Requires the local API token.",
        "operationId": "detectLanguage",
        "security": [
          {
            "PrivyToken": []
          },
          {
            "PrivyBearer": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PrivyClientHeader"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DetectRequest"
              },
              "examples": {
                "detectMalayAndEnglish": {
                  "summary": "Detect Malay and English text",
                  "value": {
                    "texts": [
                      "Apa khabar?",
                      "Hello, how are you?"
                    ],
                    "options": {
                      "engine": "auto"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Language detection result",
            "headers": {
              "Privy-API-Version": {
                "$ref": "#/components/headers/PrivyAPIVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DetectResponse"
                },
                "examples": {
                  "detectMalayAndEnglishResult": {
                    "summary": "Detection result for Malay and English text",
                    "value": {
                      "id": "det_8F2A6D4E-5F58-4A37-8E92-7B4FD40BE2D2",
                      "object": "language_detection",
                      "created": 1781180000,
                      "results": [
                        {
                          "index": 0,
                          "language": "ms",
                          "confidence": 0.92
                        },
                        {
                          "index": 1,
                          "language": "en",
                          "confidence": 0.99
                        }
                      ],
                      "usage": {
                        "input_chars": 31,
                        "latency_ms": 8
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/translate": {
      "post": {
        "tags": [
          "Translation"
        ],
        "summary": "Translate text",
        "description": "Translates one or more text items through PrivyTranslate's configured local-first translation pipeline. Requires the local API token.",
        "operationId": "translateText",
        "security": [
          {
            "PrivyToken": []
          },
          {
            "PrivyBearer": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PrivyClientHeader"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TranslateRequest"
              },
              "examples": {
                "translateSelectionToChinese": {
                  "summary": "Selected text translation",
                  "value": {
                    "source": "auto",
                    "target": "zh-Hans",
                    "texts": [
                      "Hello, how are you?"
                    ],
                    "mode": "selection",
                    "format": "text",
                    "options": {
                      "engine": "auto",
                      "preserve_formatting": true,
                      "tone": "natural",
                      "sensitive": false
                    }
                  }
                },
                "translateSensitiveChineseToEnglish": {
                  "summary": "Sensitive request that skips history storage",
                  "value": {
                    "source": "auto",
                    "target": "en",
                    "texts": [
                      "你好"
                    ],
                    "mode": "paragraph",
                    "format": "text",
                    "options": {
                      "sensitive": true
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Translation result",
            "headers": {
              "Privy-API-Version": {
                "$ref": "#/components/headers/PrivyAPIVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TranslateResponse"
                },
                "examples": {
                  "translateSelectionToChineseResult": {
                    "summary": "Translation result for selected English text",
                    "value": {
                      "id": "tr_8F2A6D4E-5F58-4A37-8E92-7B4FD40BE2D2",
                      "object": "translation",
                      "created": 1781180000,
                      "engine": "local-llm",
                      "model": "translategemma-4b-it.Q4_K_M.gguf",
                      "source": "en",
                      "target": "zh-Hans",
                      "results": [
                        {
                          "index": 0,
                          "text": "你好，你好吗？",
                          "detected_source": "en",
                          "confidence": 0.98,
                          "alternatives": []
                        }
                      ],
                      "usage": {
                        "input_chars": 19,
                        "output_chars": 7,
                        "latency_ms": 342
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionRequired"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "422": {
            "$ref": "#/components/responses/UnsupportedLanguage"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/ws/translate": {
      "get": {
        "tags": [
          "WebSocket"
        ],
        "summary": "Translate over WebSocket",
        "description": "Opens a WebSocket connection. Send each text or binary frame as a JSON TranslateRequest. Each successful frame receives a JSON TranslateResponse; validation or translation failures are sent as JSON ErrorResponse frames.",
        "operationId": "translateWebSocket",
        "servers": [
          {
            "url": "ws://127.0.0.1:49321/v1",
            "description": "PrivyTranslate macOS Local API WebSocket server"
          }
        ],
        "security": [
          {
            "PrivyToken": []
          },
          {
            "PrivyBearer": []
          },
          {
            "PrivyWebSocketQueryToken": []
          },
          {
            "PrivyWebSocketAccessToken": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebSocketTokenQuery"
          },
          {
            "$ref": "#/components/parameters/WebSocketAccessTokenQuery"
          },
          {
            "$ref": "#/components/parameters/PrivyClientHeader"
          },
          {
            "$ref": "#/components/parameters/WebSocketProtocolHeader"
          }
        ],
        "responses": {
          "101": {
            "description": "WebSocket connection established. Client frames use TranslateRequest JSON and server frames use TranslateResponse or ErrorResponse JSON.",
            "headers": {
              "Upgrade": {
                "description": "Always websocket for a successful handshake.",
                "schema": {
                  "type": "string",
                  "example": "websocket"
                }
              },
              "Connection": {
                "description": "Upgrade for a successful handshake.",
                "schema": {
                  "type": "string",
                  "example": "Upgrade"
                }
              },
              "Sec-WebSocket-Protocol": {
                "description": "Echoes bearer when the bearer subprotocol pair is used.",
                "schema": {
                  "type": "string",
                  "example": "bearer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TranslateResponse"
                },
                "examples": {
                  "requestFrame": {
                    "summary": "Client frame",
                    "value": {
                      "source": "auto",
                      "target": "zh-Hans",
                      "texts": [
                        "Hello websocket"
                      ],
                      "mode": "selection",
                      "format": "text"
                    }
                  },
                  "responseFrame": {
                    "summary": "Server frame",
                    "value": {
                      "id": "tr_8F2A6D4E-5F58-4A37-8E92-7B4FD40BE2D2",
                      "object": "translation",
                      "created": 1781180000,
                      "engine": "local-llm",
                      "model": "translategemma-4b-it.Q4_K_M.gguf",
                      "source": "en",
                      "target": "zh-Hans",
                      "results": [
                        {
                          "index": 0,
                          "text": "你好 websocket",
                          "detected_source": "en",
                          "confidence": 0.98,
                          "alternatives": []
                        }
                      ],
                      "usage": {
                        "input_chars": 15,
                        "output_chars": 12,
                        "latency_ms": 120
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/WebSocketUnauthorized"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "422": {
            "$ref": "#/components/responses/UnsupportedLanguage"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "x-websocket-message": {
          "requestSchema": "#/components/schemas/TranslateRequest",
          "responseSchema": "#/components/schemas/TranslateResponse",
          "errorSchema": "#/components/schemas/ErrorResponse"
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "PrivyToken": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Privy-Token",
        "description": "Local API token shown in PrivyTranslate macOS Settings when the Local API is enabled."
      },
      "PrivyBearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "Alternative Authorization: Bearer token authentication supported by HTTP and WebSocket handshakes."
      },
      "PrivyWebSocketQueryToken": {
        "type": "apiKey",
        "in": "query",
        "name": "token",
        "description": "Browser-friendly WebSocket token query parameter."
      },
      "PrivyWebSocketAccessToken": {
        "type": "apiKey",
        "in": "query",
        "name": "access_token",
        "description": "Alternative browser-friendly WebSocket token query parameter."
      }
    },
    "headers": {
      "PrivyAPIVersion": {
        "description": "PrivyTranslate Local API version date.",
        "schema": {
          "type": "string",
          "example": "2026-06-11"
        }
      }
    },
    "parameters": {
      "PrivyClientHeader": {
        "name": "X-Privy-Client",
        "in": "header",
        "required": false,
        "description": "Optional client identifier, for example privytranslate-chrome.",
        "schema": {
          "type": "string",
          "example": "privytranslate-chrome"
        }
      },
      "WebSocketTokenQuery": {
        "name": "token",
        "in": "query",
        "required": false,
        "description": "WebSocket token query parameter. Use this for browser WebSocket clients that cannot set custom headers.",
        "schema": {
          "type": "string"
        }
      },
      "WebSocketAccessTokenQuery": {
        "name": "access_token",
        "in": "query",
        "required": false,
        "description": "Alternative WebSocket token query parameter.",
        "schema": {
          "type": "string"
        }
      },
      "WebSocketProtocolHeader": {
        "name": "Sec-WebSocket-Protocol",
        "in": "header",
        "required": false,
        "description": "Optional subprotocol auth pair. Send bearer,<token>; the server echoes bearer when accepted.",
        "schema": {
          "type": "string",
          "example": "bearer,local-api-token"
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Invalid request",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "error": {
                "code": "invalid_request",
                "message": "texts must not be empty.",
                "type": "invalid_request_error",
                "param": "texts"
              }
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing or invalid local API token",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "error": {
                "code": "unauthorized",
                "message": "Missing or invalid local API token.",
                "type": "authentication_error",
                "param": null
              }
            }
          }
        }
      },
      "WebSocketUnauthorized": {
        "description": "Missing or invalid WebSocket credentials",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "error": {
                "code": "ws_unauthorized",
                "message": "Missing or invalid WebSocket credentials",
                "type": "authentication_error",
                "param": null
              }
            }
          }
        }
      },
      "PermissionRequired": {
        "description": "The selected provider requires a local system permission",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "error": {
                "code": "permission_required",
                "message": "Permission required: Accessibility.",
                "type": "server_error",
                "param": null
              }
            }
          }
        }
      },
      "PayloadTooLarge": {
        "description": "Request exceeds configured text limits",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "error": {
                "code": "payload_too_large",
                "message": "texts exceeds max_total_chars 50000.",
                "type": "invalid_request_error",
                "param": "texts"
              }
            }
          }
        }
      },
      "UnsupportedLanguage": {
        "description": "Source or target language is not supported",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "error": {
                "code": "unsupported_language",
                "message": "target must be a supported BCP 47 language tag.",
                "type": "invalid_request_error",
                "param": "target"
              }
            }
          }
        }
      },
      "InternalError": {
        "description": "Unexpected server error",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "error": {
                "code": "internal_error",
                "message": "Internal server error.",
                "type": "server_error",
                "param": null
              }
            }
          }
        }
      },
      "ServiceUnavailable": {
        "description": "Translation engine is unavailable",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "error": {
                "code": "engine_unavailable",
                "message": "No translation provider is available.",
                "type": "server_error",
                "param": null
              }
            }
          }
        }
      }
    },
    "schemas": {
      "LanguageCode": {
        "type": "string",
        "description": "Supported BCP 47 language code.",
        "enum": [
          "en",
          "zh-Hans",
          "zh-Hant",
          "vi",
          "th",
          "id",
          "ms",
          "fil",
          "my",
          "km",
          "lo",
          "ja",
          "ko",
          "fr",
          "de",
          "es"
        ]
      },
      "SourceLanguageCode": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/LanguageCode"
          },
          {
            "type": "string",
            "enum": [
              "auto"
            ]
          }
        ],
        "default": "auto"
      },
      "HealthResponse": {
        "type": "object",
        "required": [
          "status",
          "app",
          "version",
          "api_version",
          "uptime_ms",
          "ready"
        ],
        "additionalProperties": false,
        "properties": {
          "status": {
            "type": "string",
            "example": "ok"
          },
          "app": {
            "type": "string",
            "example": "PrivyTranslate"
          },
          "version": {
            "type": "string",
            "example": "0.5.2 (11)"
          },
          "api_version": {
            "type": "string",
            "example": "v1"
          },
          "uptime_ms": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "ready": {
            "type": "boolean"
          }
        }
      },
      "CapabilitiesResponse": {
        "type": "object",
        "required": [
          "app",
          "version",
          "api_version",
          "engines",
          "languages",
          "features",
          "limits"
        ],
        "additionalProperties": false,
        "properties": {
          "app": {
            "type": "string"
          },
          "version": {
            "type": "string"
          },
          "api_version": {
            "type": "string"
          },
          "engines": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Engine"
            }
          },
          "languages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LanguageCode"
            }
          },
          "features": {
            "$ref": "#/components/schemas/Features"
          },
          "limits": {
            "$ref": "#/components/schemas/Limits"
          }
        }
      },
      "Engine": {
        "type": "object",
        "required": [
          "id",
          "name",
          "ready"
        ],
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string",
            "enum": [
              "local-llm",
              "ollama",
              "lm-studio",
              "openai-compatible"
            ]
          },
          "name": {
            "type": "string"
          },
          "ready": {
            "type": "boolean"
          },
          "models": {
            "type": "array",
            "nullable": true,
            "items": {
              "$ref": "#/components/schemas/Model"
            }
          }
        }
      },
      "Model": {
        "type": "object",
        "required": [
          "id",
          "name",
          "ready"
        ],
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "ready": {
            "type": "boolean"
          }
        }
      },
      "Features": {
        "type": "object",
        "required": [
          "detect",
          "batch",
          "stream",
          "websocket",
          "html",
          "markdown",
          "glossary",
          "memory",
          "offline"
        ],
        "additionalProperties": false,
        "properties": {
          "detect": {
            "type": "boolean"
          },
          "batch": {
            "type": "boolean"
          },
          "stream": {
            "type": "boolean"
          },
          "websocket": {
            "type": "boolean"
          },
          "html": {
            "type": "boolean"
          },
          "markdown": {
            "type": "boolean"
          },
          "glossary": {
            "type": "boolean"
          },
          "memory": {
            "type": "boolean"
          },
          "offline": {
            "type": "boolean"
          }
        }
      },
      "Limits": {
        "type": "object",
        "required": [
          "max_items",
          "max_chars_per_item",
          "max_total_chars"
        ],
        "additionalProperties": false,
        "properties": {
          "max_items": {
            "type": "integer",
            "example": 128
          },
          "max_chars_per_item": {
            "type": "integer",
            "example": 8000
          },
          "max_total_chars": {
            "type": "integer",
            "example": 50000
          }
        }
      },
      "DetectRequest": {
        "type": "object",
        "required": [
          "texts"
        ],
        "additionalProperties": false,
        "properties": {
          "texts": {
            "$ref": "#/components/schemas/TextBatch"
          },
          "options": {
            "type": "object",
            "additionalProperties": true,
            "nullable": true
          }
        }
      },
      "DetectResponse": {
        "type": "object",
        "required": [
          "id",
          "object",
          "created",
          "results",
          "usage"
        ],
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string",
            "example": "det_8F2A6D4E-5F58-4A37-8E92-7B4FD40BE2D2"
          },
          "object": {
            "type": "string",
            "example": "language_detection"
          },
          "created": {
            "type": "integer",
            "format": "int64"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DetectResult"
            }
          },
          "usage": {
            "$ref": "#/components/schemas/Usage"
          }
        }
      },
      "DetectResult": {
        "type": "object",
        "required": [
          "index",
          "language",
          "confidence"
        ],
        "additionalProperties": false,
        "properties": {
          "index": {
            "type": "integer",
            "minimum": 0
          },
          "language": {
            "type": "string",
            "example": "en"
          },
          "confidence": {
            "type": "number",
            "format": "double",
            "minimum": 0,
            "maximum": 1
          }
        }
      },
      "TranslateRequest": {
        "type": "object",
        "required": [
          "target",
          "texts"
        ],
        "additionalProperties": false,
        "properties": {
          "source": {
            "$ref": "#/components/schemas/SourceLanguageCode"
          },
          "target": {
            "$ref": "#/components/schemas/LanguageCode"
          },
          "texts": {
            "$ref": "#/components/schemas/TextBatch"
          },
          "mode": {
            "type": "string",
            "enum": [
              "selection",
              "paragraph",
              "webpage",
              "subtitle",
              "message",
              "document"
            ],
            "default": "paragraph"
          },
          "format": {
            "type": "string",
            "enum": [
              "text",
              "html",
              "markdown"
            ],
            "default": "text"
          },
          "options": {
            "$ref": "#/components/schemas/TranslateOptions"
          }
        }
      },
      "TranslateOptions": {
        "type": "object",
        "nullable": true,
        "additionalProperties": false,
        "properties": {
          "engine": {
            "type": "string",
            "enum": [
              "auto",
              "local-llm",
              "ollama",
              "lm-studio",
              "openai-compatible"
            ]
          },
          "model": {
            "type": "string"
          },
          "preserve_formatting": {
            "type": "boolean"
          },
          "tone": {
            "type": "string",
            "example": "natural"
          },
          "domain": {
            "type": "string",
            "example": "general"
          },
          "return_alternatives": {
            "type": "boolean",
            "default": false
          },
          "glossary_id": {
            "type": "string",
            "nullable": true
          },
          "memory": {
            "type": "boolean"
          },
          "sensitive": {
            "type": "boolean",
            "description": "When true, PrivyTranslate skips translation history storage for this request.",
            "default": false
          }
        }
      },
      "TranslateResponse": {
        "type": "object",
        "required": [
          "id",
          "object",
          "created",
          "engine",
          "model",
          "source",
          "target",
          "results",
          "usage"
        ],
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string",
            "example": "tr_8F2A6D4E-5F58-4A37-8E92-7B4FD40BE2D2"
          },
          "object": {
            "type": "string",
            "example": "translation"
          },
          "created": {
            "type": "integer",
            "format": "int64"
          },
          "engine": {
            "type": "string",
            "example": "local-llm"
          },
          "model": {
            "type": "string",
            "example": "translategemma-4b-it.Q4_K_M.gguf"
          },
          "source": {
            "type": "string",
            "example": "en"
          },
          "target": {
            "$ref": "#/components/schemas/LanguageCode"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TranslateResult"
            }
          },
          "usage": {
            "$ref": "#/components/schemas/Usage"
          }
        }
      },
      "TranslateResult": {
        "type": "object",
        "required": [
          "index",
          "text",
          "detected_source",
          "confidence",
          "alternatives"
        ],
        "additionalProperties": false,
        "properties": {
          "index": {
            "type": "integer",
            "minimum": 0
          },
          "text": {
            "type": "string"
          },
          "detected_source": {
            "type": "string",
            "example": "en"
          },
          "confidence": {
            "type": "number",
            "format": "double",
            "minimum": 0,
            "maximum": 1
          },
          "alternatives": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "TextBatch": {
        "type": "array",
        "minItems": 1,
        "maxItems": 128,
        "items": {
          "type": "string",
          "maxLength": 8000
        },
        "description": "Batch of text inputs. The local API also enforces max_total_chars=50000 across all items."
      },
      "Usage": {
        "type": "object",
        "required": [
          "input_chars",
          "latency_ms"
        ],
        "additionalProperties": false,
        "properties": {
          "input_chars": {
            "type": "integer",
            "minimum": 0
          },
          "output_chars": {
            "type": "integer",
            "minimum": 0,
            "nullable": true
          },
          "latency_ms": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "required": [
          "error"
        ],
        "additionalProperties": false,
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message",
              "type"
            ],
            "additionalProperties": false,
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "type": {
                "type": "string",
                "enum": [
                  "invalid_request_error",
                  "authentication_error",
                  "server_error"
                ]
              },
              "param": {
                "type": "string",
                "nullable": true
              }
            }
          }
        }
      }
    }
  }
}
