{
  "openapi": "3.1.0",
  "info": {
    "title": "Świadectwo Energetyczne 24 — API partnerów",
    "version": "1.0.0",
    "description": "API dla systemów CRM biur nieruchomości, portali i innych partnerów. System partnera zakłada zamówienie świadectwa charakterystyki energetycznej z danymi oferty, otwiera klientowi albo agentowi formularz z tymi danymi, a po wydaniu świadectwa pobiera wskaźniki do ogłoszenia, numer świadectwa i plik PDF.\n\n**Uwierzytelnianie.** Każde żądanie wymaga nagłówka `Authorization: Bearer <klucz>`. Klucz wydajemy partnerowi; jest sekretem serwera — API nie wysyła nagłówków CORS, więc nie da się go wywołać z przeglądarki.\n\n**Zgody i płatność.** Zgody prawne, zdjęcie budynku i płatność online podaje klient w formularzu pod adresem `form_url`. API nie przyjmuje danych kart ani zgód w imieniu klienta.\n\n**Status.** API nie wysyła powiadomień (webhooków). Stan zamówienia sprawdza się przez GET /api/v1/orders/{id}; po wysłaniu świadectwa pole `certificate` zawiera wynik.\n\n**Limity.** 120 żądań na minutę na klucz, 300 nowych zamówień na godzinę. Po przekroczeniu odpowiedź 429 z nagłówkiem Retry-After.\n\nDokumentacja z przykładami: https://swiadectwo-energetyczne24.pl/api#partnerzy",
    "contact": {
      "name": "Świadectwo Energetyczne 24",
      "url": "https://swiadectwo-energetyczne24.pl/api#partnerzy",
      "email": "kontakt@swiadectwo-energetyczne24.pl"
    }
  },
  "servers": [
    {
      "url": "https://swiadectwo-energetyczne24.pl",
      "description": "Produkcja"
    }
  ],
  "security": [
    {
      "klucz": []
    }
  ],
  "paths": {
    "/api/v1/me": {
      "get": {
        "operationId": "getAccount",
        "summary": "Test połączenia",
        "description": "Zwraca partnera, zakresy klucza i ceny, po których partner sprzedaje świadectwa.",
        "responses": {
          "200": {
            "description": "Partner i klucz.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Account"
                }
              }
            }
          },
          "401": {
            "description": "Brak albo nieprawidłowy klucz API.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Klucz nie ma wymaganego zakresu.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Za dużo żądań — nagłówek Retry-After podaje, ile sekund odczekać.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/fields/{property_type}": {
      "get": {
        "operationId": "listFields",
        "summary": "Pola formularza",
        "description": "Pola, które można przekazać w `fields`: ścieżka, typ i dozwolone wartości. Służy do jednorazowego zmapowania pól oferty w systemie partnera.",
        "parameters": [
          {
            "name": "property_type",
            "in": "path",
            "required": true,
            "description": "Typ nieruchomości.",
            "schema": {
              "type": "string",
              "enum": [
                "mieszkanie",
                "dom",
                "lokal-uzytkowy",
                "budynek-nieogrzewany"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Pola formularza.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FieldList"
                }
              }
            }
          },
          "401": {
            "description": "Brak albo nieprawidłowy klucz API.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Klucz nie ma wymaganego zakresu.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Nie ma takiego zamówienia.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Za dużo żądań — nagłówek Retry-After podaje, ile sekund odczekać.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/orders": {
      "post": {
        "operationId": "createOrder",
        "summary": "Nowe zamówienie z danymi oferty",
        "description": "Zakłada zamówienie i zwraca adres formularza wypełnionego danymi oferty. Wystarczy `property_type`; im więcej danych, tym mniej wpisuje klient. Nagłówek Idempotency-Key chroni przed podwójnym zamówieniem przy ponowieniu żądania.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Własny klucz żądania, 8–120 znaków. To samo żądanie z tym samym kluczem zwraca to samo zamówienie.",
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 120
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NewOrder"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Zamówienie z tym kluczem idempotencji już istnieje.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                }
              }
            }
          },
          "201": {
            "description": "Zamówienie założone.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                }
              }
            }
          },
          "401": {
            "description": "Brak albo nieprawidłowy klucz API.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Klucz nie ma wymaganego zakresu.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Nieprawidłowe dane.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Za dużo żądań — nagłówek Retry-After podaje, ile sekund odczekać.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listOrders",
        "summary": "Lista zamówień",
        "description": "Zamówienia założone przez API, od najnowszych, bez pola `certificate`. Filtr `external_id` znajduje zamówienia dla oferty.",
        "parameters": [
          {
            "name": "external_id",
            "in": "query",
            "required": false,
            "description": "Identyfikator oferty w systemie partnera.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Liczba pozycji, 1–200. Domyślnie 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Lista zamówień.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderList"
                }
              }
            }
          },
          "401": {
            "description": "Brak albo nieprawidłowy klucz API.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Klucz nie ma wymaganego zakresu.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Nieprawidłowe dane.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Za dużo żądań — nagłówek Retry-After podaje, ile sekund odczekać.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/orders/{id}": {
      "get": {
        "operationId": "getOrder",
        "summary": "Status zamówienia i wynik",
        "description": "Stan zamówienia, płatności i świadectwa. Po wysłaniu świadectwa klientowi pole `certificate` zawiera wskaźniki EU, EK, EP, udział OZE, emisję CO₂, numer świadectwa i gotowy akapit do ogłoszenia.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Identyfikator zamówienia z odpowiedzi na POST /api/v1/orders.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Zamówienie.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                }
              }
            }
          },
          "401": {
            "description": "Brak albo nieprawidłowy klucz API.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Klucz nie ma wymaganego zakresu.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Nie ma takiego zamówienia.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Za dużo żądań — nagłówek Retry-After podaje, ile sekund odczekać.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateOrder",
        "summary": "Uzupełnienie danych",
        "description": "Dopisuje albo zmienia dane oferty, dopóki klient nie złożył zamówienia. Po złożeniu zamówienia odpowiedź 409.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Identyfikator zamówienia z odpowiedzi na POST /api/v1/orders.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrderUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Zamówienie po zmianie.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                }
              }
            }
          },
          "401": {
            "description": "Brak albo nieprawidłowy klucz API.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Klucz nie ma wymaganego zakresu.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Nie ma takiego zamówienia.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Operacja niemożliwa w tym stanie zamówienia.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "410": {
            "description": "Zamówienie wygasło.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Nieprawidłowe dane.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Za dużo żądań — nagłówek Retry-After podaje, ile sekund odczekać.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/orders/{id}/certificate": {
      "get": {
        "operationId": "downloadCertificate",
        "summary": "Plik świadectwa (PDF)",
        "description": "Podpisane świadectwo w PDF. Wymaga klucza z zakresem pdf. Dostępne po wysłaniu świadectwa klientowi; wcześniej odpowiedź 409.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Identyfikator zamówienia z odpowiedzi na POST /api/v1/orders.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Plik PDF.",
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "description": "Brak albo nieprawidłowy klucz API.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Klucz nie ma wymaganego zakresu.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Nie ma takiego zamówienia.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Operacja niemożliwa w tym stanie zamówienia.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Za dużo żądań — nagłówek Retry-After podaje, ile sekund odczekać.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "klucz": {
        "type": "http",
        "scheme": "bearer",
        "description": "Klucz API partnera, np. se24_live_…"
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "description": "Błąd.",
        "properties": {
          "error": {
            "type": "object",
            "description": "Opis błędu.",
            "properties": {
              "code": {
                "type": "string",
                "description": "Stabilny kod błędu.",
                "enum": [
                  "UNAUTHORIZED",
                  "FORBIDDEN",
                  "NOT_FOUND",
                  "VALIDATION_ERROR",
                  "CONFLICT",
                  "EXPIRED",
                  "NOT_READY",
                  "RATE_LIMITED",
                  "INTERNAL_ERROR"
                ]
              },
              "message": {
                "type": "string",
                "description": "Komunikat po polsku, nadaje się do pokazania użytkownikowi."
              },
              "field": {
                "type": "string",
                "description": "Pole, którego dotyczy błąd."
              },
              "details": {
                "description": "Szczegóły walidacji."
              }
            },
            "required": [
              "code",
              "message"
            ]
          }
        },
        "required": [
          "error"
        ]
      },
      "Price": {
        "type": "object",
        "description": "Cena zamówienia brutto, z VAT.",
        "properties": {
          "currency": {
            "type": "string",
            "description": "Waluta.",
            "enum": [
              "PLN"
            ]
          },
          "net": {
            "type": "number",
            "description": "Kwota netto."
          },
          "vat": {
            "type": "number",
            "description": "Kwota VAT."
          },
          "gross": {
            "type": "number",
            "description": "Kwota brutto — tyle zapłaci klient."
          },
          "vat_rate": {
            "type": "number",
            "description": "Stawka VAT, np. 0.23."
          },
          "items": {
            "type": "array",
            "description": "Pozycje ceny.",
            "items": {
              "type": "object",
              "description": "Pozycja.",
              "properties": {
                "name": {
                  "type": "string",
                  "description": "Nazwa pozycji."
                },
                "amount_gross": {
                  "type": "number",
                  "description": "Kwota brutto."
                },
                "type": {
                  "type": "string",
                  "description": "Rodzaj pozycji.",
                  "enum": [
                    "base",
                    "addon",
                    "discount"
                  ]
                }
              },
              "required": [
                "name",
                "amount_gross",
                "type"
              ]
            }
          }
        },
        "required": [
          "currency",
          "net",
          "vat",
          "gross",
          "vat_rate",
          "items"
        ]
      },
      "Certificate": {
        "type": "object",
        "description": "Wydane świadectwo. Wiążący jest dokument PDF.",
        "properties": {
          "number": {
            "anyOf": [
              {
                "type": "string",
                "description": "Numer świadectwa w centralnym rejestrze, np. SCHE/10388/2026/1000."
              },
              {
                "type": "null"
              }
            ]
          },
          "issued_on": {
            "anyOf": [
              {
                "type": "string",
                "description": "Data wystawienia.",
                "format": "date"
              },
              {
                "type": "null"
              }
            ]
          },
          "sent_at": {
            "type": "string",
            "description": "Kiedy świadectwo wysłaliśmy klientowi.",
            "format": "date-time"
          },
          "indicators": {
            "anyOf": [
              {
                "type": "object",
                "description": "Wskaźniki podawane w ogłoszeniu sprzedaży lub najmu.",
                "properties": {
                  "eu_kwh_m2_year": {
                    "type": "number",
                    "description": "Energia użytkowa EU, kWh/(m²·rok)."
                  },
                  "ek_kwh_m2_year": {
                    "type": "number",
                    "description": "Energia końcowa EK, kWh/(m²·rok)."
                  },
                  "ep_kwh_m2_year": {
                    "type": "number",
                    "description": "Nieodnawialna energia pierwotna EP, kWh/(m²·rok)."
                  },
                  "renewable_share_percent": {
                    "type": "number",
                    "description": "Udział odnawialnych źródeł energii, %."
                  },
                  "co2_emission_t_m2_year": {
                    "anyOf": [
                      {
                        "type": "number",
                        "description": "Emisja CO₂, t CO₂/(m²·rok)."
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "required": [
                  "eu_kwh_m2_year",
                  "ek_kwh_m2_year",
                  "ep_kwh_m2_year",
                  "renewable_share_percent",
                  "co2_emission_t_m2_year"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "listing_text": {
            "anyOf": [
              {
                "type": "string",
                "description": "Gotowy akapit ze wskaźnikami do opisu ogłoszenia."
              },
              {
                "type": "null"
              }
            ]
          },
          "pdf_url": {
            "anyOf": [
              {
                "type": "string",
                "description": "Adres pobrania PDF — tylko dla klucza z zakresem pdf.",
                "format": "uri"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "number",
          "issued_on",
          "sent_at",
          "indicators",
          "listing_text",
          "pdf_url"
        ]
      },
      "Order": {
        "type": "object",
        "description": "Zamówienie świadectwa.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Identyfikator zamówienia.",
            "format": "uuid"
          },
          "external_id": {
            "anyOf": [
              {
                "type": "string",
                "description": "Identyfikator oferty w systemie partnera."
              },
              {
                "type": "null"
              }
            ]
          },
          "agent_code": {
            "anyOf": [
              {
                "type": "string",
                "description": "Kod agenta biura, któremu przypisano zamówienie."
              },
              {
                "type": "null"
              }
            ]
          },
          "property_type": {
            "type": "string",
            "description": "Typ nieruchomości.",
            "enum": [
              "mieszkanie",
              "dom",
              "lokal-uzytkowy",
              "budynek-nieogrzewany"
            ]
          },
          "status": {
            "type": "string",
            "description": "requires_information — brakuje danych; ready_for_payment — komplet, czeka na klienta; payment_pending — klient w bramce płatniczej; paid — opłacone; in_progress — audytor pracuje; completed — świadectwo wysłane; cancelled — anulowane; expired — link wygasł.",
            "enum": [
              "requires_information",
              "ready_for_payment",
              "payment_pending",
              "paid",
              "in_progress",
              "completed",
              "cancelled",
              "expired"
            ]
          },
          "payment_status": {
            "type": "string",
            "description": "Stan płatności.",
            "enum": [
              "not_started",
              "pending",
              "paid",
              "failed",
              "cancelled"
            ]
          },
          "certificate_status": {
            "type": "string",
            "description": "Stan świadectwa.",
            "enum": [
              "not_started",
              "queued",
              "being_prepared",
              "ready",
              "sent"
            ]
          },
          "missing_fields": {
            "type": "array",
            "description": "Ścieżki pól, których brakuje. Klient uzupełni je w formularzu.",
            "items": {
              "type": "string"
            }
          },
          "price": {
            "$ref": "#/components/schemas/Price"
          },
          "form_url": {
            "type": "string",
            "description": "Formularz z danymi oferty — do otwarcia w nowej karcie.",
            "format": "uri"
          },
          "embed_url": {
            "type": "string",
            "description": "Ten sam formularz do osadzenia w ramce (iframe).",
            "format": "uri"
          },
          "created_at": {
            "type": "string",
            "description": "Utworzenie.",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "description": "Ostatnia zmiana.",
            "format": "date-time"
          },
          "expires_at": {
            "type": "string",
            "description": "Do kiedy działa link do formularza.",
            "format": "date-time"
          },
          "certificate": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Certificate"
              },
              {
                "type": "null"
              }
            ]
          },
          "invitation_sent": {
            "type": "boolean",
            "description": "Czy zaproszenie e-mailem wyszło — tylko w odpowiedzi na POST z send_invitation."
          }
        },
        "required": [
          "id",
          "external_id",
          "agent_code",
          "property_type",
          "status",
          "payment_status",
          "certificate_status",
          "missing_fields",
          "price",
          "form_url",
          "embed_url",
          "created_at",
          "updated_at",
          "expires_at"
        ]
      },
      "NewOrder": {
        "type": "object",
        "description": "Nowe zamówienie z danymi oferty.",
        "properties": {
          "property_type": {
            "type": "string",
            "description": "Typ nieruchomości.",
            "enum": [
              "mieszkanie",
              "dom",
              "lokal-uzytkowy",
              "budynek-nieogrzewany"
            ]
          },
          "external_id": {
            "type": "string",
            "description": "Identyfikator oferty w Twoim systemie — po nim znajdziesz zamówienie.",
            "maxLength": 120
          },
          "agent_code": {
            "type": "string",
            "description": "Kod agenta biura (3–12 liter i cyfr). Tylko klucze biur."
          },
          "customer": {
            "type": "object",
            "description": "Dane klienta (właściciela). Trafiają do formularza, klient może je poprawić.",
            "properties": {
              "first_name": {
                "type": "string",
                "description": "Imię."
              },
              "last_name": {
                "type": "string",
                "description": "Nazwisko."
              },
              "email": {
                "type": "string",
                "description": "Adres e-mail — na niego wyślemy świadectwo.",
                "format": "email"
              },
              "phone": {
                "type": "string",
                "description": "Telefon."
              }
            },
            "required": []
          },
          "address": {
            "type": "object",
            "description": "Adres nieruchomości.",
            "properties": {
              "street": {
                "type": "string",
                "description": "Ulica."
              },
              "building_number": {
                "type": "string",
                "description": "Numer budynku."
              },
              "apartment_number": {
                "type": "string",
                "description": "Numer lokalu."
              },
              "postal_code": {
                "type": "string",
                "description": "Kod pocztowy, np. 00-001."
              },
              "city": {
                "type": "string",
                "description": "Miejscowość."
              }
            },
            "required": []
          },
          "property": {
            "type": "object",
            "description": "Podstawowe dane techniczne z oferty.",
            "properties": {
              "area_m2": {
                "type": "number",
                "description": "Powierzchnia użytkowa w m²."
              },
              "height_m": {
                "type": "number",
                "description": "Wysokość pomieszczeń w metrach."
              },
              "year_built": {
                "type": "integer",
                "description": "Rok budowy."
              }
            },
            "required": []
          },
          "options": {
            "type": "object",
            "description": "Opcje dodatkowe.",
            "properties": {
              "paper_version": {
                "type": "boolean",
                "description": "Wersja papierowa: wydruk świadectwa z kodem QR do oryginału, wysłany na adres z zamówienia. Oryginałem jest zawsze PDF z podpisem elektronicznym."
              }
            },
            "required": []
          },
          "fields": {
            "type": "array",
            "maxItems": 100,
            "description": "Pozostałe pola formularza (ogrzewanie, okna, wentylacja…). Ścieżki i dozwolone wartości podaje GET /api/v1/fields/{property_type}.",
            "items": {
              "type": "object",
              "description": "Jedno pole formularza.",
              "properties": {
                "path": {
                  "type": "string",
                  "description": "Ścieżka pola, np. heating.heating."
                },
                "value": {
                  "description": "Wartość — tekst, liczba, wartość logiczna albo lista tekstów."
                }
              },
              "required": [
                "path",
                "value"
              ]
            }
          },
          "send_invitation": {
            "type": "boolean",
            "description": "Wyślij klientowi e-mail z linkiem do formularza w imieniu biura. Wymaga customer_consent i e-maila klienta."
          },
          "customer_consent": {
            "type": "boolean",
            "description": "Potwierdzenie, że klient zgodził się na kontakt w sprawie świadectwa."
          }
        },
        "required": [
          "property_type"
        ]
      },
      "OrderUpdate": {
        "type": "object",
        "description": "Uzupełnienie danych zamówienia.",
        "properties": {
          "customer": {
            "type": "object",
            "description": "Dane klienta (właściciela). Trafiają do formularza, klient może je poprawić.",
            "properties": {
              "first_name": {
                "type": "string",
                "description": "Imię."
              },
              "last_name": {
                "type": "string",
                "description": "Nazwisko."
              },
              "email": {
                "type": "string",
                "description": "Adres e-mail — na niego wyślemy świadectwo.",
                "format": "email"
              },
              "phone": {
                "type": "string",
                "description": "Telefon."
              }
            },
            "required": []
          },
          "address": {
            "type": "object",
            "description": "Adres nieruchomości.",
            "properties": {
              "street": {
                "type": "string",
                "description": "Ulica."
              },
              "building_number": {
                "type": "string",
                "description": "Numer budynku."
              },
              "apartment_number": {
                "type": "string",
                "description": "Numer lokalu."
              },
              "postal_code": {
                "type": "string",
                "description": "Kod pocztowy, np. 00-001."
              },
              "city": {
                "type": "string",
                "description": "Miejscowość."
              }
            },
            "required": []
          },
          "property": {
            "type": "object",
            "description": "Podstawowe dane techniczne z oferty.",
            "properties": {
              "area_m2": {
                "type": "number",
                "description": "Powierzchnia użytkowa w m²."
              },
              "height_m": {
                "type": "number",
                "description": "Wysokość pomieszczeń w metrach."
              },
              "year_built": {
                "type": "integer",
                "description": "Rok budowy."
              }
            },
            "required": []
          },
          "options": {
            "type": "object",
            "description": "Opcje dodatkowe.",
            "properties": {
              "paper_version": {
                "type": "boolean",
                "description": "Wersja papierowa: wydruk świadectwa z kodem QR do oryginału, wysłany na adres z zamówienia. Oryginałem jest zawsze PDF z podpisem elektronicznym."
              }
            },
            "required": []
          },
          "fields": {
            "type": "array",
            "maxItems": 100,
            "description": "Pozostałe pola formularza (ogrzewanie, okna, wentylacja…). Ścieżki i dozwolone wartości podaje GET /api/v1/fields/{property_type}.",
            "items": {
              "type": "object",
              "description": "Jedno pole formularza.",
              "properties": {
                "path": {
                  "type": "string",
                  "description": "Ścieżka pola, np. heating.heating."
                },
                "value": {
                  "description": "Wartość — tekst, liczba, wartość logiczna albo lista tekstów."
                }
              },
              "required": [
                "path",
                "value"
              ]
            }
          }
        },
        "required": []
      },
      "OrderList": {
        "type": "object",
        "description": "Lista zamówień.",
        "properties": {
          "count": {
            "type": "integer",
            "description": "Liczba pozycji."
          },
          "data": {
            "type": "array",
            "description": "Zamówienia od najnowszych.",
            "items": {
              "$ref": "#/components/schemas/Order"
            }
          }
        },
        "required": [
          "count",
          "data"
        ]
      },
      "Field": {
        "type": "object",
        "description": "Pole formularza.",
        "properties": {
          "path": {
            "type": "string",
            "description": "Ścieżka do użycia w fields[].path."
          },
          "label": {
            "type": "string",
            "description": "Nazwa pola po polsku."
          },
          "type": {
            "type": "string",
            "description": "Typ wartości.",
            "enum": [
              "string",
              "number",
              "boolean",
              "enum",
              "enum-array"
            ]
          },
          "required": {
            "type": "boolean",
            "description": "Czy pole jest wymagane do złożenia zamówienia."
          },
          "options": {
            "type": "array",
            "description": "Dozwolone wartości.",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "path",
          "label",
          "type",
          "required"
        ]
      },
      "FieldList": {
        "type": "object",
        "description": "Pola formularza dla typu nieruchomości.",
        "properties": {
          "property_type": {
            "type": "string",
            "description": "Typ nieruchomości.",
            "enum": [
              "mieszkanie",
              "dom",
              "lokal-uzytkowy",
              "budynek-nieogrzewany"
            ]
          },
          "count": {
            "type": "integer",
            "description": "Liczba pól."
          },
          "data": {
            "type": "array",
            "description": "Pola w kolejności formularza.",
            "items": {
              "$ref": "#/components/schemas/Field"
            }
          }
        },
        "required": [
          "property_type",
          "count",
          "data"
        ]
      },
      "Account": {
        "type": "object",
        "description": "Partner i klucz.",
        "properties": {
          "partner": {
            "type": "object",
            "description": "Partner.",
            "properties": {
              "name": {
                "type": "string",
                "description": "Nazwa partnera."
              },
              "type": {
                "type": "string",
                "description": "agency — biuro nieruchomości; affiliate — partner polecający.",
                "enum": [
                  "agency",
                  "affiliate"
                ]
              }
            },
            "required": [
              "name",
              "type"
            ]
          },
          "key": {
            "type": "object",
            "description": "Klucz API.",
            "properties": {
              "name": {
                "type": "string",
                "description": "Nazwa klucza."
              },
              "scopes": {
                "type": "array",
                "description": "Zakresy klucza.",
                "items": {
                  "type": "string",
                  "enum": [
                    "zamowienia",
                    "wyniki",
                    "pdf"
                  ]
                }
              }
            },
            "required": [
              "name",
              "scopes"
            ]
          },
          "prices": {
            "type": "array",
            "description": "Ceny bazowe, po których partner sprzedaje świadectwa.",
            "items": {
              "type": "object",
              "description": "Cena dla typu nieruchomości.",
              "properties": {
                "property_type": {
                  "type": "string",
                  "description": "Typ nieruchomości.",
                  "enum": [
                    "mieszkanie",
                    "dom",
                    "lokal-uzytkowy",
                    "budynek-nieogrzewany"
                  ]
                },
                "label": {
                  "type": "string",
                  "description": "Nazwa typu."
                },
                "base_price_gross_pln": {
                  "type": "number",
                  "description": "Cena bazowa brutto w PLN."
                }
              },
              "required": [
                "property_type",
                "label",
                "base_price_gross_pln"
              ]
            }
          }
        },
        "required": [
          "partner",
          "key",
          "prices"
        ]
      }
    }
  }
}