openapi: 3.1.0
info:
  title: HairHungary adatkiviteli és szolgáltatóváltási felületek
  version: 2026-08-02.1
  license:
    name: Nyilvános műszaki dokumentáció; a rendszer szerzői jogvédelem alatt áll
    identifier: LicenseRef-Proprietary
  description: |
    A HairHungary rendszer dokumentált, hitelesített adatkiviteli felületei.
    A dokumentáció nem ad nyilvános hozzáférést ügyféladatokhoz. Átvevő
    szolgáltató csak a Hair-Aesthetic Clinic Kft. kifejezett meghatalmazása,
    időkorlátos és célhoz kötött hitelesítés, valamint naplózott átadás mellett
    kaphat hozzáférést. A dokumentáció és a váltáshoz szükséges felületi
    hozzáférés külön díj nélkül áll rendelkezésre.
servers:
  - url: https://crm.hairhungary.hu
    description: |
      Tervezett kanonikus éles cím. A teljes atomi export alapból tiltott,
      amíg a DNS, a production séma, a kiadási eredet és a kapcsolódó
      biztonsági kapuk igazoltan le nem zárultak.
tags:
  - name: Teljes adatkivitel
    description: Atomi, teljes, ellenőrzőösszeggel védett váltási adatcsomag.
  - name: Működési export
    description: Szerepkörhöz igazított, szűrhető üzleti adatkivitel.
  - name: Kilépési protokoll
    description: Az adatkiadás, átadás és törlés életciklusának naplózott kezelése.
paths:
  /api/backup/export:
    get:
      tags: [Teljes adatkivitel]
      summary: Atomi, teljes JSON-adatcsomag előállítása
      description: |
        Egyetlen PostgreSQL-utasítás pillanatképéből készülő, 33 táblás,
        táblánkénti és teljes SHA-256 ellenőrzőösszeggel ellátott JSON-csomag.
        Kizárólag külön exporttitokkal és a kanonikus production eredet,
        Supabase-projekt, megváltoztathatatlan kiadási azonosító és
        sémaátállási tanúsítás egyezése esetén működik. Bármely hiány vagy
        eltérés esetén adatcsomag létrehozása nélkül, alapból tiltó módon áll le.
      operationId: exportAtomicSnapshot
      security:
        - backupExportSecret: []
      responses:
        "200":
          description: Ellenőrzött, teljes atomi export.
          headers:
            Content-Disposition:
              schema: { type: string }
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AtomicExport"
        "401":
          description: Hiányzó vagy hibás exporttitok.
        "503":
          description: |
            Az export nincs konfigurálva, vagy a kanonikus eredet, projekt,
            kiadási eredet, séma, atomi pillanatkép vagy tanúsítás nem egyezik.
  /api/export:
    get:
      tags: [Működési export]
      summary: Szerepkörhöz igazított érdeklődői XLSX-export
      description: |
        A hitelesített felhasználó jogosultságához igazodó, szűrhető
        érdeklődői export. A pénzügyi és forrásmezők csak arra jogosult
        szerepkörnél szerepelnek.
      operationId: exportLeadsXlsx
      security:
        - applicationSession: []
      parameters:
        - { name: region, in: query, schema: { type: string } }
        - { name: treatment_type, in: query, schema: { type: string } }
        - { name: source, in: query, schema: { type: string } }
        - { name: status, in: query, schema: { type: string } }
        - { name: language, in: query, schema: { type: string } }
        - { name: date_from, in: query, schema: { type: string, format: date } }
        - { name: date_to, in: query, schema: { type: string, format: date } }
      responses:
        "200":
          description: Jogosultsághoz igazított XLSX-fájl.
          content:
            application/vnd.openxmlformats-officedocument.spreadsheetml.sheet:
              schema: { type: string, contentEncoding: binary }
        "401": { description: Nincs hitelesített felhasználó. }
        "403": { description: A szerepkör nem jogosult adatkivitelre. }
  /api/export-protokoll:
    get:
      tags: [Kilépési protokoll]
      summary: Adatkiadási folyamatok lekérése
      operationId: listExportProtocols
      security:
        - applicationSession: []
      responses:
        "200":
          description: Adatkiadási folyamatbejegyzések.
          content:
            application/json:
              schema:
                type: array
                items: { $ref: "#/components/schemas/ExportProtocolEntry" }
        "401": { description: Nincs hitelesített felhasználó. }
    post:
      tags: [Kilépési protokoll]
      summary: Új adatkiadási folyamat létrehozása
      operationId: createExportProtocol
      security:
        - applicationSession: []
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: "#/components/schemas/ExportProtocolCreate" }
      responses:
        "201":
          description: Létrehozott folyamat.
          content:
            application/json:
              schema: { $ref: "#/components/schemas/ExportProtocolEntry" }
        "400": { description: Érvénytelen vagy hiányos adat. }
        "401": { description: Nincs hitelesített felhasználó. }
    patch:
      tags: [Kilépési protokoll]
      summary: Adatkiadási folyamat állapotának módosítása
      operationId: updateExportProtocol
      security:
        - applicationSession: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: "#/components/schemas/ExportProtocolPatch"
      responses:
        "200":
          description: Frissített folyamat.
          content:
            application/json:
              schema: { $ref: "#/components/schemas/ExportProtocolEntry" }
        "400": { description: Érvénytelen vagy nem módosítható mező. }
        "401": { description: Nincs hitelesített felhasználó. }
        "404": { description: A bejegyzés nem található. }
