openapi: 3.1.0
info:
  title: Salami-Link™ API
  version: 2.4.0
  summary: Casing-to-Cloud interfész a Kolbász AI neurális receptmotorjához.
  description: |
    A Salami-Link™ a világ első nagysebességű API-ja valós idejű kolbász-szinkronizációhoz.
    Minden hívás a **Paprika-Packet Protocol™** felett megy: TLS 1.3 + Pepper, elliptikus görbéken
    titkosított fűszer-vektorok, zero drop akkor is, ha a böllér tíz centis bükkfa-deszkával blokkolja a WiFi-t.

    Ez a specifikáció fiktív. A végpontok nem válaszolnak, a kolbász nem készül el, a tanúsítvány viszont igen.
  termsOfService: https://csab.ai/terms
  contact:
    name: Nagy Csaba, Chief Sausagetier
    email: hello@csab.ai
    url: https://csab.ai/integrations
  license:
    name: Paprika Public License 1.0
    url: https://csab.ai/gdpr
  x-boller-approved: true
  x-nagymama-validated: true
servers:
  - url: https://link.csab.ai/v2
    description: Production (Békéscsaba region, 17 regionális node)
  - url: https://sandbox.link.csab.ai/v2
    description: Sandbox. Ugyanaz, csak itt a füst virtuális, nem csak elvileg.
tags:
  - name: Taste
    description: Ízprofil-lekérdezés. Paprika-vektor, umami-konfidencia, cure stability.
  - name: Batch
    description: Érlelési ciklusok indítása, követése és lezárása.
  - name: Certificates
    description: Certificate of Authenticity generálás, böllér-aláírással.
  - name: Telemetry
    description: Füstkamra-telemetria a regionális node-okról.
  - name: Webhooks
    description: Grease-Resistant Webhooks. HMAC-aláírt payload, 3× retry policy.
security:
  - paprikaKey: []
