{
  "openapi": "3.1.1",
  "info": {
    "title": "Aiden Extraction Agent API",
    "description": "Extracts header and order lines from PDFs into JSON. Per client it learns a template with AI on the first document; later documents of that layout are parsed in about a second.",
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "http://extraction-agent.dev.aidencloud.eu/"
    }
  ],
  "paths": {
    "/healthz": {
      "get": {
        "tags": [
          "Health"
        ],
        "summary": "Liveness",
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/ready": {
      "get": {
        "tags": [
          "Health"
        ],
        "summary": "Readiness (storage reachable, and whether the LLM is configured)",
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/service": {
      "get": {
        "tags": [
          "Health"
        ],
        "summary": "Public service information for the web interface",
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/clients": {
      "get": {
        "tags": [
          "Clients"
        ],
        "summary": "Clients by name (for the web interface)",
        "operationId": "ListClients",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Client"
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Clients"
        ],
        "summary": "Create a client with a unique name",
        "operationId": "CreateClient",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateClientRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Client"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/extractions": {
      "post": {
        "tags": [
          "Extractions"
        ],
        "summary": "Upload a PDF and extract header and lines",
        "description": "Multipart form with `file` (the PDF) and optional `callbackUrl` (the result is POSTed there when done, and again for every revision).\nReturns **200** with the result when it is ready within a few seconds (a known layout: template path), otherwise **202** with\n`statusUrl` and `eventsUrl`. Send `Prefer: respond-async` to always get 202. The first document of a new layout takes minutes\n(LLM extraction); the template is learned afterwards and later documents of that layout take about a second.",
        "operationId": "CreateExtraction",
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "required": [
                  "file"
                ],
                "type": "object",
                "allOf": [
                  {
                    "type": "object",
                    "properties": {
                      "file": {
                        "$ref": "#/components/schemas/IFormFile"
                      }
                    }
                  },
                  {
                    "type": "object",
                    "properties": {
                      "callbackUrl": {
                        "type": "string"
                      }
                    }
                  }
                ]
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExtractionResult"
                }
              }
            }
          },
          "202": {
            "description": "Accepted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExtractionAccepted"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/extractions/{id}": {
      "get": {
        "tags": [
          "Extractions"
        ],
        "summary": "Status and result of an extraction",
        "description": "`status`: running | completed | failed. `revision` increases when a template update re-ran the document (feedback round). `learning` shows the template learning state.",
        "operationId": "GetExtraction",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExtractionStatusResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/extractions/{id}/events": {
      "get": {
        "tags": [
          "Extractions"
        ],
        "summary": "Progress as server-sent events",
        "description": "Replays earlier events, then streams new ones (`identify`, `llm`, `validate`, `learn`, `feedback`, …) until the extraction and its learning are finished.",
        "operationId": "GetExtractionEvents",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/templates": {
      "get": {
        "tags": [
          "Templates"
        ],
        "summary": "Templates of the calling client",
        "operationId": "ListTemplates",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TemplateInfo"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/templates/{id}/versions": {
      "get": {
        "tags": [
          "Templates"
        ],
        "summary": "Versions of a template and the size of its example set",
        "operationId": "GetTemplateVersions",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TemplateInfo"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/templates/{id}/versions/{version}": {
      "get": {
        "tags": [
          "Templates"
        ],
        "summary": "The template JSON of one version (what the AI wrote)",
        "operationId": "GetTemplateVersion",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "version",
            "in": "path",
            "required": true,
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Template"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/templates/{id}/rollback": {
      "post": {
        "tags": [
          "Templates"
        ],
        "summary": "Activate an earlier version",
        "operationId": "RollbackTemplate",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RollbackRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TemplateInfo"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/templates/{id}": {
      "delete": {
        "tags": [
          "Templates"
        ],
        "summary": "Reset: delete the template, its versions and examples (the next request relearns)",
        "operationId": "DeleteTemplate",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "AnchorWord": {
        "required": [
          "text",
          "x"
        ],
        "type": "object",
        "properties": {
          "text": {
            "type": "string"
          },
          "x": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
            "type": [
              "number",
              "string"
            ],
            "format": "double"
          }
        }
      },
      "Client": {
        "required": [
          "clientId",
          "name",
          "createdAt"
        ],
        "type": "object",
        "properties": {
          "clientId": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ColumnRange": {
        "required": [
          "x0",
          "x1"
        ],
        "type": "object",
        "properties": {
          "x0": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
            "type": [
              "number",
              "string"
            ],
            "format": "double"
          },
          "x1": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
            "type": [
              "number",
              "string"
            ],
            "format": "double"
          },
          "rowOffset": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32",
            "default": 0
          }
        }
      },
      "ContinuationRule": {
        "type": "object",
        "properties": {
          "regex": {
            "type": "string"
          },
          "target": {
            "type": "string"
          },
          "append": {
            "type": "boolean"
          }
        }
      },
      "CreateClientRequest": {
        "required": [
          "name"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "DocumentHeader": {
        "type": "object",
        "properties": {
          "documentType": {
            "type": [
              "null",
              "string"
            ]
          },
          "documentNumber": {
            "type": [
              "null",
              "string"
            ]
          },
          "documentDate": {
            "type": [
              "null",
              "string"
            ],
            "format": "date"
          },
          "dueDate": {
            "type": [
              "null",
              "string"
            ],
            "format": "date"
          },
          "currency": {
            "type": [
              "null",
              "string"
            ]
          },
          "supplier": {
            "$ref": "#/components/schemas/Party"
          },
          "customer": {
            "$ref": "#/components/schemas/Party"
          },
          "totals": {
            "$ref": "#/components/schemas/DocumentTotals"
          },
          "attributes": {
            "type": [
              "null",
              "object"
            ],
            "additionalProperties": {
              "type": "string"
            }
          }
        }
      },
      "DocumentTotals": {
        "type": "object",
        "properties": {
          "net": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "format": "double"
          },
          "vat": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "format": "double"
          },
          "gross": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "format": "double"
          },
          "subtotals": {
            "type": "array",
            "items": {
              "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
              "type": [
                "number",
                "string"
              ],
              "format": "double"
            }
          }
        }
      },
      "ExtractedLine": {
        "type": "object",
        "properties": {
          "lineNo": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "section": {
            "type": [
              "null",
              "string"
            ]
          },
          "date": {
            "type": [
              "null",
              "string"
            ],
            "format": "date"
          },
          "materialCode": {
            "type": [
              "null",
              "string"
            ]
          },
          "description": {
            "type": [
              "null",
              "string"
            ]
          },
          "quantity": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "format": "double"
          },
          "unit": {
            "type": [
              "null",
              "string"
            ]
          },
          "unitPrice": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "format": "double"
          },
          "priceUnit": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "format": "double"
          },
          "lineTotal": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "format": "double"
          },
          "vatCode": {
            "type": [
              "null",
              "string"
            ]
          },
          "attributes": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "source": {
            "$ref": "#/components/schemas/SourceRef"
          }
        }
      },
      "ExtractionAccepted": {
        "required": [
          "extractionId",
          "status",
          "statusUrl",
          "eventsUrl"
        ],
        "type": "object",
        "properties": {
          "extractionId": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "statusUrl": {
            "type": "string"
          },
          "eventsUrl": {
            "type": "string"
          }
        }
      },
      "ExtractionResult": {
        "type": "object",
        "properties": {
          "extractionId": {
            "type": [
              "null",
              "string"
            ]
          },
          "templateId": {
            "type": [
              "null",
              "string"
            ]
          },
          "templateVersion": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "path": {
            "type": "string"
          },
          "header": {
            "$ref": "#/components/schemas/DocumentHeader"
          },
          "lines": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ExtractedLine"
            }
          },
          "validation": {
            "$ref": "#/components/schemas/ValidationReport"
          },
          "timings": {
            "$ref": "#/components/schemas/Timings"
          }
        }
      },
      "ExtractionStatusResponse": {
        "required": [
          "extractionId",
          "status",
          "revision",
          "learning",
          "finished",
          "createdAt",
          "completedAt",
          "error",
          "result"
        ],
        "type": "object",
        "properties": {
          "extractionId": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "revision": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "learning": {
            "type": "string"
          },
          "finished": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "completedAt": {
            "type": [
              "null",
              "string"
            ],
            "format": "date-time"
          },
          "error": {
            "type": [
              "null",
              "string"
            ]
          },
          "result": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/ExtractionResult"
              }
            ]
          }
        }
      },
      "FieldRule": {
        "type": "object",
        "properties": {
          "regex": {
            "type": "string"
          },
          "type": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "FormatSettings": {
        "type": "object",
        "properties": {
          "decimal": {
            "type": "string"
          },
          "thousands": {
            "type": "string"
          },
          "date": {
            "type": "string"
          },
          "currency": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "IdentifyRule": {
        "type": "object",
        "properties": {
          "anyText": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "IFormFile": {
        "type": "string",
        "format": "binary"
      },
      "LinePrefixRule": {
        "type": "object",
        "properties": {
          "regex": {
            "type": "string"
          },
          "lookahead": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          }
        }
      },
      "LineRule": {
        "type": "object",
        "properties": {
          "regex": {
            "type": "string"
          },
          "carry": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "attributes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "Party": {
        "type": "object",
        "properties": {
          "name": {
            "type": [
              "null",
              "string"
            ]
          },
          "number": {
            "type": [
              "null",
              "string"
            ]
          },
          "vatNumber": {
            "type": [
              "null",
              "string"
            ]
          },
          "cocNumber": {
            "type": [
              "null",
              "string"
            ]
          },
          "address": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "PatternRule": {
        "type": "object",
        "properties": {
          "regex": {
            "type": "string"
          }
        }
      },
      "ProblemDetails": {
        "type": "object",
        "properties": {
          "type": {
            "type": [
              "null",
              "string"
            ]
          },
          "title": {
            "type": [
              "null",
              "string"
            ]
          },
          "status": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "detail": {
            "type": [
              "null",
              "string"
            ]
          },
          "instance": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "ResidueLine": {
        "required": [
          "page",
          "line",
          "text"
        ],
        "type": "object",
        "properties": {
          "page": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "line": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "text": {
            "type": "string"
          },
          "gap": {
            "type": "boolean"
          }
        }
      },
      "RollbackRequest": {
        "required": [
          "version"
        ],
        "type": "object",
        "properties": {
          "version": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          }
        }
      },
      "SectionRule": {
        "type": "object",
        "properties": {
          "regex": {
            "type": "string"
          },
          "requiresNextLine": {
            "type": [
              "null",
              "string"
            ]
          },
          "lookahead": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          }
        }
      },
      "SourceRef": {
        "type": "object",
        "properties": {
          "page": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "line": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "bbox": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
              "type": [
                "number",
                "string"
              ],
              "format": "double"
            }
          },
          "fields": {
            "type": [
              "null",
              "object"
            ],
            "additionalProperties": {
              "type": "array",
              "items": {
                "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
                "type": [
                  "number",
                  "string"
                ],
                "format": "double"
              }
            }
          }
        }
      },
      "TableRule": {
        "type": "object",
        "properties": {
          "heading": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AnchorWord"
            }
          },
          "columns": {
            "type": "object",
            "additionalProperties": {
              "$ref": "#/components/schemas/ColumnRange"
            }
          },
          "keyColumn": {
            "type": "string"
          },
          "stopWords": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "descriptionAbove": {
            "type": "boolean"
          },
          "rowSignature": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "tolerance": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
            "type": [
              "number",
              "string"
            ],
            "format": "double"
          }
        }
      },
      "Template": {
        "type": "object",
        "properties": {
          "schemaVersion": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "templateId": {
            "type": [
              "null",
              "string"
            ]
          },
          "clientId": {
            "type": [
              "null",
              "string"
            ]
          },
          "fingerprint": {
            "type": [
              "null",
              "string"
            ]
          },
          "version": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "identify": {
            "$ref": "#/components/schemas/IdentifyRule"
          },
          "formats": {
            "$ref": "#/components/schemas/FormatSettings"
          },
          "ignore": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PatternRule"
            }
          },
          "noise": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PatternRule"
            }
          },
          "header": {
            "type": "object",
            "additionalProperties": {
              "$ref": "#/components/schemas/FieldRule"
            }
          },
          "totals": {
            "type": "object",
            "additionalProperties": {
              "$ref": "#/components/schemas/FieldRule"
            }
          },
          "section": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/SectionRule"
              }
            ]
          },
          "sectionContinuation": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/PatternRule"
              }
            ]
          },
          "line": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/LineRule"
              }
            ]
          },
          "table": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/TableRule"
              }
            ]
          },
          "linePrefix": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LinePrefixRule"
            }
          },
          "continuation": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ContinuationRule"
            }
          },
          "required": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "checks": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "TemplateInfo": {
        "required": [
          "templateId",
          "fingerprint",
          "activeVersion",
          "versions",
          "exampleCount"
        ],
        "type": "object",
        "properties": {
          "templateId": {
            "type": "string"
          },
          "fingerprint": {
            "type": [
              "null",
              "string"
            ]
          },
          "activeVersion": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "versions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TemplateVersionInfo"
            }
          },
          "exampleCount": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "provenRuns": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32",
            "default": 0
          }
        }
      },
      "TemplateVersionInfo": {
        "required": [
          "version",
          "createdAt",
          "reason"
        ],
        "type": "object",
        "properties": {
          "version": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "reason": {
            "type": "string"
          }
        }
      },
      "Timings": {
        "type": "object",
        "properties": {
          "ingestMs": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int64"
          },
          "extractMs": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int64"
          },
          "llmMs": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int64"
          },
          "totalMs": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "format": "int64"
          }
        }
      },
      "ValidationCheck": {
        "required": [
          "name",
          "passed"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "passed": {
            "type": "boolean"
          },
          "detail": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "ValidationReport": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string"
          },
          "checks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ValidationCheck"
            }
          },
          "residue": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ResidueLine"
            }
          }
        }
      }
    },
    "securitySchemes": {
      "ApiKey": {
        "type": "apiKey",
        "description": "Client API key (local development: see README).",
        "name": "X-Api-Key",
        "in": "header"
      },
      "ClientId": {
        "type": "apiKey",
        "description": "Id of a client from GET /clients (what the web interface sends). Used only when no X-Api-Key is sent.",
        "name": "X-Client-Id",
        "in": "header"
      }
    }
  },
  "security": [
    {
      "ApiKey": [ ]
    },
    {
      "ClientId": [ ]
    }
  ],
  "tags": [
    {
      "name": "Health"
    },
    {
      "name": "Clients"
    },
    {
      "name": "Extractions"
    },
    {
      "name": "Templates"
    }
  ]
}