{
  "openapi": "3.1.0",
  "info": {
    "title": "lattedit Compile API",
    "version": "1.0.0",
    "summary": "Compile complete LaTeX projects into PDFs.",
    "description": "A stateless API for compiling a complete LaTeX project. No account or API key is required. The service is rate limited and may take longer to answer while its free compile worker wakes.",
    "termsOfService": "https://lattedit.xyz/privacy",
    "contact": {
      "name": "lattedit support",
      "url": "https://lattedit.xyz/contact",
      "email": "cneuralnets@gmail.com"
    }
  },
  "servers": [
    {
      "url": "https://www.lattedit.xyz/api/v1",
      "description": "Production"
    }
  ],
  "externalDocs": {
    "description": "Developer guide, examples, rate limits, and versioning policy",
    "url": "https://lattedit.xyz/developers"
  },
  "x-api-catalog": "https://lattedit.xyz/.well-known/api-catalog",
  "x-versioning-policy": "https://lattedit.xyz/api-policy",
  "x-deprecation-policy": "Stable operations use RFC 9745 Deprecation and Link headers, followed by a dated Sunset header with at least 90 days notice.",
  "paths": {
    "/health": {
      "get": {
        "operationId": "getCompilerHealth",
        "summary": "Check compiler availability",
        "description": "Returns the TeX version and current compile worker load. Call this before a latency-sensitive compile because an idle free worker may need time to wake.",
        "security": [],
        "parameters": [
          {
            "name": "details",
            "in": "query",
            "required": false,
            "description": "Use full to include process uptime and configured compile limits.",
            "schema": { "type": "string", "enum": ["basic", "full"], "default": "basic" }
          }
        ],
        "responses": {
          "200": {
            "description": "The compile service is available.",
            "headers": {
              "RateLimit-Policy": { "$ref": "#/components/headers/RateLimitPolicy" },
              "RateLimit": { "$ref": "#/components/headers/RateLimit" }
            },
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/HealthResponse" },
                "examples": {
                  "ready": { "value": { "ok": true, "tex": "pdfTeX 3.141592653", "busy": 0, "queued": 0 } }
                }
              }
            }
          },
          "405": { "description": "The endpoint received a non-GET method.", "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/Problem" } } } },
          "500": { "description": "The service hit an unexpected error.", "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/Problem" } } } },
          "503": { "description": "The compile worker is temporarily unavailable.", "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/Problem" } } } },
          "default": { "description": "An error response not otherwise listed.", "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/Problem" } } } }
        }
      }
    },
    "/compile": {
      "post": {
        "operationId": "compileLatexProject",
        "summary": "Compile a LaTeX project",
        "description": "Compiles all submitted project files and returns a base64 PDF plus the complete TeX log. A LaTeX document error is represented by a 200 response with a non-success status because the API operation itself completed.",
        "security": [],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional caller-generated key for retry correlation. Compilation is deterministic for identical project input; workspaceKey controls short-lived incremental compiler state.",
            "schema": { "type": "string", "minLength": 8, "maxLength": 128 }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The complete project. Include every source, bibliography, image, style, and other file read by TeX.",
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/CompileRequest" },
              "examples": {
                "article": {
                  "value": {
                    "compiler": "pdflatex",
                    "main": "main.tex",
                    "stopOnFirstError": true,
                    "files": [
                      {
                        "path": "main.tex",
                        "encoding": "utf8",
                        "content": "\\documentclass{article}\\begin{document}Hello\\end{document}"
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Compilation finished. Inspect status and log; pdf is null when no PDF was produced.",
            "headers": {
              "Server-Timing": { "$ref": "#/components/headers/ServerTiming" },
              "RateLimit-Policy": { "$ref": "#/components/headers/RateLimitPolicy" },
              "RateLimit": { "$ref": "#/components/headers/RateLimit" }
            },
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CompileResponse" }
              }
            }
          },
          "400": { "description": "The request JSON or project is invalid.", "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/Problem" } } } },
          "405": { "description": "The endpoint received a non-POST method.", "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/Problem" } } } },
          "413": { "description": "The submitted project exceeds the request size limit.", "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/Problem" } } } },
          "429": { "description": "The client exhausted its compile quota for the current minute.", "headers": { "Retry-After": { "schema": { "type": "integer", "minimum": 1 } } }, "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/Problem" } } } },
          "500": { "description": "The compile service hit an unexpected error.", "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/Problem" } } } },
          "503": { "description": "The compile queue is full or the worker is unavailable.", "headers": { "Retry-After": { "schema": { "type": "integer", "minimum": 1 } } }, "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/Problem" } } } },
          "default": { "description": "An error response not otherwise listed.", "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/Problem" } } } }
        }
      }
    }
  },
  "components": {
    "headers": {
      "RateLimitPolicy": {
        "description": "Rate limit quota and window in seconds.",
        "schema": { "type": "string", "example": "20;w=60" }
      },
      "RateLimit": {
        "description": "Current rate limit, approximate remaining quota, and reset time in seconds.",
        "schema": { "type": "string", "example": "limit=20, remaining=19, reset=60" }
      },
      "ServerTiming": {
        "description": "Server-side file synchronization and TeX engine durations.",
        "schema": { "type": "string", "example": "sync;dur=3, latex;dur=814" }
      }
    },
    "schemas": {
      "ProjectFile": {
        "type": "object",
        "additionalProperties": false,
        "required": ["path", "content", "encoding"],
        "properties": {
          "path": { "type": "string", "minLength": 1, "maxLength": 512, "description": "Relative project path without dot segments or a leading slash.", "example": "chapters/introduction.tex" },
          "content": { "type": "string", "description": "UTF-8 text or base64-encoded binary bytes." },
          "encoding": { "type": "string", "enum": ["utf8", "base64"], "description": "How content is encoded." }
        }
      },
      "CompileRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": ["main", "files"],
        "properties": {
          "compiler": { "type": "string", "enum": ["pdflatex", "xelatex", "lualatex"], "default": "pdflatex" },
          "main": { "type": "string", "minLength": 1, "maxLength": 512, "description": "Relative path to the project's root TeX file.", "example": "main.tex" },
          "workspaceKey": { "type": "string", "minLength": 16, "maxLength": 128, "pattern": "^[A-Za-z0-9_-]+$", "description": "Random, non-personal capability reused for short-lived incremental builds. Omit for an isolated one-shot compile." },
          "stopOnFirstError": { "type": "boolean", "default": false },
          "files": { "type": "array", "minItems": 1, "maxItems": 300, "items": { "$ref": "#/components/schemas/ProjectFile" } }
        }
      },
      "CompileResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": ["status", "pdf", "log", "durationMs", "syncMs", "engineMs", "cache"],
        "properties": {
          "status": { "type": "string", "enum": ["success", "error", "failure", "timeout"] },
          "pdf": { "type": ["string", "null"], "contentEncoding": "base64", "contentMediaType": "application/pdf", "description": "Compiled PDF, or null when TeX produced none." },
          "log": { "type": "string", "description": "Complete compiler log for diagnostics." },
          "durationMs": { "type": "integer", "minimum": 0 },
          "syncMs": { "type": "integer", "minimum": 0 },
          "engineMs": { "type": "integer", "minimum": 0 },
          "cache": { "type": "string", "enum": ["none", "cold", "incremental", "exact"] }
        }
      },
      "HealthResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": ["ok", "tex", "busy", "queued"],
        "properties": {
          "ok": { "type": "boolean", "const": true },
          "tex": { "type": ["string", "null"], "description": "Installed pdfTeX version, or null while detection is pending." },
          "busy": { "type": "integer", "minimum": 0 },
          "queued": { "type": "integer", "minimum": 0 },
          "uptimeSeconds": { "type": "integer", "minimum": 0 },
          "rateLimitPerMinute": { "type": "integer", "minimum": 1 },
          "maxProjectFiles": { "type": "integer", "minimum": 1 }
        }
      },
      "Problem": {
        "type": "object",
        "additionalProperties": false,
        "required": ["type", "title", "status", "code", "message", "detail", "resolution", "instance"],
        "properties": {
          "type": { "type": "string", "format": "uri" },
          "title": { "type": "string" },
          "status": { "type": "integer", "minimum": 400, "maximum": 599 },
          "code": { "type": "string", "pattern": "^[a-z0-9_]+$", "example": "invalid_project" },
          "message": { "type": "string", "description": "Human-readable error message, equal to detail for broad client compatibility." },
          "detail": { "type": "string" },
          "resolution": { "type": "string" },
          "instance": { "type": "string", "description": "Request path associated with the error.", "example": "/api/v1/compile" }
        }
      }
    }
  }
}