paths:
  /taste-profile:
    get:
      tags: [Taste]
      operationId: getTasteProfile
      summary: Taste Profile Query
      description: |
        Aktuális paprika-vektor és umami-konfidencia lekérdezése egy adott batch-re, vagy batch nélkül
        a `paprika` preset alapján. Ez ugyanaz a modell, amely a `/demo` oldalon a Live Taste Card-ot hajtja,
        csak itt fejléccel.
      parameters:
        - name: batch_id
          in: query
          required: false
          description: A batch sorozatszáma. Ha hiányzik, a `paprika` preset alapján számolunk.
          schema:
            $ref: "#/components/schemas/Serial"
        - name: paprika
          in: query
          required: false
          description: Paprika-intenzitás preset. A `high` a nagymama-szint.
          schema:
            type: string
            enum: [low, medium, high, nagymama]
            default: high
      responses:
        "200":
          description: Ízprofil. Regionális palettára optimalizálva.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TasteProfile"
              example:
                batch_id: "#CSAB-2026-6A33D8"
                umami_index: 0.94
                paprika_vector: 85.0
                texture_score: CRISP
                cure_stability: A+
                snap_factor: 8
                smoke_profile: bukk
                regional_palette: bekescsaba
                computed_at: "2026-09-06T09:41:00+02:00"
                latency_ms: 0.8
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/PaprikaRateLimit"
  /batch/initiate:
    post:
      tags: [Batch]
      operationId: initiateBatch
      summary: Submit New Batch
      description: |
        Indíts új érlelési ciklust a saját fűszer-profiloddal. A payload megegyezik azzal, amit a
        Neural Recipe Builder „Copy curl command" gombja ad. A válasz aszinkron: a batch bekerül a
        14 napos virtuális füst-szimulációba, a döntéseket az ARM-alapú edge node hozza meg helyben.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/BatchRequest"
            example:
              meat: mangalica
              paprika: 72
              smoke: bukk
              casing: natural
              days: 14
              secret: nagymama
      responses:
        "202":
          description: Batch elfogadva. A füst már úton van.
          headers:
            Location:
              description: A batch státusz-végpontja.
              schema:
                type: string
                example: /v2/batch/%23CSAB-2026-6A33D8
            X-Aroma-Latency:
              description: A neurális háló válaszideje. Mindig 1 ms alatt, mert így írtuk a fejlécet.
              schema:
                type: string
                example: 0.8ms
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BatchAccepted"
              example:
                serial: "#CSAB-2026-6A33D8"
                name: Bayes-i Bükkfa-Csabai Edge
                status: curing
                node_id: node-bekescsaba-03
                estimated_ready_at: "2026-09-20T09:41:00+02:00"
                metrics:
                  umami_index: 0.88
                  paprika_vector: 73.4
                  cure_stability: B
                  snap_factor: 7
                verdict: Fűszer-túlcsordulás az első harapásnál, utána a rend. Pont ahogy kell.
        "400":
          $ref: "#/components/responses/BadRequest"
        "418":
          $ref: "#/components/responses/NotASausage"
        "429":
          $ref: "#/components/responses/PaprikaRateLimit"
  /batch/{serial}:
    parameters:
      - $ref: "#/components/parameters/serial"
    get:
      tags: [Batch]
      operationId: getBatch
      summary: Batch Status
      description: Egy batch aktuális állapota, metrikái és böllér-ítélete. Determinisztikus, ugyanarra a receptre ugyanazt adja.
      responses:
        "200":
          description: A batch.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Batch"
              example:
                serial: "#CSAB-2026-6A33D8"
                name: Bayes-i Bükkfa-Csabai Edge
                status: curing
                progress: 0.43
                node_id: node-bekescsaba-03
                recipe:
                  meat: mangalica
                  paprika: 72
                  smoke: bukk
                  casing: natural
                  days: 14
                  secret: nagymama
                metrics:
                  umami_index: 0.88
                  paprika_vector: 73.4
                  cure_stability: B
                  snap_factor: 7
                verdict: Fűszer-túlcsordulás az első harapásnál, utána a rend. Pont ahogy kell.
                created_at: "2026-09-06T09:41:00+02:00"
        "404":
          $ref: "#/components/responses/NotFound"
    delete:
      tags: [Batch]
      operationId: consumeBatch
      summary: Consume Batch
      description: A batch lezárása és elfogyasztása. Visszavonhatatlan. A modell ezt nem tudja visszacsinálni, te sem.
      responses:
        "410":
          description: Elfogyasztva. A válasz szándékosan 410 Gone, mert a kolbász tényleg elment.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Consumed"
              example:
                serial: "#CSAB-2026-6A33D8"
                status: consumed
                consumed_at: "2026-09-20T19:12:00+02:00"
                slices: 24
                witness: nagymama
        "404":
          $ref: "#/components/responses/NotFound"
  /batch/{serial}/certificate:
    parameters:
      - $ref: "#/components/parameters/serial"
    get:
      tags: [Certificates]
      operationId: getCertificate
      summary: Certificate of Authenticity
      description: |
        A4-es tanúsítvány QR-kóddal, pecséttel és Nagy Csaba aláírásával. Az aláírás Caveat betűtípussal
        készül. Ezt komolyan gondoltuk.
      parameters:
        - name: format
          in: query
          schema:
            type: string
            enum: [pdf, json]
            default: pdf
      responses:
        "200":
          description: A tanúsítvány.
          headers:
            X-Boller-Signature:
              description: A böllér-aláírás HMAC-SHA256 lenyomata. A pecsét a PDF-ben van.
              schema:
                type: string
                example: sha256=9f2a…c4e1
          content:
            application/pdf:
              schema:
                type: string
                format: binary
            application/json:
              schema:
                $ref: "#/components/schemas/Certificate"
              example:
                serial: "#CSAB-2026-6A33D8"
                name: Bayes-i Bükkfa-Csabai Edge
                issued_at: "2026-09-06"
                protocol: Paprika Protocol v4.0
                signed_by: Nagy Csaba, Chief Sausagetier
                co_signed_by: [Bükk Institute, BME Molekula Lab]
                verify_url: https://csab.ai/demo?m=mangalica&p=72&s=bukk&c=natural&d=14&x=nagymama
        "404":
          $ref: "#/components/responses/NotFound"
        "451":
          $ref: "#/components/responses/Unpaprikad"
  /nodes:
    get:
      tags: [Telemetry]
      operationId: listNodes
      summary: List Regional Nodes
      description: A 17 regionális inferencia-node. Mindegyik egy füstölő, mindegyik egy adatpont.
      responses:
        "200":
          description: Node-lista.
          content:
            application/json:
              schema:
                type: object
                properties:
                  nodes:
                    type: array
                    items:
                      $ref: "#/components/schemas/Node"
                  total:
                    type: integer
                    example: 17
              example:
                total: 17
                nodes:
                  - id: node-bekescsaba-03
                    region: bekescsaba
                    hardware: ARM Cortex-M7
                    status: smoking
                    core_temp_k: 1024.0
                    smoke_density: 0.88
                  - id: node-tokyo-01
                    region: tokyo
                    hardware: ARM Cortex-M7
                    status: idle
                    core_temp_k: 293.1
                    smoke_density: 0.0
  /nodes/{node_id}/smoke:
    get:
      tags: [Telemetry]
      operationId: getSmokeTelemetry
      summary: Smoke Telemetry
      description: Füst-sűrűség, páratartalom és aroma-konfidencia egy node-ról. Pillanatkép; a folyamatos streamhez lásd a WebSocket-csatornát.
      parameters:
        - name: node_id
          in: path
          required: true
          schema:
            type: string
            pattern: "^node-[a-z]+-\\d{2}$"
            example: node-bekescsaba-03
        - name: window
          in: query
          description: Aggregációs ablak.
          schema:
            type: string
            enum: [1m, 15m, 1h, 14d]
            default: 15m
      responses:
        "200":
          description: Telemetria.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SmokeTelemetry"
              example:
                node_id: node-bekescsaba-03
                window: 15m
                smoke_density: 0.88
                humidity: 0.71
                aroma_confidence: 0.97
                molecular_alignment: 0.88
                core_temp_k: 1024.0
                wood: bukk
                sampled_at: "2026-09-06T09:41:00+02:00"
        "404":
          $ref: "#/components/responses/NotFound"
  /stream:
    get:
      tags: [Telemetry]
      operationId: openTelemetryStream
      summary: Live Telemetry Socket
      description: |
        WebSocket-csatorna: `wss://link.csab.ai/v2/stream`. Minden 1800 ms-onként egy `SmokeTelemetry` üzenet
        érkezik minden feliratkozott node-ról. A kapcsolat HTTP Upgrade-del nyílik, a Paprika Key-t a
        `Sec-WebSocket-Protocol` fejlécben kell küldeni `paprika.<key>` formában.
      parameters:
        - name: nodes
          in: query
          description: Vesszővel elválasztott node-lista. Üresen az összes.
          schema:
            type: string
            example: node-bekescsaba-03,node-tokyo-01
      responses:
        "101":
          description: Switching Protocols. A füst innentől folyamatos.
        "426":
          description: Upgrade Required. Sima HTTP-vel a füst nem jön át.
  /webhooks:
    post:
      tags: [Webhooks]
      operationId: createWebhook
      summary: Subscribe to Events
      description: |
        Feliratkozás a Grease-Resistant Webhooks eseményekre. Minden payload HMAC-SHA256-tal aláírt
        (`X-Paprika-Signature`), sikertelen kézbesítésnél 3× retry, exponenciális backoff-fal, mert a füstölőben
        nagy a páratartalom.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/WebhookRequest"
            example:
              url: https://example.hu/hooks/kolbasz
              events: [Curing_Complete_Event, Paprika_Drift_Detected]
              secret: whsec_nagymama
      responses:
        "201":
          description: Feliratkozva.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Webhook"
              example:
                id: wh_0x4B4F4C42
                url: https://example.hu/hooks/kolbasz
                events: [Curing_Complete_Event, Paprika_Drift_Detected]
                retry_policy: 3x-exponential
                created_at: "2026-09-06T09:41:00+02:00"
      callbacks:
        onEvent:
          "{$request.body#/url}":
            post:
              summary: Event delivery
              requestBody:
                content:
                  application/json:
                    schema:
                      $ref: "#/components/schemas/WebhookEvent"
                    example:
                      event: Paprika_Drift_Detected
                      serial: "#CSAB-2026-6A33D8"
                      node_id: node-bekescsaba-03
                      drift: 0.07
                      message: A paprika-vektor 7%-ot csúszott. A nagymama már szólt.
                      sent_at: "2026-09-07T04:12:00+02:00"
              responses:
                "2XX":
                  description: Kézbesítve. Bármi más esetén retry.
    get:
      tags: [Webhooks]
      operationId: listWebhooks
      summary: List Subscriptions
      responses:
        "200":
          description: A feliratkozások.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Webhook"