components:
  securitySchemes:
    applicationSession:
      type: apiKey
      in: cookie
      name: hairhungary_session
      description: Név szerinti, szerepkörhöz kötött alkalmazás-munkamenet.
    backupExportSecret:
      type: apiKey
      in: header
      name: x-backup-secret
      description: Elkülönített, időkorlátosan átadható exporttitok.
  schemas:
    AtomicExport:
      type: object
      required: [schemaVersion, generatedAt, canonicalOrigin, projectRef, releaseCommit, snapshot, tableCount, counts, tableSha256, contentSha256, tables]
      properties:
        schemaVersion: { type: integer, const: 2 }
        generatedAt: { type: string, format: date-time }
        canonicalOrigin: { type: string, format: uri }
        projectRef: { type: string }
        releaseCommit: { type: string, pattern: "^[a-f0-9]{40}$" }
        snapshot: { type: object, additionalProperties: true }
        tableCount: { type: integer, const: 33 }
        counts: { type: object, additionalProperties: { type: integer, minimum: 0 } }
        tableSha256: { type: object, additionalProperties: { type: string, pattern: "^[a-f0-9]{64}$" } }
        contentSha256: { type: string, pattern: "^[a-f0-9]{64}$" }
        tables: { type: object, additionalProperties: { type: array, items: { type: object, additionalProperties: true } } }
    ExportProtocolCreate:
      type: object
      required: [trigger, format, data_scope]
      properties:
        trigger:
          type: string
          enum: [szerzodes_megszunes, erintetti_kerelem, rendszeres_export]
        format: { type: string, enum: [csv, xlsx, json] }
        data_scope:
          type: array
          minItems: 1
          maxItems: 50
          items: { type: string, minLength: 1, maxLength: 120 }
        requested_at: { type: string, format: date-time }
        export_deadline: { type: string, format: date-time }
        status: { type: string, enum: [keszult, atadva, torles_folyamatban, torolve] }
        note: { type: string, maxLength: 4000 }
    ExportProtocolPatch:
      type: object
      required: [id]
      properties:
        id: { type: string }
        checklist_complete: { type: boolean }
        export_deadline: { type: string, format: date-time }
        delivered_at: { type: string, format: date-time }
        deletion_certificate_issued: { type: boolean }
        deletion_at: { type: string, format: date-time }
        retained_for_legal_reason: { type: string, maxLength: 4000 }
        status: { type: string, enum: [keszult, atadva, torles_folyamatban, torolve] }
        note: { type: string, maxLength: 4000 }
      additionalProperties: false
    ExportProtocolEntry:
      allOf:
        - $ref: "#/components/schemas/ExportProtocolCreate"
        - type: object
          required: [id, requested_at, export_deadline, checklist_complete, deletion_certificate_issued, status]
          properties:
            id: { type: string }
            checklist_complete: { type: boolean }
            delivered_at: { type: string, format: date-time }
            deletion_certificate_issued: { type: boolean }
            deletion_at: { type: string, format: date-time }
            retained_for_legal_reason: { type: string }
