{
  "openapi": "3.1.0",
  "info": {
    "title": "Energirör Public Service API",
    "version": "2.0.0",
    "description": "Publikt, rate-limitat API för AI-agenter. Tjänster och routing hämtas från Energirörs service_catalog. API:t kan klassificera ärenden, göra säker värmepumpstriage, föreslå sammanhängande lediga tider och skapa en pending bokningsförfrågan. Kundregister och rå kalenderdata exponeras aldrig."
  },
  "servers": [
    {
      "url": "https://mcp.energiror.se/functions/v1/agent-service-api",
      "description": "Production API"
    }
  ],
  "paths": {
    "/services": {
      "get": {
        "operationId": "listServices",
        "summary": "Lista levande bokningsbara tjänster",
        "responses": { "200": { "description": "Tjänstekatalog" }, "429": { "$ref": "#/components/responses/RateLimited" } }
      }
    },
    "/resolve-service": {
      "post": {
        "operationId": "resolveService",
        "summary": "Matcha kundens problem mot rätt service_code",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ResolveServiceRequest" } } } },
        "responses": { "200": { "description": "Matchande tjänster" }, "400": { "$ref": "#/components/responses/BadRequest" } }
      }
    },
    "/slots": {
      "post": {
        "operationId": "suggestServiceSlots",
        "summary": "Föreslå sammanhängande lediga servicetider",
        "description": "Använder tjänstens duration och service_technician_assignments. Teknikernamn och kalenderdetaljer exponeras inte.",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SlotRequest" } } } },
        "responses": { "200": { "description": "Tidsförslag" }, "400": { "$ref": "#/components/responses/BadRequest" }, "429": { "$ref": "#/components/responses/RateLimited" } }
      }
    },
    "/availability": {
      "post": {
        "operationId": "checkAvailability",
        "summary": "Kontrollera ett exakt tidsfönster",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AvailabilityRequest" } } } },
        "responses": { "200": { "description": "Aggregerad free/busy" }, "400": { "$ref": "#/components/responses/BadRequest" }, "429": { "$ref": "#/components/responses/RateLimited" } }
      }
    },
    "/triage": {
      "post": {
        "operationId": "triageHeatPumpIssue",
        "summary": "Säker teknisk triage av värmepumpsfel",
        "description": "Använder Kjells manualbank, felsökningsmotor och valfri verifierad produkt/reservdelssökning.",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TriageRequest" } } } },
        "responses": { "200": { "description": "Säkra felsökningssteg och verifierade kandidater" }, "400": { "$ref": "#/components/responses/BadRequest" }, "429": { "$ref": "#/components/responses/RateLimited" } }
      }
    },
    "/booking-request": {
      "post": {
        "operationId": "createBookingRequest",
        "summary": "Skapa pending bokningsförfrågan",
        "description": "Kontrollerar vald tid igen, väljer intern resurs enligt service_catalog, verifierar adress och berikar ärendet privat. Ingen kalender reserveras innan Energirör bekräftar bokningen.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": { "type": "string", "minLength": 8, "maxLength": 128 }
          },
          {
            "name": "X-Agent-Client",
            "in": "header",
            "required": false,
            "schema": { "type": "string", "maxLength": 80 }
          }
        ],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BookingRequest" } } } },
        "responses": {
          "201": { "description": "Pending bokningsförfrågan skapad" },
          "200": { "description": "Idempotent replay" },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "409": { "description": "Vald tid är inte längre ledig eller idempotenskonflikt" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ServiceRef": {
        "type": "string",
        "description": "Använd service_code från GET /services, t.ex. VP-REPARATION eller VVS-SERVICE. Äldre tjänstenamn accepteras för bakåtkompatibilitet."
      },
      "ResolveServiceRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": ["issue"],
        "properties": { "issue": { "type": "string", "minLength": 3, "maxLength": 2000 } }
      },
      "SlotRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": ["service_code", "from_date"],
        "properties": {
          "service_code": { "$ref": "#/components/schemas/ServiceRef" },
          "from_date": { "type": "string", "format": "date" },
          "to_date": { "type": "string", "format": "date", "description": "Valfri. Högst 14 kalenderdagar från from_date." },
          "daypart": { "type": "string", "enum": ["any", "morning", "afternoon"], "default": "any" },
          "city": { "type": "string", "maxLength": 100 },
          "max_results": { "type": "integer", "minimum": 1, "maximum": 6, "default": 3 }
        }
      },
      "AvailabilityRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": ["service_code", "start_datetime", "end_datetime"],
        "properties": {
          "service_code": { "$ref": "#/components/schemas/ServiceRef" },
          "start_datetime": { "type": "string", "description": "Lokal Europe/Stockholm-tid utan zon, t.ex. 2026-10-07T08:00." },
          "end_datetime": { "type": "string" },
          "city": { "type": "string", "maxLength": 100 }
        }
      },
      "TriageRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": ["model", "symptom"],
        "properties": {
          "model": { "type": "string", "maxLength": 200 },
          "symptom": { "type": "string", "maxLength": 2000 },
          "error_code": { "type": "string", "maxLength": 120 },
          "part_query": { "type": "string", "maxLength": 180 }
        }
      },
      "BookingRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": ["service_code", "customer_name", "customer_email", "customer_phone", "address", "postal_code", "city", "problem_description", "service_date", "service_time"],
        "properties": {
          "service_code": { "$ref": "#/components/schemas/ServiceRef" },
          "customer_name": { "type": "string", "minLength": 2, "maxLength": 120 },
          "customer_email": { "type": "string", "format": "email", "maxLength": 254 },
          "customer_phone": { "type": "string", "minLength": 5, "maxLength": 30 },
          "address": { "type": "string", "minLength": 2, "maxLength": 200 },
          "postal_code": { "type": "string", "pattern": "^\\d{3}\\s?\\d{2}$" },
          "city": { "type": "string", "minLength": 2, "maxLength": 100 },
          "problem_description": { "type": "string", "minLength": 2, "maxLength": 2000 },
          "service_date": { "type": "string", "format": "date" },
          "service_time": { "type": "string", "pattern": "^\\d{2}:(00|30)$" },
          "heat_pump_brand_model": { "type": "string", "maxLength": 200 },
          "heat_pump_serial_number": { "type": "string", "maxLength": 120 },
          "heat_pump_error_code": { "type": "string", "maxLength": 120 },
          "urgency": { "type": "string", "enum": ["low", "normal", "high", "urgent"], "default": "normal" },
          "rot_avdrag": { "type": "boolean", "default": false },
          "diagnostic_summary": { "type": "string", "maxLength": 1200 },
          "steps_tried": { "type": "array", "maxItems": 10, "items": { "type": "string", "maxLength": 240 } },
          "part_article_numbers": { "type": "array", "maxItems": 10, "items": { "type": "string", "maxLength": 80 } },
          "agent_id": { "type": "string", "maxLength": 80 }
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Ogiltig förfrågan",
        "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean" }, "error": { "type": "string" } } } } }
      },
      "RateLimited": {
        "description": "För många förfrågningar",
        "headers": { "Retry-After": { "schema": { "type": "string" } } }
      }
    }
  }
}