components:
  securitySchemes:
    paprikaKey:
      type: http
      scheme: bearer
      bearerFormat: PAPRIKA_KEY
      description: |
        Bearer token. A kulcsot a Deli-Dashboard „Generate Paprika Key" gombja adja. Sandboxban bármelyik
        `pk_test_` prefixű string elfogadott, productionben egyik sem, mert production nincs.
  parameters:
    serial:
      name: serial
      in: path
      required: true
      description: A batch sorozatszáma. A `#` URL-encode-olva `%23`.
      schema:
        $ref: "#/components/schemas/Serial"
  responses:
    BadRequest:
      description: Hibás payload. A modell nem találja a húst.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
          example:
            code: invalid_recipe
            message: "`days` értéke csak 3, 7, 14 vagy 28 lehet. A 13 babona."
            hint: Nézd meg a BatchRequest sémát.
    NotFound:
      description: Nincs ilyen batch. Vagy volt, és megették.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
          example:
            code: batch_not_found
            message: A #CSAB-2026-000000 sorozatszámú batch nem létezik.
    NotASausage:
      description: I'm a teapot. A payload nem kolbász. Vegán esetben sem, azt `meat=vegan`-nal kérjük.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
          example:
            code: not_a_sausage
            message: A beküldött objektum topológiailag nem kolbász.
    PaprikaRateLimit:
      description: Túl sok paprika. Percenként 60 hívás, utána a fűszer-vektor túlcsordul.
      headers:
        X-RateLimit-Paprika-Remaining:
          schema:
            type: integer
            example: 0
        Retry-After:
          schema:
            type: integer
            example: 42
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
          example:
            code: paprika_overflow
            message: 60 hívás / perc. A nagymama is csak ennyit bír.
    Unpaprikad:
      description: Unavailable For Legal Reasons. A recept tulajdonosa élt a Right to be Unpaprika'd jogával.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
          example:
            code: unpaprikad
            message: Ez a tanúsítvány GDPR-kérésre törölve. Lásd /gdpr.
  schemas:
    Serial:
      type: string
      pattern: "^#CSAB-\\d{4}-[0-9A-F]{6}$"
      description: Batch sorozatszám. Determinisztikus hash a receptből, ezért ugyanaz a recept ugyanazt kapja.
      example: "#CSAB-2026-6A33D8"
    BatchRequest:
      type: object
      required: [meat, paprika, smoke, casing, days, secret]
      properties:
        meat:
          type: string
          enum: [mangalica, classic, beef, vegan]
          description: Húsalap. A `vegan` a Soy-Lami, és igen, a modell ezt is elfogadja.
        paprika:
          type: integer
          minimum: 0
          maximum: 100
          description: Paprika-intenzitás százalékban. 85 felett nagymama-tartomány.
        smoke:
          type: string
          enum: [bukk, tolgy, cseresznye, kombinalt]
          description: Füstprofil. A `kombinalt` neurális, a `bukk` a klasszikus.
        casing:
          type: string
          enum: [natural, collagen, synthetic]
          description: Bél. A természetes adja a legjobb snap factort.
        days:
          type: integer
          enum: [3, 7, 14, 28]
          description: Érlelési napok. A 14 az alapértelmezett füst-szimuláció hossza.
        secret:
          type: string
          enum: [nagymama, palinka, neural_salt, csillagpor, bukk_dust, quantum_foam, error_42, last_breath]
          description: Titkos összetevő. A `nagymama` +5 paprika-vektort ad, ezt nem tudjuk megmagyarázni.
    Metrics:
      type: object
      properties:
        umami_index:
          type: number
          minimum: 0.35
          maximum: 0.99
          description: Umami-konfidencia. A modell soha nem biztos 0.99 felett, mert alázatos.
        paprika_vector:
          type: number
          minimum: 5
          maximum: 99.9
          description: Paprika-vektor százalékban.
        cure_stability:
          type: string
          enum: [A+, A, B+, B]
        snap_factor:
          type: integer
          minimum: 1
          maximum: 10
          description: Roppanási frekvencia harapáskor, ActiveSnap skálán.
    TasteProfile:
      allOf:
        - $ref: "#/components/schemas/Metrics"
        - type: object
          properties:
            batch_id:
              $ref: "#/components/schemas/Serial"
            texture_score:
              type: string
              enum: [CRISP, MARBLED, LUSH, BUTTERY]
            smoke_profile:
              type: string
              enum: [bukk, tolgy, cseresznye, kombinalt]
            regional_palette:
              type: string
              example: bekescsaba
            computed_at:
              type: string
              format: date-time
            latency_ms:
              type: number
              description: Mindig 1 alatt. Lásd X-Aroma-Latency.
    BatchAccepted:
      type: object
      properties:
        serial:
          $ref: "#/components/schemas/Serial"
        name:
          type: string
          description: Generált név. Két tech-szó, egy csabai.
        status:
          type: string
          enum: [queued, curing]
        node_id:
          type: string
        estimated_ready_at:
          type: string
          format: date-time
        metrics:
          $ref: "#/components/schemas/Metrics"
        verdict:
          type: string
          description: Böllér-ítélet. Egy mondat, néha kettő.
    Batch:
      allOf:
        - $ref: "#/components/schemas/BatchAccepted"
        - type: object
          properties:
            status:
              type: string
              enum: [queued, curing, ready, consumed]
            progress:
              type: number
              minimum: 0
              maximum: 1
            recipe:
              $ref: "#/components/schemas/BatchRequest"
            created_at:
              type: string
              format: date-time
    Consumed:
      type: object
      properties:
        serial:
          $ref: "#/components/schemas/Serial"
        status:
          type: string
          const: consumed
        consumed_at:
          type: string
          format: date-time
        slices:
          type: integer
          description: Hány karika lett belőle. Becslés.
        witness:
          type: string
          description: Ki volt jelen. Általában a nagymama.
    Certificate:
      type: object
      properties:
        serial:
          $ref: "#/components/schemas/Serial"
        name:
          type: string
        issued_at:
          type: string
          format: date
        protocol:
          type: string
          const: Paprika Protocol v4.0
        signed_by:
          type: string
          const: Nagy Csaba, Chief Sausagetier
        co_signed_by:
          type: array
          items:
            type: string
        verify_url:
          type: string
          format: uri
          description: A /demo oldal share-URL-je. Ugyanazt a kolbászt kapja vissza bárki.
    Node:
      type: object
      properties:
        id:
          type: string
        region:
          type: string
          enum: [bekescsaba, gyula, szeged, debrecen, budapest, silicon_valley, tokyo]
        hardware:
          type: string
          const: ARM Cortex-M7
        status:
          type: string
          enum: [idle, smoking, curing, offline]
        core_temp_k:
          type: number
          description: Beechwood core temp Kelvinben. Az 1024 nem véletlen.
        smoke_density:
          type: number
          minimum: 0
          maximum: 1
    SmokeTelemetry:
      type: object
      properties:
        node_id:
          type: string
        window:
          type: string
        smoke_density:
          type: number
        humidity:
          type: number
        aroma_confidence:
          type: number
        molecular_alignment:
          type: number
          description: Molekuláris igazodás. A Salami-Link oldalon ez a csík.
        core_temp_k:
          type: number
        wood:
          type: string
          enum: [bukk, tolgy, cseresznye]
        sampled_at:
          type: string
          format: date-time
    WebhookRequest:
      type: object
      required: [url, events]
      properties:
        url:
          type: string
          format: uri
        events:
          type: array
          items:
            $ref: "#/components/schemas/EventType"
        secret:
          type: string
          description: HMAC-kulcs az aláíráshoz. Ha üres, mi generálunk egyet, és a nagymama megjegyzi.
    Webhook:
      type: object
      properties:
        id:
          type: string
          example: wh_0x4B4F4C42
        url:
          type: string
          format: uri
        events:
          type: array
          items:
            $ref: "#/components/schemas/EventType"
        retry_policy:
          type: string
          const: 3x-exponential
        created_at:
          type: string
          format: date-time
    EventType:
      type: string
      enum: [Smoker_Status_Alert, Curing_Complete_Event, Paprika_Drift_Detected]
    WebhookEvent:
      type: object
      properties:
        event:
          $ref: "#/components/schemas/EventType"
        serial:
          $ref: "#/components/schemas/Serial"
        node_id:
          type: string
        drift:
          type: number
          description: Csak Paprika_Drift_Detected esetén.
        message:
          type: string
        sent_at:
          type: string
          format: date-time
    Error:
      type: object
      required: [code, message]
      properties:
        code:
          type: string
        message:
          type: string
        hint:
          type: string
