openapi: 3.0.3
info:
  title: MyRepair Private API
  version: 1.0.0
  description: |
    Moderní OpenAPI reference pro privátní API servisní aplikace MyRepair.app.

    ## Autorizace

    Každý chráněný požadavek musí obsahovat jednu z autorizačních hlaviček.

    Doporučený režim pro MCP a uživatelské integrace je Bearer token:

    ```http
    Authorization: Bearer VAS_UZIVATELSKY_TOKEN
    X-MyRepair-Company-ID: ID_WORKSPACE
    ```

    `X-MyRepair-Company-ID` je potřeba, pokud má uživatel přístup do více workspace.

    Legacy režim se statickým API klíčem je:

    ```http
    MyRepair-Key: VAS_API_KLIC
    ```

    PHP příklad:

    ```php
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        "Content-Type: application/json",
        "MyRepair-Key: VAS_API_KLIC"
    ));
    ```

    API klíč získáte v administraci na adrese
    [workspace.myrepair.app/settings/api/](https://workspace.myrepair.app/settings/api/).

    ## Webhooky

    V administraci lze pro jednotlivé eventy nastavit jeden cílový webhook endpoint.
    MyRepair odesílá webhooky asynchronně a každý request podepisuje HMAC SHA-256 podpisem:

    ```text
    sha256 = HMAC_SHA256(secret, "{timestamp}.{raw_body}")
    ```

    Přijatý request obsahuje hlavičky:
    - `X-MyRepair-Webhook-Event`
    - `X-MyRepair-Webhook-Delivery`
    - `X-MyRepair-Webhook-Timestamp`
    - `X-MyRepair-Webhook-Signature`
    - `X-MyRepair-Webhook-Debug`

    Podporované eventy:
    - `order:create`
    - `order:update`
    - `order:item.create`
    - `order:item.update`
    - `invoice:create`
    - `invoice:update`
    - `proforma:create`
    - `proforma:update`
    - `customer:create`
    - `customer:update`
    - `stock:update`

    Pokud narazíte na problém, napište na [support@myrepair.app](mailto:support@myrepair.app)
    nebo přes [Whatsapp](https://api.whatsapp.com/message/RX3CQGSWPH57L1).
  contact:
    name: MyRepair Support
    email: support@myrepair.app
    url: https://workspace.myrepair.app/settings/api/
servers:
  - url: https://private-api.myrepair.app
    description: Produkční Private API
security:
  - MyRepairKey: []
  - MyRepairBearer: []
tags:
  - name: Locations
    description: Práce s pobočkami
  - name: Products
    description: Katalog produktů a služeb
  - name: Orders
    description: Zakládání servisních zakázek
  - name: Tracking
    description: Vyhledání zakázky přes tracking, ID nebo UUID
  - name: Reservations
    description: Rezervace a servisní termíny
  - name: Customers
    description: Zákazníci a jejich poslední zakázky
  - name: Profit
    description: Ziskovost dokladů, rezervací a servisních zakázek
  - name: Stock
    description: Skladové zásoby a pohyby
  - name: Invoices
    description: Faktury a jejich položky
  - name: Payments
    description: Platby a platební metody
  - name: Webhooks
    description: Debug a ověřování webhook delivery
paths:
  /reservations:
    get:
      tags:
        - Reservations
      summary: Výpis rezervací
      description: Vrací rezervace a servisní termíny podle data. Bez parametrů vrací dnešní rezervace.
      parameters:
        - in: query
          name: date
          schema:
            type: string
            format: date
          description: Jedno datum ve formátu YYYY-MM-DD. Výchozí je dnešní datum.
          example: "2026-06-23"
        - in: query
          name: date_from
          schema:
            type: string
            format: date
          description: Začátek rozsahu. Má přednost před `date`.
          example: "2026-06-23"
        - in: query
          name: date_to
          schema:
            type: string
            format: date
          description: Konec rozsahu.
          example: "2026-06-23"
        - in: query
          name: warehouseId
          schema:
            type: integer
          description: Filtr na pobočku.
          example: 1
        - in: query
          name: status
          schema:
            type: integer
          description: Filtr podle interního status kódu.
          example: 2001
        - in: query
          name: include_closed
          schema:
            type: boolean
            default: false
          description: Pokud je true, vrací i zrušené/uzavřené rezervace.
        - in: query
          name: page
          schema:
            type: integer
            minimum: 1
            default: 1
        - in: query
          name: per_page
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 50
      responses:
        "200":
          description: Seznam rezervací
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ReservationsListResponse"
        "400":
          description: Chybný parametr
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "401":
          $ref: "#/components/responses/MissingApiKey"
        "403":
          $ref: "#/components/responses/InvalidApiKey"
        "405":
          $ref: "#/components/responses/MethodNotAllowedGet"
  /orders:
    get:
      tags:
        - Orders
      summary: Výpis servisních zakázek
      description: Vrací servisní zakázky s filtrováním podle data, stavu, pobočky, zákazníka a fulltextu.
      parameters:
        - in: query
          name: q
          schema:
            type: string
          description: Fulltext nad kódem, UUID, jménem, e-mailem, telefonem a firmou.
        - in: query
          name: date
          schema:
            type: string
            format: date
          description: Filtr podle plánovaného data zakázky.
        - in: query
          name: date_from
          schema:
            type: string
            format: date
        - in: query
          name: date_to
          schema:
            type: string
            format: date
        - in: query
          name: created_from
          schema:
            type: string
            format: date
        - in: query
          name: created_to
          schema:
            type: string
            format: date
        - in: query
          name: warehouseId
          schema:
            type: integer
        - in: query
          name: customerId
          schema:
            type: integer
        - in: query
          name: status
          schema:
            type: integer
        - in: query
          name: email
          schema:
            type: string
        - in: query
          name: phone
          schema:
            type: string
        - in: query
          name: include_closed
          schema:
            type: boolean
            default: false
        - in: query
          name: page
          schema:
            type: integer
            minimum: 1
            default: 1
        - in: query
          name: per_page
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 20
      responses:
        "200":
          description: Seznam zakázek
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        "401":
          $ref: "#/components/responses/MissingApiKey"
        "403":
          $ref: "#/components/responses/InvalidApiKey"
  /orders/{identifier}:
    get:
      tags:
        - Orders
      summary: Detail servisní zakázky
      parameters:
        - in: path
          name: identifier
          required: true
          schema:
            type: string
          description: Interní ID, idCode, UUID nebo shortID zakázky.
      responses:
        "200":
          description: Detail zakázky včetně položek, komentářů a historie stavů
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        "404":
          description: Zakázka nebyla nalezena
  /orders/{identifier}/status:
    patch:
      tags:
        - Orders
      summary: Změna stavu servisní zakázky
      parameters:
        - in: path
          name: identifier
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - status
              properties:
                status:
                  type: integer
                  example: 2002
                comment:
                  type: string
      responses:
        "200":
          description: Aktualizovaná zakázka
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
  /orders/{identifier}/comments:
    get:
      tags:
        - Orders
      summary: Komentáře servisní zakázky
      parameters:
        - in: path
          name: identifier
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Seznam komentářů
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
    post:
      tags:
        - Orders
      summary: Přidání komentáře k zakázce
      parameters:
        - in: path
          name: identifier
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - comment
              properties:
                comment:
                  type: string
      responses:
        "201":
          description: Komentář byl vytvořen
  /customers:
    get:
      tags:
        - Customers
      summary: Výpis zákazníků
      parameters:
        - in: query
          name: q
          schema:
            type: string
        - in: query
          name: email
          schema:
            type: string
        - in: query
          name: phone
          schema:
            type: string
        - in: query
          name: companyId
          schema:
            type: string
        - in: query
          name: groupId
          schema:
            type: integer
      responses:
        "200":
          description: Seznam zákazníků
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
    post:
      tags:
        - Customers
      summary: Vytvoření zákazníka
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
      responses:
        "201":
          description: Zákazník byl vytvořen
  /customers/{identifier}:
    get:
      tags:
        - Customers
      summary: Detail zákazníka
      parameters:
        - in: path
          name: identifier
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Detail zákazníka a poslední zakázky
    patch:
      tags:
        - Customers
      summary: Úprava zákazníka
      parameters:
        - in: path
          name: identifier
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
      responses:
        "200":
          description: Zákazník byl upraven
  /statuses:
    get:
      tags:
        - Orders
      summary: Výpis stavů servisních zakázek
      responses:
        "200":
          description: Seznam dostupných stavů
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
  /profit/reservations:
    get:
      tags:
        - Profit
      summary: Výpis zisku rezervací a zakázek
      description: Vrací zisk podle plánovaného data rezervace/zakázky. Výpočet používá čistý obrat bez DPH, nákupní cenu položek a navázané náhradní díly.
      parameters:
        - in: query
          name: date
          schema:
            type: string
            format: date
        - in: query
          name: from
          schema:
            type: string
            format: date
        - in: query
          name: to
          schema:
            type: string
            format: date
        - in: query
          name: warehouseId
          schema:
            type: integer
        - in: query
          name: status
          schema:
            type: integer
        - in: query
          name: include_closed
          schema:
            type: boolean
        - in: query
          name: page
          schema:
            type: integer
            minimum: 1
        - in: query
          name: per_page
          schema:
            type: integer
            minimum: 1
            maximum: 100
      responses:
        "200":
          description: Přehled zisku rezervací
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
  /profit/reservations/{identifier}:
    get:
      tags:
        - Profit
      summary: Detail zisku rezervace nebo zakázky
      parameters:
        - in: path
          name: identifier
          required: true
          schema:
            type: string
          description: Interní ID, idCode, UUID nebo shortID zakázky.
      responses:
        "200":
          description: Detail zisku po položkách
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
  /profit/invoices:
    get:
      tags:
        - Profit
      summary: Výpis zisku dokladů
      description: Vrací zisk dokladů podle data vystavení. U dobropisu se výsledek počítá se záporným znaménkem.
      parameters:
        - in: query
          name: date
          schema:
            type: string
            format: date
        - in: query
          name: from
          schema:
            type: string
            format: date
        - in: query
          name: to
          schema:
            type: string
            format: date
        - in: query
          name: docType
          schema:
            type: integer
        - in: query
          name: serviceId
          schema:
            type: integer
        - in: query
          name: page
          schema:
            type: integer
            minimum: 1
        - in: query
          name: per_page
          schema:
            type: integer
            minimum: 1
            maximum: 100
      responses:
        "200":
          description: Přehled zisku dokladů
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
  /profit/invoices/{identifier}:
    get:
      tags:
        - Profit
      summary: Detail zisku dokladu
      parameters:
        - in: path
          name: identifier
          required: true
          schema:
            type: string
          description: Interní ID, UUID nebo kód dokladu.
      responses:
        "200":
          description: Detail zisku dokladu po položkách
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
  /locations:
    get:
      tags:
        - Locations
      summary: Výpis poboček
      description: Vyhledává a stránkuje seznam poboček.
      parameters:
        - in: query
          name: q
          schema:
            type: string
          description: Fulltext dotaz nad názvem, adresou a městem.
          example: ostrava
        - in: query
          name: city
          schema:
            type: string
          description: Filtr dle města.
          example: Ostrava
        - in: query
          name: postcode
          schema:
            type: string
          description: Filtr dle PSČ.
          example: "70030"
        - in: query
          name: page
          schema:
            type: integer
            minimum: 1
            default: 1
          example: 1
        - in: query
          name: per_page
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 20
          example: 20
        - in: query
          name: limit
          schema:
            type: integer
            minimum: 1
            maximum: 100
          description: Alias pro `per_page`.
          example: 20
      responses:
        "200":
          description: Seznam poboček
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/LocationsListResponse"
        "400":
          description: Chybný parametr
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: bad_request
                  message: Parametr per_page musí být v rozsahu 1–100.
        "401":
          $ref: "#/components/responses/MissingApiKey"
        "403":
          $ref: "#/components/responses/InvalidApiKey"
        "405":
          $ref: "#/components/responses/MethodNotAllowedGet"
  /products:
    get:
      tags:
        - Products
      summary: Výpis produktů
      description: Vrací seznam produktů a služeb s podporou fulltext vyhledávání.
      parameters:
        - in: query
          name: q
          schema:
            type: string
          description: Fulltext dotaz nad názvem produktu.
          example: Výměna baterie iPhone 15 Pro Max
        - in: query
          name: page
          schema:
            type: integer
            minimum: 1
            default: 1
      responses:
        "200":
          description: Seznam produktů
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProductsListResponse"
        "400":
          description: Chybný parametr
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: bad_request
                  message: Parametr page musí být celé číslo >= 1.
        "401":
          $ref: "#/components/responses/MissingApiKey"
        "403":
          $ref: "#/components/responses/InvalidApiKey"
        "405":
          $ref: "#/components/responses/MethodNotAllowedGet"
  /order:
    post:
      tags:
        - Orders
      summary: Vytvoření objednávky
      description: Vytvoří novou servisní zakázku s vybranými produkty a tracking odkazem.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/OrderCreateRequest"
      responses:
        "201":
          description: Zakázka vytvořena
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OrderCreateResponse"
        "400":
          description: Chybný payload
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: bad_request
                  message: Chybí povinný parametr warehouseId nebo products.
        "401":
          $ref: "#/components/responses/MissingApiKey"
        "403":
          $ref: "#/components/responses/InvalidApiKey"
        "405":
          $ref: "#/components/responses/MethodNotAllowedPost"
        "422":
          description: Validační chyba
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: validation_error
                  message: Datum inDate musí být ve formátu YYYY-MM-DD a v budoucnosti.
  /tracking:
    get:
      tags:
        - Tracking
      summary: Vyhledání trackingu zakázky
      description: |
        Vyhledá zakázku přes tracking kód, interní ID, UUID, číslo zakázky, e-mail nebo telefon.

        Použijte vždy právě jeden identifikátor.

        Doporučené varianty:
        - `trackingId`: veřejný tracking kód z odkazu zákazníka, například `28A99Z` nebo `MY-28A99Z`
        - `orderId`: interní databázové ID zakázky, například `123`
        - `uuid`: technický UUID identifikátor zakázky
        - `idCode`: číslo zakázky, které typicky vidí zákazník nebo obsluha, například `2500001`
        - `email`: e-mail zákazníka; pokud má více zakázek, vrátí se poslední vytvořená
        - `phone`: telefon zákazníka; funguje s předvolbou i bez ní a při více shodách vrátí poslední vytvořenou zakázku

        Praktické příklady:
        - `GET /tracking?trackingId=MY-28A99Z`
        - `GET /tracking?idCode=2500001`
        - `GET /tracking?orderId=123`
        - `GET /tracking?uuid=550e8400-e29b-41d4-a716-446655440000`
        - `GET /tracking?email=jakubnovak@myrepair.app`
        - `GET /tracking?phone=734468653`
        - `GET /tracking?phone=%2B420734468653`
      parameters:
        - in: query
          name: trackingId
          schema:
            type: string
          description: |
            Veřejný tracking kód zakázky.

            Je to hodnota z tracking odkazu zákazníka, například z URL
            `https://tracking.myrepair.app/cs/28A99Z`.

            Podporovaný je i vstup s prefixem `MY-`, například `MY-28A99Z`.
          example: MY-28A99Z
        - in: query
          name: orderId
          schema:
            type: integer
          description: |
            Interní ID zakázky v databázi MyRepair.

            Používejte hlavně při serverové integraci, pokud už si u sebe ukládáte primární ID zakázky.
          example: 123
        - in: query
          name: uuid
          schema:
            type: string
            format: uuid
          description: |
            Technický UUID identifikátor zakázky.

            Hodí se hlavně při integraci mezi systémy, kde potřebujete stabilní unikátní identifikátor.
          example: 550e8400-e29b-41d4-a716-446655440000
        - in: query
          name: idCode
          schema:
            type: string
          description: |
            Číslo zakázky, které vidí zákazník nebo obsluha.

            Typicky jde o evidenční číslo zakázky, například `2500001`.
          example: "2500001"
        - in: query
          name: email
          schema:
            type: string
            format: email
          description: |
            E-mail zákazníka.

            Pokud pod jedním e-mailem existuje více zakázek, endpoint vrátí poslední vytvořenou zakázku.
          example: jakubnovak@myrepair.app
        - in: query
          name: phone
          schema:
            type: string
          description: |
            Telefon zákazníka.

            Lze poslat číslo bez předvolby, například `734468653`, i s předvolbou, například `+420734468653`.
            Pokud pod telefonem existuje více zakázek, endpoint vrátí poslední vytvořenou zakázku.
          examples:
            withoutPrefix:
              value: "734468653"
            withPrefix:
              value: "+420734468653"
      responses:
        "200":
          description: Detail trackingu a zakázky
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TrackingResponse"
        "401":
          $ref: "#/components/responses/MissingApiKey"
        "403":
          $ref: "#/components/responses/InvalidApiKey"
        "404":
          description: Tracking nebo zakázka nebyla nalezena
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              examples:
                tracking:
                  value:
                    error:
                      code: not_found
                      message: Tracking nebyl nalezen.
                order:
                  value:
                    error:
                      code: not_found
                      message: Zakázka nebyla nalezena.
        "405":
          $ref: "#/components/responses/MethodNotAllowedGet"
        "422":
          description: Neplatná kombinace parametrů
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              examples:
                missing:
                  value:
                    error:
                      code: validation_error
                      message: Je nutné zadat jeden z parametrů trackingId, orderId, uuid, idCode, email nebo phone.
                tooMany:
                  value:
                    error:
                      code: validation_error
                      message: Použijte pouze jeden z parametrů trackingId, orderId, uuid, idCode, email nebo phone.
  /stock:
    get:
      tags:
        - Stock
      summary: Výpis skladových zásob
      parameters:
        - in: query
          name: page
          schema:
            type: integer
            minimum: 1
            default: 1
        - in: query
          name: per_page
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 20
        - in: query
          name: productId
          schema:
            type: integer
          description: Filtr dle produktu.
        - in: query
          name: ean
          schema:
            type: string
          description: Filtr dle EAN nebo SKU.
      responses:
        "200":
          description: Skladové zásoby
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/StockListResponse"
        "400":
          description: Chybný parametr
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              examples:
                page:
                  value:
                    error:
                      code: bad_request
                      message: Parametr page musí být celé číslo >= 1.
                productId:
                  value:
                    error:
                      code: bad_request
                      message: Parametr productId musí být číslo.
        "401":
          $ref: "#/components/responses/MissingApiKey"
        "403":
          $ref: "#/components/responses/InvalidApiKey"
        "405":
          $ref: "#/components/responses/MethodNotAllowedGet"
        "500":
          $ref: "#/components/responses/InternalError"
  /stock/movements:
    get:
      tags:
        - Stock
      summary: Výpis pohybů skladu
      description: Vrací skladové pohyby. `productId` nebo `ean` jsou volitelné filtry, bez nich endpoint vrací globální výpis všech pohybů podle data a stránkování.
      parameters:
        - in: query
          name: productId
          schema:
            type: integer
          description: Volitelný filtr na ID produktu.
        - in: query
          name: ean
          schema:
            type: string
          description: Volitelný filtr na EAN nebo SKU produktu.
        - in: query
          name: date
          schema:
            type: string
            format: date
          description: Konkrétní datum pohybu ve formátu `YYYY-MM-DD`.
        - in: query
          name: from
          schema:
            type: string
            format: date
          description: Datum od ve formátu `YYYY-MM-DD`.
        - in: query
          name: to
          schema:
            type: string
            format: date
          description: Datum do ve formátu `YYYY-MM-DD`.
        - in: query
          name: warehouseId
          schema:
            type: integer
          description: Volitelný filtr na sklad/pobočku.
        - in: query
          name: page
          schema:
            type: integer
            minimum: 1
            default: 1
        - in: query
          name: per_page
          schema:
            type: integer
            minimum: 1
            maximum: 200
            default: 50
      responses:
        "200":
          description: Přehled pohybů
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/StockMovementListResponse"
        "400":
          description: Chybný parametr
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: bad_request
                  message: Parametr from musí být ve formátu YYYY-MM-DD.
        "401":
          $ref: "#/components/responses/MissingApiKey"
        "403":
          $ref: "#/components/responses/InvalidApiKey"
        "405":
          $ref: "#/components/responses/MethodNotAllowedGetPost"
        "500":
          $ref: "#/components/responses/InternalError"
    post:
      tags:
        - Stock
      summary: Zápis skladového pohybu
      description: |
        Umožňuje zapsat příjem, výdej nebo transfer mezi sklady.

        Pro `type = in` nebo `out` pošlete `warehouseId`.
        Pro `type = transfer` pošlete `sourceWarehouseId` a `targetWarehouseId`.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/StockMovementWriteRequest"
      responses:
        "201":
          description: Pohyb uložen
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/StockMovementListResponse"
        "400":
          description: Neplatný JSON payload
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: bad_request
                  message: Invalid JSON payload.
        "401":
          $ref: "#/components/responses/MissingApiKey"
        "403":
          $ref: "#/components/responses/InvalidApiKey"
        "404":
          description: Produkt nebo sklad nebyl nalezen
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              examples:
                product:
                  value:
                    error:
                      code: not_found
                      message: Produkt nebyl nalezen.
                warehouse:
                  value:
                    error:
                      code: not_found
                      message: Sklad nebyl nalezen.
        "405":
          $ref: "#/components/responses/MethodNotAllowedGetPost"
        "422":
          description: Validační chyba
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: validation_error
                  message: Parametr type musí být in, out nebo transfer.
        "500":
          $ref: "#/components/responses/InternalError"
  /payments/methods:
    get:
      tags:
        - Payments
      summary: Výpis platebních metod
      responses:
        "200":
          description: Dostupné platební metody
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaymentMethodsResponse"
        "401":
          $ref: "#/components/responses/MissingApiKey"
        "403":
          $ref: "#/components/responses/InvalidApiKey"
        "405":
          $ref: "#/components/responses/MethodNotAllowedGet"
        "500":
          $ref: "#/components/responses/InternalError"
  /payments:
    get:
      tags:
        - Payments
      summary: Výpis plateb
      parameters:
        - in: query
          name: page
          schema:
            type: integer
            minimum: 1
            default: 1
        - in: query
          name: per_page
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 20
        - in: query
          name: from
          schema:
            type: string
            format: date
        - in: query
          name: to
          schema:
            type: string
            format: date
        - in: query
          name: invoiceCode
          schema:
            type: string
        - in: query
          name: vs
          schema:
            type: string
          description: Variabilní symbol, pokud je v databázi dostupný příslušný sloupec.
      responses:
        "200":
          description: Seznam plateb
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaymentsListResponse"
        "400":
          description: Chybný parametr
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: bad_request
                  message: Parametr per_page musí být v rozsahu 1–100.
        "401":
          $ref: "#/components/responses/MissingApiKey"
        "403":
          $ref: "#/components/responses/InvalidApiKey"
        "405":
          $ref: "#/components/responses/MethodNotAllowedGetPost"
        "422":
          description: Chybný formát data
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: validation_error
                  message: Parametr from musí být ve formátu YYYY-MM-DD.
        "500":
          $ref: "#/components/responses/InternalError"
    post:
      tags:
        - Payments
      summary: Vytvoření platby
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PaymentWriteRequest"
      responses:
        "201":
          description: Platba vytvořena
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaymentSummaryResponse"
        "400":
          description: Neplatný JSON payload
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: bad_request
                  message: Invalid JSON payload.
        "401":
          $ref: "#/components/responses/MissingApiKey"
        "403":
          $ref: "#/components/responses/InvalidApiKey"
        "404":
          description: Faktura nebyla nalezena
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: not_found
                  message: Faktura nebyla nalezena.
        "405":
          $ref: "#/components/responses/MethodNotAllowedGetPost"
        "422":
          description: Validační chyba
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              examples:
                identifier:
                  value:
                    error:
                      code: validation_error
                      message: Je nutné zadat invoiceId, invoiceCode nebo invoiceUuid.
                amount:
                  value:
                    error:
                      code: validation_error
                      message: Částka musí být nenulová.
        "500":
          $ref: "#/components/responses/InternalError"
  /payments/{identifier}:
    parameters:
      - in: path
        name: identifier
        required: true
        schema:
          type: string
        description: ID platby.
        example: "128"
    get:
      tags:
        - Payments
      summary: Detail platby
      responses:
        "200":
          description: Detail platby
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaymentResponse"
        "401":
          $ref: "#/components/responses/MissingApiKey"
        "403":
          $ref: "#/components/responses/InvalidApiKey"
        "404":
          description: Platba nebyla nalezena
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: not_found
                  message: Platba nebyla nalezena.
        "405":
          $ref: "#/components/responses/MethodNotAllowedGetPut"
    put:
      tags:
        - Payments
      summary: Úprava platby
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PaymentUpdateRequest"
      responses:
        "200":
          description: Platba aktualizována
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaymentSummaryResponse"
        "400":
          description: Neplatný JSON payload
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: bad_request
                  message: Invalid JSON payload.
        "401":
          $ref: "#/components/responses/MissingApiKey"
        "403":
          $ref: "#/components/responses/InvalidApiKey"
        "404":
          description: Platba nebyla nalezena
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: not_found
                  message: Platba nebyla nalezena.
        "405":
          $ref: "#/components/responses/MethodNotAllowedGetPut"
        "422":
          description: Validační chyba
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: validation_error
                  message: Částka musí být nenulová.
        "500":
          $ref: "#/components/responses/InternalError"
  /invoices:
    get:
      tags:
        - Invoices
      summary: Výpis faktur
      parameters:
        - in: query
          name: page
          schema:
            type: integer
            minimum: 1
            default: 1
        - in: query
          name: per_page
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 20
        - in: query
          name: dateCreate
          schema:
            type: string
            format: date
        - in: query
          name: from
          schema:
            type: string
            format: date
        - in: query
          name: to
          schema:
            type: string
            format: date
      responses:
        "200":
          description: Seznam faktur
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InvoicesListResponse"
        "400":
          description: Chybný parametr
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: bad_request
                  message: Parametr per_page musí být v rozsahu 1–100.
        "401":
          $ref: "#/components/responses/MissingApiKey"
        "403":
          $ref: "#/components/responses/InvalidApiKey"
        "405":
          $ref: "#/components/responses/MethodNotAllowedGetPost"
        "422":
          description: Chybný formát data
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: validation_error
                  message: Parametr dateCreate musí být ve formátu YYYY-MM-DD.
        "500":
          $ref: "#/components/responses/InternalError"
    post:
      tags:
        - Invoices
      summary: Vytvoření faktury
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/InvoiceCreateRequest"
      responses:
        "201":
          description: Faktura vytvořena
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InvoiceSummaryResponse"
        "400":
          description: Neplatný JSON payload
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: bad_request
                  message: Invalid JSON payload.
        "401":
          $ref: "#/components/responses/MissingApiKey"
        "403":
          $ref: "#/components/responses/InvalidApiKey"
        "404":
          description: Fakturační údaje nebyly nalezeny
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: not_found
                  message: Fakturační údaje nebyly nalezeny.
        "405":
          $ref: "#/components/responses/MethodNotAllowedGetPost"
        "422":
          description: Validační chyba
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: validation_error
                  message: Faktura musí obsahovat alespoň jednu položku.
        "500":
          $ref: "#/components/responses/InternalError"
  /invoices/{identifier}:
    parameters:
      - in: path
        name: identifier
        required: true
        schema:
          type: string
        description: ID faktury, UUID nebo `invoiceCode`.
        example: INV-2026-0001
    get:
      tags:
        - Invoices
      summary: Detail faktury
      responses:
        "200":
          description: Detail faktury
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InvoiceDetailResponse"
        "401":
          $ref: "#/components/responses/MissingApiKey"
        "403":
          $ref: "#/components/responses/InvalidApiKey"
        "404":
          description: Faktura nebyla nalezena
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: not_found
                  message: Faktura nebyla nalezena.
        "405":
          $ref: "#/components/responses/MethodNotAllowedGetPut"
    put:
      tags:
        - Invoices
      summary: Úprava faktury
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/InvoiceUpdateRequest"
      responses:
        "200":
          description: Faktura aktualizována
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InvoiceSummaryResponse"
        "400":
          description: Neplatný JSON payload
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: bad_request
                  message: Invalid JSON payload.
        "401":
          $ref: "#/components/responses/MissingApiKey"
        "403":
          $ref: "#/components/responses/InvalidApiKey"
        "404":
          description: Faktura nebyla nalezena
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: not_found
                  message: Faktura nebyla nalezena.
        "405":
          $ref: "#/components/responses/MethodNotAllowedGetPut"
        "422":
          description: Validační chyba
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: validation_error
                  message: Faktura musí obsahovat alespoň jednu položku.
        "500":
          $ref: "#/components/responses/InternalError"
  /webhooks/debug:
    get:
      tags:
        - Webhooks
      security: []
      summary: Debug detail webhook delivery
      description: |
        Vrací detail jedné webhook delivery včetně requestu, response a chyb.

        Endpoint je určený hlavně pro debugging klienta a používá náhodný `debug` token,
        který MyRepair přikládá do každého webhooku v hlavičce `X-MyRepair-Webhook-Debug`.
      parameters:
        - in: query
          name: delivery
          required: true
          schema:
            type: string
          description: Delivery ID webhooku.
          example: 9ad3ffc9-5872-44c6-8bfb-4e883ad02bfe
        - in: query
          name: token
          required: true
          schema:
            type: string
          description: Debug token z hlavičky `X-MyRepair-Webhook-Debug`.
          example: 2e17f16a0c1df7a83e7b1f9610f8cdd1cf86b87b
      responses:
        "200":
          description: Detail webhook delivery
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WebhookDebugResponse"
        "400":
          description: Chybějící parametr
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: bad_request
                  message: Missing delivery or token.
        "404":
          description: Delivery nebyla nalezena
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: not_found
                  message: Webhook delivery not found.
        "405":
          description: Nepovolená metoda
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
              example:
                error:
                  code: method_not_allowed
                  message: Only GET is allowed.
components:
  securitySchemes:
    MyRepairKey:
      type: apiKey
      in: header
      name: MyRepair-Key
    MyRepairBearer:
      type: http
      scheme: bearer
  responses:
    MissingApiKey:
      description: Chybějící API klíč
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
          example:
            error:
              code: missing_api_key
              message: Chybí hlavička MyRepair-Key.
    InvalidApiKey:
      description: Neplatný API klíč
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
          example:
            error:
              code: invalid_api_key
              message: Neplatný MyRepair-Key.
    MethodNotAllowedGet:
      description: Endpoint podporuje pouze GET
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
          example:
            error:
              code: method_not_allowed
              message: Only GET is allowed.
    MethodNotAllowedPost:
      description: Endpoint podporuje pouze POST
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
          example:
            error:
              code: method_not_allowed
              message: Only POST is allowed.
    MethodNotAllowedGetPost:
      description: Endpoint podporuje pouze GET a POST
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
          example:
            error:
              code: method_not_allowed
              message: Only GET and POST are allowed.
    MethodNotAllowedGetPut:
      description: Endpoint podporuje pouze GET a PUT
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
          example:
            error:
              code: method_not_allowed
              message: Only GET and PUT are allowed.
    InternalError:
      description: Interní chyba serveru
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
          example:
            error:
              code: internal_error
              message: Interní chyba serveru.
  schemas:
    Error:
      type: object
      required:
        - code
        - message
      properties:
        code:
          type: string
          example: validation_error
        message:
          type: string
          example: Parametr page musí být celé číslo >= 1.
    ErrorResponse:
      type: object
      required:
        - error
      properties:
        error:
          $ref: "#/components/schemas/Error"
    Paginator:
      type: object
      required:
        - totalCount
        - page
        - pageCount
        - itemsOnPage
        - itemsPerPage
      properties:
        totalCount:
          type: integer
          example: 55
        page:
          type: integer
          example: 1
        pageCount:
          type: integer
          example: 3
        itemsOnPage:
          type: integer
          example: 20
        itemsPerPage:
          type: integer
          example: 20
    Contact:
      type: object
      properties:
        email:
          type: string
          nullable: true
          example: test@myrepair.app
        phone:
          type: string
          nullable: true
          example: "+420111222333"
    Gps:
      type: object
      properties:
        lat:
          type: number
          format: double
          nullable: true
          example: 49.8347
        lng:
          type: number
          format: double
          nullable: true
          example: 18.282
    Location:
      type: object
      properties:
        id:
          type: integer
          example: 1
        name:
          type: string
          nullable: true
          example: MyRepair Ostrava
        address:
          type: string
          nullable: true
          example: Lidická 881
        city:
          type: string
          nullable: true
          example: Ostrava
        postCode:
          type: string
          nullable: true
          example: "70030"
        contact:
          $ref: "#/components/schemas/Contact"
        gps:
          $ref: "#/components/schemas/Gps"
    LocationsListResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            locations:
              type: array
              items:
                $ref: "#/components/schemas/Location"
            paginator:
              $ref: "#/components/schemas/Paginator"
    Product:
      type: object
      properties:
        id:
          type: integer
          example: 1001
        name:
          type: string
          nullable: true
          example: Výměna baterie na iPhone 15 Pro Max
        price:
          type: integer
          nullable: true
          example: 35990
        currency:
          type: string
          nullable: true
          example: CZK
        url:
          type: string
          nullable: true
          example: https://eshop.myrepair.app/products/1001
        duration_minutes:
          type: integer
          nullable: true
          example: 60
        category:
          type: string
          nullable: true
          example: iPhone | iPhone 15 | iPhone Pro Max
    ProductsListResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            products:
              type: array
              items:
                $ref: "#/components/schemas/Product"
            paginator:
              $ref: "#/components/schemas/Paginator"
    NotificationsSettings:
      type: object
      properties:
        email:
          type: boolean
          example: true
        sms:
          type: boolean
          example: true
    OrderProductInput:
      type: object
      required:
        - productId
      properties:
        productId:
          type: integer
          example: 1
        price:
          type: number
          format: float
          example: 100
        q:
          type: integer
          example: 1
    OrderCreateRequest:
      type: object
      required:
        - warehouseId
        - products
        - inDate
      properties:
        name:
          type: string
          example: Jakub
        surname:
          type: string
          example: Novák
        email:
          type: string
          example: jakubnovak@myrepair.app
        phoneCode:
          oneOf:
            - type: integer
            - type: string
          example: 420
        phone:
          oneOf:
            - type: integer
            - type: string
          example: 734468653
        companyName:
          type: string
          example: myrepair s.r.o.
        companyId:
          oneOf:
            - type: integer
            - type: string
          example: 23521414
        companyVat:
          type: string
          example: CZ23521414
        warehouseId:
          type: integer
          example: 1
        inDate:
          type: string
          format: date
          example: "2026-04-20"
        inTime:
          type: string
          example: "11:00:00"
        notifications:
          $ref: "#/components/schemas/NotificationsSettings"
        products:
          type: array
          items:
            $ref: "#/components/schemas/OrderProductInput"
    OrderCreateResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            orderCode:
              oneOf:
                - type: integer
                - type: string
              example: 2500001
            trackingLink:
              type: string
              example: https://tracking.myrepair.app/cs/28A99Z
    TrackingLookup:
      type: object
      properties:
        type:
          type: string
          description: Název parametru, přes který bylo hledání provedeno.
          example: trackingId
        value:
          type: string
          example: MY-28A99Z
    TrackingStatus:
      type: object
      properties:
        code:
          type: integer
          example: 2001
        label:
          type: string
          nullable: true
          example: Vytvořeno
        message:
          type: string
          nullable: true
          example: Zákazka - Vytvořena
        progress:
          type: integer
          nullable: true
          example: 10
        state:
          type: integer
          nullable: true
          example: 1
        badgeClass:
          type: string
          nullable: true
          example: bg-soft-primary text-primary
    TrackingResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            lookup:
              $ref: "#/components/schemas/TrackingLookup"
            order:
              type: object
              properties:
                id:
                  type: integer
                  description: Interní ID zakázky v databázi MyRepair.
                  example: 123
                orderCode:
                  type: string
                  nullable: true
                  description: Číslo zakázky, které vidí zákazník nebo obsluha.
                  example: "2500001"
                uuid:
                  type: string
                  nullable: true
                  format: uuid
                  description: Technický UUID identifikátor zakázky.
                  example: 550e8400-e29b-41d4-a716-446655440000
                shortId:
                  type: string
                  nullable: true
                  example: ABC1234
                source:
                  type: integer
                  nullable: true
                  example: 1
                orderType:
                  type: integer
                  nullable: true
                  example: 1
                createdAt:
                  type: string
                  nullable: true
                  example: "2026-03-29 15:35:21"
                inDate:
                  type: string
                  nullable: true
                  example: "2026-04-20 11:00:00"
                outDate:
                  type: string
                  nullable: true
                  example: null
            tracking:
              type: object
              properties:
                idTracking:
                  type: string
                  nullable: true
                  description: Veřejný tracking kód zakázky.
                  example: 28A99Z
                label:
                  type: string
                  nullable: true
                  description: Tracking kód ve formátu pro zobrazení zákazníkovi.
                  example: MY-28A99Z
                url:
                  type: string
                  nullable: true
                  description: Přímý odkaz do zákaznického tracking portálu.
                  example: https://tracking.myrepair.app/cs/28A99Z
                createdAt:
                  type: string
                  nullable: true
                  example: "2026-03-29 15:35:21"
            status:
              $ref: "#/components/schemas/TrackingStatus"
            customer:
              type: object
              properties:
                name:
                  type: string
                  nullable: true
                  example: Jakub
                surname:
                  type: string
                  nullable: true
                  example: Novák
                email:
                  type: string
                  nullable: true
                  example: jakubnovak@myrepair.app
                phoneCode:
                  type: string
                  nullable: true
                  example: "420"
                phone:
                  type: string
                  nullable: true
                  example: "734468653"
                company:
                  type: object
                  properties:
                    name:
                      type: string
                      nullable: true
                      example: myrepair s.r.o.
                    id:
                      type: string
                      nullable: true
                      example: "23521414"
                    vatId:
                      type: string
                      nullable: true
                      example: CZ23521414
            warehouse:
              type: object
              properties:
                id:
                  type: integer
                  nullable: true
                  example: 1
                name:
                  type: string
                  nullable: true
                  example: MyRepair Ostrava
                city:
                  type: string
                  nullable: true
                  example: Ostrava
                email:
                  type: string
                  nullable: true
                  example: ostrava@myrepair.app
                phoneCode:
                  type: string
                  nullable: true
                  example: "+420"
                phone:
                  type: string
                  nullable: true
                  example: "111222333"
    StockItem:
      type: object
      properties:
        productId:
          type: integer
          nullable: true
          example: 1001
        warehouseId:
          type: integer
          nullable: true
          example: 1
        warehouseName:
          type: string
          nullable: true
          example: MyRepair Ostrava
        productName:
          type: string
          nullable: true
          example: Výměna baterie na iPhone 15 Pro Max
        sku:
          type: string
          nullable: true
          example: IP15PM-BAT
        ean:
          type: string
          nullable: true
          example: "8591234567890"
        onHand:
          type: number
          format: float
          example: 12
        reserved:
          type: number
          format: float
          example: 2
        min:
          type: number
          format: float
          example: 1
        max:
          type: number
          format: float
          example: 20
    StockListResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            stocks:
              type: array
              items:
                $ref: "#/components/schemas/StockItem"
            paginator:
              $ref: "#/components/schemas/Paginator"
    StockMovement:
      type: object
      properties:
        id:
          type: integer
          example: 501
        productId:
          type: integer
          example: 1001
        productName:
          type: string
          example: iPhone 15 Pro displej
        sku:
          type: string
          nullable: true
          example: SKU-123
        ean:
          type: string
          nullable: true
          example: "8590000000001"
        warehouseId:
          type: integer
          example: 1
        warehouseName:
          type: string
          nullable: true
          example: MyRepair Ostrava
        change:
          type: number
          format: float
          example: -1
        before:
          type: number
          format: float
          example: 12
        after:
          type: number
          format: float
          example: 11
        method:
          type: integer
          nullable: true
          example: 4
        serviceId:
          type: integer
          nullable: true
          example: 10880
        userId:
          type: integer
          nullable: true
          example: 12
        createdAt:
          type: string
          nullable: true
          example: "2026-03-29 16:14:02"
    StockMovementListResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            productId:
              type: integer
              example: 1001
            type:
              type: string
              nullable: true
              example: transfer
            movements:
              type: array
              items:
                $ref: "#/components/schemas/StockMovement"
            paginator:
              $ref: "#/components/schemas/Paginator"
    StockMovementWriteRequest:
      type: object
      required:
        - type
        - productId
        - quantity
      properties:
        type:
          type: string
          enum:
            - in
            - out
            - transfer
          example: transfer
        productId:
          type: integer
          example: 1001
        quantity:
          type: number
          format: float
          minimum: 0.01
          example: 2
        warehouseId:
          type: integer
          description: Použijte pro `type = in` nebo `out`.
          example: 1
        sourceWarehouseId:
          type: integer
          description: Použijte pro `type = transfer`.
          example: 1
        targetWarehouseId:
          type: integer
          description: Použijte pro `type = transfer`.
          example: 2
    PaymentMethod:
      type: object
      properties:
        id:
          type: integer
          example: 1
        name:
          type: string
          nullable: true
          example: Hotově
        icon:
          type: string
          nullable: true
          example: fa-money-bill-wave
    PaymentMethodsResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            methods:
              type: array
              items:
                $ref: "#/components/schemas/PaymentMethod"
    PaymentListItem:
      type: object
      properties:
        id:
          type: integer
          example: 128
        invoiceId:
          type: integer
          nullable: true
          example: 450
        invoiceCode:
          type: string
          nullable: true
          example: INV-2026-0001
        invoiceUuid:
          type: string
          nullable: true
          format: uuid
          example: 8a6619f9-f857-4f4f-9dbf-9887ef3abdb3
        documentTypeId:
          type: integer
          nullable: true
          example: 1
        serviceId:
          type: integer
          nullable: true
          example: 123
        amount:
          type: number
          format: float
          nullable: true
          example: 1490
        paymentMethod:
          $ref: "#/components/schemas/PaymentMethod"
        type:
          type: integer
          nullable: true
          example: 1
        note:
          type: string
          nullable: true
          example: Záloha
        createdAt:
          type: string
          nullable: true
          example: "2026-03-29 14:05:00"
    PaymentsListResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            payments:
              type: array
              items:
                $ref: "#/components/schemas/PaymentListItem"
            paginator:
              $ref: "#/components/schemas/Paginator"
    PaymentWriteRequest:
      type: object
      required:
        - amount
        - paymentMethodId
      properties:
        invoiceId:
          oneOf:
            - type: integer
            - type: string
          description: Identifikace faktury přes ID.
          example: 450
        invoiceCode:
          type: string
          description: Identifikace faktury přes kód.
          example: INV-2026-0001
        invoiceUuid:
          type: string
          format: uuid
          description: Identifikace faktury přes UUID.
          example: 8a6619f9-f857-4f4f-9dbf-9887ef3abdb3
        amount:
          type: number
          format: float
          example: 1490
        paymentMethodId:
          type: integer
          example: 1
        type:
          type: integer
          example: 1
        note:
          type: string
          example: Záloha
    PaymentUpdateRequest:
      type: object
      properties:
        amount:
          type: number
          format: float
          example: 1490
        paymentMethodId:
          type: integer
          example: 2
        type:
          type: integer
          example: 1
        note:
          type: string
          example: Doplatek kartou
    PaymentResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            payment:
              $ref: "#/components/schemas/PaymentListItem"
    PaymentSummaryResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            paymentId:
              type: integer
              example: 128
            invoiceId:
              type: integer
              nullable: true
              example: 450
            amount:
              type: number
              format: float
              example: 1490
            paymentMethodId:
              type: integer
              example: 2
            type:
              type: integer
              example: 1
            note:
              type: string
              nullable: true
              example: Doplatek kartou
            createdAt:
              type: string
              nullable: true
              example: "2026-03-29 14:05:00"
    InvoiceParty:
      type: object
      properties:
        name:
          type: string
          nullable: true
          example: myrepair s.r.o.
        companyId:
          type: string
          nullable: true
          example: "23521414"
        vatId:
          type: string
          nullable: true
          example: CZ23521414
        address:
          type: string
          nullable: true
          example: Lidická 881
        city:
          type: string
          nullable: true
          example: Ostrava
        zip:
          type: string
          nullable: true
          example: "70030"
        country:
          type: string
          nullable: true
          example: CZ
    InvoiceItem:
      type: object
      properties:
        id:
          type: integer
          nullable: true
          example: 1
        productId:
          type: integer
          nullable: true
          example: 1001
        sku:
          type: string
          nullable: true
          example: IP15PM-BAT
        name:
          type: string
          nullable: true
          example: Výměna baterie na iPhone 15 Pro Max
        quantity:
          type: number
          format: float
          nullable: true
          example: 1
        priceGross:
          type: number
          format: float
          nullable: true
          example: 1490
        priceNet:
          type: number
          format: float
          nullable: true
          example: 1231.4
        vatRate:
          type: number
          format: float
          nullable: true
          example: 21
    InvoiceListItem:
      type: object
      properties:
        id:
          type: integer
          example: 450
        uuid:
          type: string
          nullable: true
          format: uuid
          example: 8a6619f9-f857-4f4f-9dbf-9887ef3abdb3
        invoiceCode:
          type: string
          nullable: true
          example: INV-2026-0001
        documentTypeId:
          type: integer
          nullable: true
          example: 1
        dateCreate:
          type: string
          nullable: true
          example: "2026-03-29"
        dateDueToPay:
          type: string
          nullable: true
          example: "2026-04-05"
        dateVat:
          type: string
          nullable: true
          example: "2026-03-29"
        customer:
          type: object
          properties:
            name:
              type: string
              nullable: true
              example: Jakub Novák
            companyId:
              type: string
              nullable: true
              example: "23521414"
            vatId:
              type: string
              nullable: true
              example: CZ23521414
        paymentMethod:
          $ref: "#/components/schemas/PaymentMethod"
        totalGross:
          type: number
          format: float
          nullable: true
          example: 1490
        itemsTotal:
          type: number
          format: float
          nullable: true
          example: 1490
        paymentsTotal:
          type: number
          format: float
          nullable: true
          example: 500
    InvoicesListResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            invoices:
              type: array
              items:
                $ref: "#/components/schemas/InvoiceListItem"
            paginator:
              $ref: "#/components/schemas/Paginator"
    InvoiceDetail:
      type: object
      properties:
        id:
          type: integer
          example: 450
        uuid:
          type: string
          nullable: true
          format: uuid
          example: 8a6619f9-f857-4f4f-9dbf-9887ef3abdb3
        invoiceCode:
          type: string
          nullable: true
          example: INV-2026-0001
        documentTypeId:
          type: integer
          nullable: true
          example: 1
        dateCreate:
          type: string
          nullable: true
          example: "2026-03-29"
        dateDueToPay:
          type: string
          nullable: true
          example: "2026-04-05"
        dateVat:
          type: string
          nullable: true
          example: "2026-03-29"
        currencyId:
          type: integer
          nullable: true
          example: 1
        paymentMethod:
          $ref: "#/components/schemas/PaymentMethod"
        customer:
          $ref: "#/components/schemas/InvoiceParty"
        supplier:
          $ref: "#/components/schemas/InvoiceParty"
        totals:
          type: object
          properties:
            totalGross:
              type: number
              format: float
              nullable: true
              example: 1490
            items:
              type: array
              items:
                $ref: "#/components/schemas/InvoiceItem"
            payments:
              type: array
              items:
                $ref: "#/components/schemas/PaymentListItem"
    InvoiceDetailResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            invoice:
              $ref: "#/components/schemas/InvoiceDetail"
    InvoiceItemInput:
      type: object
      required:
        - name
        - quantity
        - unitPrice
      properties:
        productId:
          type: integer
          example: 1001
        sku:
          type: string
          example: IP15PM-BAT
        name:
          type: string
          example: Výměna baterie na iPhone 15 Pro Max
        quantity:
          type: number
          format: float
          example: 1
        unitPrice:
          type: number
          format: float
          example: 1490
        unitPriceWithoutVat:
          type: number
          format: float
          example: 1231.4
        vatRate:
          type: number
          format: float
          example: 21
    InvoiceCreateRequest:
      type: object
      required:
        - billerId
        - invoiceCode
        - docType
        - dateCreate
        - dateDueToPay
        - dateVat
        - paymentMethodId
        - items
      properties:
        billerId:
          type: integer
          example: 1
        invoiceCode:
          type: string
          example: INV-2026-0001
        docType:
          type: integer
          example: 1
        dateCreate:
          type: string
          format: date
          example: "2026-03-29"
        dateDueToPay:
          type: string
          format: date
          example: "2026-04-05"
        dateVat:
          type: string
          format: date
          example: "2026-03-29"
        paymentMethodId:
          type: integer
          example: 1
        currencyId:
          type: integer
          example: 1
        warehouseId:
          type: integer
          example: 1
        serviceId:
          type: integer
          example: 123
        customer:
          $ref: "#/components/schemas/InvoiceParty"
        items:
          type: array
          items:
            $ref: "#/components/schemas/InvoiceItemInput"
    InvoiceUpdateRequest:
      type: object
      required:
        - invoiceCode
        - docType
        - dateCreate
        - dateDueToPay
        - dateVat
        - paymentMethodId
        - items
      properties:
        invoiceCode:
          type: string
          example: INV-2026-0001
        docType:
          type: integer
          example: 1
        dateCreate:
          type: string
          format: date
          example: "2026-03-29"
        dateDueToPay:
          type: string
          format: date
          example: "2026-04-05"
        dateVat:
          type: string
          format: date
          example: "2026-03-29"
        paymentMethodId:
          type: integer
          example: 2
        currencyId:
          type: integer
          example: 1
        warehouseId:
          type: integer
          example: 1
        serviceId:
          type: integer
          example: 123
        customer:
          $ref: "#/components/schemas/InvoiceParty"
        items:
          type: array
          items:
            $ref: "#/components/schemas/InvoiceItemInput"
    InvoiceSummaryResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            invoiceId:
              type: integer
              example: 450
            uuid:
              type: string
              nullable: true
              format: uuid
              example: 8a6619f9-f857-4f4f-9dbf-9887ef3abdb3
            invoiceCode:
              type: string
              nullable: true
              example: INV-2026-0001
            totalGross:
              type: number
              format: float
              example: 1490
            totalNet:
              type: number
              format: float
              example: 1231.4
    ReservationStatus:
      type: object
      properties:
        code:
          type: integer
          example: 2001
        label:
          type: string
          nullable: true
          example: Přijato
    ReservationWarehouse:
      type: object
      properties:
        id:
          type: integer
          example: 1
        name:
          type: string
          example: iPhoneLab Ostrava
        city:
          type: string
          example: Ostrava
        email:
          type: string
          nullable: true
        phone:
          type: string
          nullable: true
    ReservationCustomer:
      type: object
      properties:
        id:
          type: integer
          example: 123
        firstName:
          type: string
          example: Jan
        lastName:
          type: string
          example: Novák
        email:
          type: string
          nullable: true
          example: jan@example.com
        phone:
          type: string
          nullable: true
          example: "+420777123456"
        companyName:
          type: string
          nullable: true
        companyId:
          type: string
          nullable: true
        companyVat:
          type: string
          nullable: true
    Reservation:
      type: object
      properties:
        id:
          type: integer
          example: 456
        code:
          type: string
          example: "202600123"
        uuid:
          type: string
          format: uuid
        shortId:
          type: string
          example: AB12CD
        scheduledAt:
          type: string
          example: "2026-06-23 14:30:00"
        date:
          type: string
          format: date
          example: "2026-06-23"
        timeFrom:
          type: string
          example: "14:30"
        outDate:
          type: string
          nullable: true
          example: "2026-06-24 16:00:00"
        status:
          $ref: "#/components/schemas/ReservationStatus"
        source:
          type: integer
          example: 1
        orderType:
          type: integer
          example: 1
        warehouse:
          $ref: "#/components/schemas/ReservationWarehouse"
        customer:
          $ref: "#/components/schemas/ReservationCustomer"
        services:
          type: array
          items:
            type: string
          example:
            - Diagnostika zařízení
    ReservationsListResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            reservations:
              type: array
              items:
                $ref: "#/components/schemas/Reservation"
            dateFrom:
              type: string
              format: date
            dateTo:
              type: string
              format: date
            paginator:
              $ref: "#/components/schemas/Paginator"
    WebhookResourceRef:
      type: object
      properties:
        type:
          type: string
          example: order
        id:
          type: string
          nullable: true
          example: "123"
        uuid:
          type: string
          nullable: true
          example: 550e8400-e29b-41d4-a716-446655440000
    WebhookEnvelope:
      type: object
      properties:
        delivery:
          type: object
          properties:
            id:
              type: string
              example: 9ad3ffc9-5872-44c6-8bfb-4e883ad02bfe
            event:
              type: string
              example: order:create
            createdAt:
              type: string
              format: date-time
              example: "2026-04-03T10:11:12Z"
            debugUrl:
              type: string
              example: https://private-api.myrepair.app/webhooks/debug/?delivery=9ad3ffc9-5872-44c6-8bfb-4e883ad02bfe&token=2e17f16a0c1df7a83e7b1f9610f8cdd1cf86b87b
        company:
          type: object
          properties:
            id:
              type: integer
              example: 1
            uuid:
              type: string
              nullable: true
            alias:
              type: string
              nullable: true
              example: iphlab
            projectName:
              type: string
              nullable: true
              example: iPhoneLab
        resource:
          $ref: "#/components/schemas/WebhookResourceRef"
        data:
          type: object
          additionalProperties: true
    WebhookDeliveryDebug:
      type: object
      properties:
        deliveryId:
          type: string
          example: 9ad3ffc9-5872-44c6-8bfb-4e883ad02bfe
        event:
          type: string
          example: order:update
        status:
          type: string
          example: delivered
        targetUrl:
          type: string
          example: https://hooks.example.com/myrepair
        responseCode:
          type: integer
          example: 200
        responseTime:
          type: integer
          example: 148
        createdAt:
          type: string
          nullable: true
          example: "2026-04-03 11:34:55"
        dispatchedAt:
          type: string
          nullable: true
          example: "2026-04-03 11:34:55"
        finishedAt:
          type: string
          nullable: true
          example: "2026-04-03 11:34:56"
        requestHeaders:
          type: object
          additionalProperties: true
        requestBody:
          oneOf:
            - type: object
              additionalProperties: true
            - type: string
        responseHeaders:
          type: array
          items:
            type: string
        responseBody:
          oneOf:
            - type: object
              additionalProperties: true
            - type: string
        errorMessage:
          type: string
          nullable: true
          example: ""
        resource:
          $ref: "#/components/schemas/WebhookResourceRef"
    WebhookDebugResponse:
      type: object
      properties:
        success:
          type: boolean
          example: true
        data:
          $ref: "#/components/schemas/WebhookDeliveryDebug"
