{
  "openapi": "3.0.3",
  "info": {
    "title": "ECU-Patch Auto-Patch Engine",
    "version": "0.5.0-pilot",
    "description": "Standalone gateway for the ECU-Patch Auto-Patch Engine with local WinOLS script agents, canonical solution metadata, prepaid OEM Patch Credits and tenant-safe file-service integrations."
  },
  "servers": [
    {
      "url": "https://oem.ecu-patch.de",
      "description": "Production-like pilot"
    }
  ],
  "paths": {
    "/v1/files": {
      "post": {
        "summary": "Upload a file for analysis or patching",
        "security": [
          {
            "portalAuth": []
          }
        ]
      }
    },
    "/v1/files/{fileId}/analyze": {
      "post": {
        "summary": "Queue local agent analysis and compatible patch discovery",
        "security": [
          {
            "portalAuth": []
          }
        ]
      }
    },
    "/v1/files/{fileId}/patches": {
      "get": {
        "summary": "Read enabled compatible solution offers found by the local agent. Retail/customer-credit price is metadata only.",
        "security": [
          {
            "portalAuth": []
          }
        ]
      }
    },
    "/v1/files/{fileId}/solutions": {
      "get": {
        "summary": "Read enabled compatible canonical solutions and optional Retail / Customer Credit Price",
        "tags": [
          "Solutions"
        ],
        "security": [
          {
            "portalAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Solution offers"
          }
        }
      }
    },
    "/v1/jobs": {
      "post": {
        "summary": "Create a patch job. One successful patch operation consumes one Patch Credit.",
        "security": [
          {
            "portalAuth": []
          }
        ]
      }
    },
    "/v1/jobs/{jobId}": {
      "get": {
        "summary": "Read job status and operation status",
        "security": [
          {
            "portalAuth": []
          }
        ]
      }
    },
    "/v1/jobs/{jobId}/cancel": {
      "post": {
        "summary": "Cancel a job that has not started processing",
        "tags": [
          "Jobs"
        ],
        "security": [
          {
            "portalAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Cancelled job"
          },
          "409": {
            "description": "Job cannot be cancelled"
          }
        }
      }
    },
    "/v1/jobs/{jobId}/result": {
      "get": {
        "summary": "Download metadata for the patched result file",
        "security": [
          {
            "portalAuth": []
          }
        ]
      }
    },
    "/v1/jobs/{jobId}/result/download": {
      "get": {
        "summary": "Download the immutable final result for the owning partner",
        "security": [
          {
            "portalAuth": []
          }
        ],
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Binary result file"
          },
          "403": {
            "description": "Not owned by partner"
          },
          "404": {
            "description": "Result unavailable"
          },
          "410": {
            "description": "Result expired"
          }
        }
      }
    },
    "/v1/credits": {
      "get": {
        "summary": "Read current Patch Credit balance",
        "security": [
          {
            "portalAuth": []
          }
        ]
      }
    },
    "/v1/usage": {
      "get": {
        "summary": "Read successful and failed patch operation counts",
        "security": [
          {
            "portalAuth": []
          }
        ]
      }
    },
    "/v1/agent/activate": {
      "post": {
        "summary": "Activate a local outbound-only agent with an activation code"
      }
    },
    "/v1/agent/heartbeat": {
      "post": {
        "summary": "Record local agent heartbeat and script index status",
        "security": [
          {
            "agentAuth": []
          }
        ]
      }
    },
    "/v1/agent/status": {
      "get": {
        "summary": "Read assignment, service state and supported Agent versions",
        "security": [
          {
            "agentAuth": []
          }
        ]
      }
    },
    "/v1/agent/jobs/next": {
      "get": {
        "summary": "Long-poll style next job claim for local agent",
        "security": [
          {
            "agentAuth": []
          }
        ]
      }
    },
    "/v1/agent/jobs/{jobId}/analysis-result": {
      "post": {
        "summary": "Submit canonical solution metadata from local agent. Script contents and private filenames stay local.",
        "security": [
          {
            "agentAuth": []
          }
        ]
      }
    },
    "/v1/agent/jobs/{jobId}/input": {
      "get": {
        "summary": "Download the customer input for the active claim",
        "security": [
          {
            "agentAuth": []
          }
        ]
      }
    },
    "/v1/agent/jobs/{jobId}/result-upload": {
      "post": {
        "summary": "Upload a patched customer result for the active claim and result ID",
        "security": [
          {
            "agentAuth": []
          }
        ]
      }
    },
    "/v1/agent/jobs/{jobId}/patch-result": {
      "post": {
        "summary": "Submit patch result. Failed operations release reserved credits.",
        "security": [
          {
            "agentAuth": []
          }
        ]
      }
    }
  },
  "components": {
    "securitySchemes": {
      "portalAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Api-Key",
        "description": "Use X-Api-Key with X-Api-Timestamp, X-Api-Nonce and X-Api-Signature HMAC headers."
      },
      "agentAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Agent-Id",
        "description": "Use X-Agent-Id together with X-Agent-Secret."
      }
    }
  }
}