openapi: 3.1.0
info:
  title: Kasseneck API
  version: "2.0.0"
  summary: Österreichische Registrierkassen-/RKSV-API für Belegerstellung und -abruf.
  description: |
    Die **Kasseneck API** ist eine HTTPS-Schnittstelle für österreichische
    Registrierkassen nach **RKSV** (Registrierkassensicherheitsverordnung,
    BAO §131, BMF-DEP). Damit erstellst du signierte Belege (Startbeleg,
    Umsatzbeleg, Storno, Training, Nullbeleg), rufst Belege ab und lädst
    Beleg-PDFs.

    Kasseneck ist ein Produkt der **Kreiseck** und richtet sich an POS-/
    Kassensysteme, Kassenhersteller und Integrationspartner in Österreich.

    Für Flutter/Dart gibt es das offizielle Paket
    [`kasseneck_api`](https://pub.dev/packages/kasseneck_api) auf pub.dev.

    ## Authentifizierung
    Geräte-Endpunkte nutzen zwei Merkmale:
    - `Authorization: Bearer <api_key>` — der Geräte-/API-Schlüssel (Format
      `kr_live_…` bzw. `kr_test_…` für die Testumgebung).
    - `cashregister-token: <token>` — der Kassen-Token (Format `cb_live_…` /
      `cb_test_…`), identifiziert die konkrete Registrierkasse.

    ## Umgebungen
    - **Live:** echte, rechtsgültige RKSV-Belege (Schlüssel `kr_live_…`).
    - **Test:** Sandbox mit Testsignatur (`kr_test_…`), `production:false` —
      strukturell valide, aber keine rechtsgültigen Signaturen. Ideal zum
      Integrieren ohne echte steuerliche Wirkung.

    ## Antwortformat
    Alle JSON-Endpunkte liefern HTTP 200 mit einem Envelope:
    `{ "status": "success" | "error", "message": string, "data": object }`.
    Fachliche Fehler kommen ebenfalls mit HTTP 200 und `status: "error"`.

    ## Versionen
    Empfohlen ist **v2** (`/v2/…`) mit der Positionsform
    `{ name, quantity, unitPriceCents, vatRate }` — Preise in **ganzen Cent**
    (keine Fließkommazahlen). Die **v1**-Endpunkte (`/v1/…`) und die v1-Positionsform
    (`amount`, `priceOne`, `vat`) bleiben aus Kompatibilität gültig (deprecated).
  contact:
    name: Kasseneck
    url: https://api.kasseneck.at
  license:
    name: Proprietär
servers:
  - url: https://api.kasseneck.at
    description: Produktion
externalDocs:
  description: Offizielles Dart/Flutter-Paket auf pub.dev
  url: https://pub.dev/packages/kasseneck_api
tags:
  - name: Belege
    description: Belege erstellen, abrufen und als PDF laden.
paths:
  /v2/createReceipt:
    post:
      operationId: createReceipt
      tags: [Belege]
      summary: Beleg erstellen und RKSV-signieren
      description: |
        Erstellt einen Beleg und signiert ihn (ES256, verkettete RKSV-Signatur →
        DEP). **Der erste Beleg einer Kasse muss ein `start`-Beleg sein** und
        erfolgreich signiert werden; danach `standard`-Belege usw.

        Voraussetzung: aktives Modul `registrierkasse` für das Konto.

        Hinweis: `receiptId` und Zeitstempel werden serverseitig vergeben.
      security:
        - ApiKeyAuth: []
          CashregisterToken: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [params]
              properties:
                params:
                  $ref: '#/components/schemas/CreateReceiptParams'
            examples:
              startbeleg:
                summary: Startbeleg (einmalig zuerst)
                value: { params: { receiptType: start } }
              umsatzbeleg:
                summary: Standard-Umsatzbeleg (bar)
                value:
                  params:
                    receiptType: standard
                    paymentMethod: cash
                    items:
                      - { name: "Kaffee", quantity: 2, unitPriceCents: 350, vatRate: 20 }
                      - { name: "Brot", quantity: 1, unitPriceCents: 220, vatRate: 10 }
      responses:
        "200":
          description: Envelope mit signiertem Beleg oder Fehler.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ReceiptEnvelope'
  /v2/getReceipt:
    post:
      operationId: getReceipt
      tags: [Belege]
      summary: Beleg abrufen
      description: Liefert einen zuvor erstellten Beleg der Kasse anhand seiner `receiptId`.
      security:
        - ApiKeyAuth: []
          CashregisterToken: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [params]
              properties:
                params:
                  type: object
                  required: [receiptId]
                  properties:
                    receiptId:
                      type: string
                      description: ID des Belegs (aus der createReceipt-Antwort).
            examples:
              abruf:
                value: { params: { receiptId: "abc123" } }
      responses:
        "200":
          description: Envelope mit dem Beleg oder Fehler.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ReceiptEnvelope'
  /v2/downloadReceipt:
    get:
      operationId: downloadReceipt
      tags: [Belege]
      summary: Beleg-PDF laden (Capability-Link)
      description: |
        Liefert das Beleg-PDF direkt (`application/pdf`). Autorisierung erfolgt
        ausschließlich über den verschlüsselten `fullReceiptId`-Token aus der
        createReceipt-Antwort — kein API-Schlüssel nötig. Der Token ist ein
        Capability-Link (wer ihn hat, sieht das PDF).
      security: []
      parameters:
        - name: fullReceiptId
          in: query
          required: true
          schema:
            type: string
          description: Verschlüsselter Beleg-Token aus `data.receipt.fullReceiptId`.
      responses:
        "200":
          description: PDF-Datei.
          content:
            application/pdf:
              schema:
                type: string
                format: binary
        "400":
          description: Beleg-Link unvollständig.
        "404":
          description: User oder Beleg nicht gefunden.
components:
  securitySchemes:
    ApiKeyAuth:
      type: http
      scheme: bearer
      description: Geräte-/API-Schlüssel im Bearer-Header (`kr_live_…` / `kr_test_…`).
    CashregisterToken:
      type: apiKey
      in: header
      name: cashregister-token
      description: Kassen-Token der Registrierkasse (`cb_live_…` / `cb_test_…`).
  schemas:
    CreateReceiptParams:
      type: object
      required: [receiptType]
      properties:
        receiptType:
          type: string
          enum: [start, standard, zero, cancellation, training]
          description: |
            `start` = Startbeleg (einmalig zuerst, ohne Positionen).
            `standard` = Umsatzbeleg. `cancellation` = Storno.
            `training` = Trainingsbeleg (kein Umsatz). `zero` = Nullbeleg.
        paymentMethod:
          type: string
          enum: [cash, creditCard, online, uberApp, uberCard, uberCash, boltApp, boltCash, boltCard]
          description: Zahlungsart. Pflicht bei `standard`, `cancellation`, `training`.
        items:
          type: array
          description: Belegpositionen (Pflicht bei `standard`/`cancellation`/`training`).
          items:
            $ref: '#/components/schemas/ReceiptItem'
        vouchers:
          type: array
          description: Optionale Gutschein-Vorgänge (Verkauf/Einlösung).
          items:
            $ref: '#/components/schemas/Voucher'
        customerDetails:
          type: string
          description: Optionale Kundenangabe auf dem Beleg.
        legalMessage:
          type: string
          description: Optionaler rechtlicher Hinweistext.
        customProjectId:
          type: string
          description: Optionale eigene Projekt-/Referenz-ID.
    ReceiptItem:
      type: object
      description: >
        Empfohlene v2-Form. Die v1-Felder (amount, priceOne, vat) werden aus
        Kompatibilität weiterhin akzeptiert, sind aber deprecated.
      required: [name, quantity, unitPriceCents, vatRate]
      properties:
        name: { type: string, description: Bezeichnung der Position. }
        quantity: { type: number, description: Menge. }
        unitPriceCents:
          type: integer
          description: Einzelpreis (brutto) in ganzen Cent — keine Fließkommazahlen (vermeidet Rundungsfehler).
        vatRate:
          type: number
          enum: [20, 10, 13, 0, 19, 4.9]
          description: USt-Satz in Prozent (österreichische Sätze inkl. Sonder-/Grundnahrungssätze).
        amount:
          type: number
          deprecated: true
          description: "v1 (deprecated): Menge — nutze stattdessen quantity."
        priceOne:
          type: number
          deprecated: true
          description: "v1 (deprecated): Einzelpreis in Euro (Fließkomma) — nutze stattdessen unitPriceCents."
        vat:
          type: number
          deprecated: true
          description: "v1 (deprecated): USt-Satz — nutze stattdessen vatRate."
    Voucher:
      type: object
      required: [action, type]
      properties:
        action: { type: string, enum: [sell, redeem] }
        type: { type: string, enum: [value, promo] }
        code: { type: string, description: Gutscheincode (Default "no-code"). }
        value: { type: number, description: Wert (>0). Pflicht bei type=value. }
        name: { type: string }
        valueCents: { type: integer, description: Wert in Cent (Vorrang). }
    ReceiptEnvelope:
      type: object
      properties:
        status: { type: string, enum: [success, error] }
        message: { type: string }
        data:
          type: object
          properties:
            receipt:
              $ref: '#/components/schemas/Receipt'
            company: { type: string, description: Firmenname des Unternehmers. }
            uid: { type: [string, "null"], description: USt-IdNr des Unternehmers. }
            taxnr: { type: [string, "null"] }
            is_small_business: { type: boolean }
    Receipt:
      type: object
      description: Der gespeicherte, signierte Beleg.
      properties:
        counter: { type: integer, description: Fortlaufender Zähler der Kasse. }
        receiptType: { type: string }
        receiptId: { type: string }
        cashregisterId: { type: string }
        timeStamp: { type: string, description: Beleg-Zeitstempel (Europe/Vienna). }
        amountRateStandard: { type: number }
        amountRateReduced1: { type: number }
        amountRateReduced2: { type: number }
        amountRateZero: { type: number }
        amountRateSpecial: { type: number }
        certificateSerialNumber: { type: string }
        signaturePreviousReceipt: { type: string, description: Verkettung zum Vorbeleg (RKSV). }
        fullReceiptId: { type: string, description: Verschlüsselter Token für den PDF-Download. }
        sig: { type: string, description: "JWS ES256: header.payload.signature." }
        signatureSuccess: { type: boolean }
        qr: { type: string, description: Maschinenlesbarer QR-Text des Belegs. }
