openapi: 3.0.3

info:
  title: easyPos Cloud Fiscalization API
  version: 1.0.1
  license:
    name: ISC
    url: https://opensource.org/licenses/ISC
  description: |
    API për fiskalizimin e faturave dhe të transaksioneve të arkës.

    ## Autentikimi
    Çdo kërkesë kërkon `Authorization: Bearer <token>`. Biznesi dhe pajisja
    merren nga token-i, prandaj nuk dërgohen në body. Zëvendësoni vlerën
    shembull të kokës `integration-app` me identifikuesin e qëndrueshëm që i
    është caktuar integrimit tuaj dhe përdoreni të pandryshuar në çdo kërkesë.

    ## `docId`
    Çdo dokument identifikohet nga `docId`, i cili zgjidhet nga ju dhe duhet të
    jetë unik. I njëjti `docId` nuk fiskalizohet dy herë: nëse e dërgoni sërish,
    kërkesa vazhdon të njëjtin dokument dhe kthen të njëjtin rezultat. Përdoreni
    për të riprovuar pa rrezik dublikimi. Në përgjigje kthehet si `orderId`.

    ## Faturë e zakonshme dhe faturë elektronike
    Një faturë e zakonshme (`isEinvoice: false`, parazgjedhje) është e përfunduar
    kur kthen `fic`.

    Një faturë elektronike (`isEinvoice: true`) është e përfunduar vetëm kur kthen
    **edhe `fic` edhe `eic`**. Nëse ndonjëri mungon, përgjigjja përmban vetëm
    `orderId` dhe `error` — trajtojeni si faturë të pafiskalizuar dhe riprovoni me
    të njëjtin `docId`.

    ## Kodet e TVSH-së
    `vatCode` varet nga statusi dhe konfigurimi fiskal i biznesit, jo vetëm nga
    artikulli. Mapping-u i konfirmuar është: `A` 0% për biznes jo subjekt të
    TVSH-së, `B` 20%, `C` 0% furnizim i përjashtuar, `D` 10%, `E` 6% dhe `J` 0%
    eksport mallrash. Kodet e tjera A–L nuk duhen përdorur pa konfigurim të
    konfirmuar. API-ja nuk ofron endpoint për këtë mapping; ruajeni në
    konfigurimin e integrimit.

    ## Gabimet
    Gabimet kthehen si `{ "message": "..." }`, me `field` shtesë kur dështon
    validimi. Fushat e panjohura në nivelin e parë të body-t e refuzojnë kërkesën.

  contact:
    name: ESDP

servers:
  - url: 'https://api.dev.easypos.al/fiscalisation-service/v1'
    description: Development
  - url: 'https://api.easypos.al/fiscalisation-service/v1'
    description: Production

tags:
  - name: invoice
    description: Fiskalizimi, korrigjimi, statusi dhe PDF-ja e faturave
  - name: balance
    description: Transaksionet e arkës
  - name: utilities
    description: Tatimpagues dhe operatorë

security:
  - bearerAuth: []

paths:
  /invoice/register:
    post:
      tags: [invoice]
      operationId: registerInvoice
      summary: Fiskalizon një faturë
      description: |
        Fiskalizon një faturë të re, ose vazhdon atë me të njëjtin `docId`.

        Për të korrigjuar një faturë ekzistuese, dërgoni `correctiveInvoice.iicRef`
        bashkë me artikujt e rinj.

        ### Llojet e dokumenteve (`documentType`)
        Lejohen vetëm kur `isEinvoice` mungon ose është `false`.

        - `ORDER` — porosi. Gjithnjë me para në dorë; `payment` nuk dërgohet, sepse
          porosia paguhet e plotë me metodën `ORDER` që e gjeneron shërbimi.
        - `SUMMARY` — faturë përmbledhëse. `articles` nuk dërgohen: rreshtat merren
          nga porositë e listuara te `summaryInvoices`, dhe `total` duhet të jetë
          saktësisht sa shuma e totaleve të tyre. Porositë shënohen si të përdorura,
          që të mos hyjnë në një faturë tjetër përmbledhëse.
        - `SELFISSUE` — vetëfaturim. Kërkon `selfIssueType` dhe të dhënat e
          furnitorit te `buyer`. Vetëm ky lloj lejon `reverseCharge`.
        - `EXPORT` — eksport. Të gjithë artikujt duhet të kenë TVSH të tipit
          eksport, dhe `buyer` është i detyrueshëm dhe jo i tipit `NUIS`.

        ### Kur `isEinvoice` është `true`
        - metodat e pagesës duhet të jenë pa para në dorë (`ACCOUNT`, `FACTORING`,
          `COMPENSATION`, `TRANSFER`, `WAIVER`, `KIND`, `OTHER`);
        - `buyer` është i detyrueshëm dhe duhet të jetë i tipit `NUIS`;
        - `selectedProcess` lejon `P1`–`P11`;
        - `selectedInvoiceType`, nëse nuk dërgohet, caktohet nga procesi:
          `P4→386`, `P9`/`P10`→`384`, `P11→326`, të tjerat `→380`;
        - `P4` kërkon `prepaidAmount` më të madh se zero dhe jo më shumë se totali;
        - `P9` dhe `P10` kërkojnë `correctiveInvoice.iicRef`, dhe fatura e referuar
          duhet të ketë `eic`.
      parameters:
        - $ref: '#/components/parameters/IntegrationApp'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RegisterInvoiceRequest'
            examples:
              eZakonshme:
                summary: Faturë me para në dorë
                value:
                  docId: 'SHOP-2026-000123'
                  articles:
                    - articleId: 'ART-1'
                      name: 'Kafe'
                      vatCode: 'B'
                      price: 120
                      units: 2
                      soldIn: 'XPP'
                  payment:
                    - type: CASH
                      amount: 240
              elektronike:
                summary: Faturë elektronike me transfertë bankare
                value:
                  docId: 'SHOP-2026-000124'
                  isEinvoice: true
                  selectedProcess: P1
                  payDeadline: '2026-09-30'
                  buyer:
                    buyerIDType: NUIS
                    buyerIDNum: 'K11715005L'
                    buyerName: 'VODAFONE ALBANIA'
                    buyerAddress: 'Autostrada Tiranë-Durrës, Rruga Pavarësia, Nr. 61'
                    buyerTown: 'Kashar'
                    buyerCountry: 'ALB'
                    buyerCountryCode: 'AL'
                  articles:
                    - articleId: 'ART-1'
                      name: 'Licencë software'
                      vatCode: 'B'
                      price: 100000
                      units: 1
                      soldIn: 'XPP'
                  payment:
                    - type: ACCOUNT
                      amount: 100000
                      details:
                        - idNumber: 'AL47212110090000000235698741'
                          name: 'Shitësi SHPK'
                          bankName: 'Banka XYZ'
                          swift_code: 'ABCDEFGH'
                          country: 'Shqipëri'
                          countryCode: 'AL'
                          currency: 'ALL'
              elektronikeP4:
                summary: Faturë elektronike parapagimi P4
                value:
                  docId: 'SHOP-2026-EINVOICE-P4'
                  isEinvoice: true
                  selectedProcess: P4
                  prepaidAmount: 5000
                  buyer:
                    buyerIDType: NUIS
                    buyerIDNum: 'K11715005L'
                    buyerName: 'VODAFONE ALBANIA'
                    buyerAddress: 'Autostrada Tiranë-Durrës, Rruga Pavarësia, Nr. 61'
                    buyerTown: 'Kashar'
                    buyerCountry: 'ALB'
                  articles:
                    - articleId: 'ADV-1'
                      name: 'Parapagim shërbimi'
                      vatCode: 'B'
                      price: 10000
                      units: 1
                      soldIn: 'XPP'
                  payment:
                    - type: TRANSFER
                      amount: 10000
              elektronikeP9:
                summary: Notë krediti elektronike P9
                value:
                  docId: 'SHOP-2026-EINVOICE-P9'
                  isEinvoice: true
                  selectedProcess: P9
                  correctiveInvoice:
                    iicRef: 'D21EBF3F7B7C502D6AAF2321A7CE2CE8'
                  buyer:
                    buyerIDType: NUIS
                    buyerIDNum: 'K11715005L'
                    buyerName: 'VODAFONE ALBANIA'
                    buyerAddress: 'Autostrada Tiranë-Durrës, Rruga Pavarësia, Nr. 61'
                    buyerTown: 'Kashar'
                    buyerCountry: 'ALB'
                  articles:
                    - articleId: 'CORR-1'
                      name: 'Korrigjim shërbimi'
                      vatCode: 'B'
                      price: -1000
                      units: 1
                      soldIn: 'XPP'
                  payment:
                    - type: TRANSFER
                      amount: -1000
              elektronikeP11:
                summary: Faturim elektronik i pjesshëm P11
                value:
                  docId: 'SHOP-2026-EINVOICE-P11'
                  isEinvoice: true
                  selectedProcess: P11
                  buyer:
                    buyerIDType: NUIS
                    buyerIDNum: 'K11715005L'
                    buyerName: 'VODAFONE ALBANIA'
                    buyerAddress: 'Autostrada Tiranë-Durrës, Rruga Pavarësia, Nr. 61'
                    buyerTown: 'Kashar'
                    buyerCountry: 'ALB'
                  articles:
                    - articleId: 'PART-1'
                      name: 'Faturim i pjesshëm'
                      vatCode: 'B'
                      price: 25000
                      units: 1
                      soldIn: 'XPP'
                  payment:
                    - type: TRANSFER
                      amount: 25000
              meBlerës:
                summary: Faturë me para në dorë, me blerës
                value:
                  docId: 'SHOP-2026-000125'
                  buyer:
                    buyerIDType: NUIS
                    buyerIDNum: 'K11715005L'
                    buyerName: 'VODAFONE ALBANIA'
                    buyerAddress: 'Autostrada Tiranë-Durrës, Rruga Pavarësia, Nr. 61'
                    buyerTown: 'Kashar'
                    buyerCountry: 'ALB'
                  articles:
                    - articleId: 'ART-7'
                      name: 'Tastierë'
                      vatCode: 'B'
                      price: 3600
                      units: 2
                      soldIn: 'XPP'
                  payment:
                    - type: CASH
                      amount: 7200
              porosi:
                summary: Porosi (ORDER) — pa payment
                value:
                  docId: 'SHOP-2026-000200'
                  documentType: ORDER
                  articles:
                    - articleId: 'ART-1'
                      name: 'Kafe'
                      vatCode: 'B'
                      price: 120
                      units: 2
                      soldIn: 'XPP'
              permbledhese:
                summary: Faturë përmbledhëse (SUMMARY) — pa articles
                value:
                  docId: 'SHOP-2026-000201'
                  documentType: SUMMARY
                  summaryInvoices:
                    - 'D21EBF3F7B7C502D6AAF2321A7CE2CE8'
                    - 'A11EBF3F7B7C502D6AAF2321A7CE2CE9'
                  total: 7200
                  payment:
                    - type: CASH
                      amount: 7200
              vetefaturim:
                summary: Vetëfaturim (SELFISSUE) me autongarkesë
                value:
                  docId: 'SHOP-2026-000202'
                  documentType: SELFISSUE
                  selfIssueType: ABROAD
                  reverseCharge: true
                  buyer:
                    buyerIDType: NUIS
                    buyerIDNum: 'L93416401M'
                    buyerName: 'Shitësi SHPK'
                    buyerAddress: 'Rruga e Durrësit'
                    buyerTown: 'Tiranë'
                    buyerCountry: 'ALB'
                  articles:
                    - articleId: 'ART-9'
                      name: 'Shërbim i importuar'
                      vatCode: 'B'
                      price: 50000
                      units: 1
                      soldIn: 'XPP'
                  payment:
                    - type: CASH
                      amount: 60000
              eksport:
                summary: Faturë eksporti (EXPORT)
                value:
                  docId: 'SHOP-2026-000203'
                  documentType: EXPORT
                  supplyPeriod:
                    start: '2026-03-01'
                    end: '2026-03-31'
                  buyer:
                    buyerIDType: PASS
                    buyerIDNum: 'X1234567'
                    buyerName: 'Blerësi i huaj'
                    buyerAddress: 'Via Roma 1'
                    buyerTown: 'Bari'
                    buyerCountry: 'ITA'
                    buyerCountryCode: 'IT'
                  articles:
                    - articleId: 'ART-3'
                      name: 'Mall për eksport'
                      vatCode: 'J'
                      price: 25000
                      units: 4
                      soldIn: 'XPP'
                  payment:
                    - type: CASH
                      amount: 100000
      responses:
        '200':
          $ref: '#/components/responses/InvoiceResult'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'

  /invoice/cancel:
    post:
      tags: [invoice]
      operationId: cancelInvoice
      summary: Anulon një faturë të fiskalizuar
      description: |
        Lëshon një faturë korrigjuese duke përmbysur artikujt dhe pagesat e faturës
        së identifikuar nga `correctiveInvoice.iicRef`. Artikujt nuk dërgohen.

        Fatura e referuar duhet të ekzistojë, të mos jetë vetë korrigjuese, dhe —
        nëse është elektronike — të ketë `eic`.

        `docId` duhet të jetë i ri, i ndryshëm nga ai i faturës origjinale.
        Anulimi normal përfundon me `fic`; anulimi elektronik përfundon vetëm kur
        përgjigjja përmban edhe `fic` edhe `eic`.
      parameters:
        - $ref: '#/components/parameters/IntegrationApp'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CancelInvoiceRequest'
            examples:
              normal:
                summary: Anulim i faturës normale
                value:
                  docId: 'SHOP-2026-000123-CANCEL'
                  correctiveInvoice:
                    iicRef: 'D21EBF3F7B7C502D6AAF2321A7CE2CE8'
                  invoiceNotes: 'Anulim me kërkesë të klientit'
              electronic:
                summary: Anulim elektronik P10
                value:
                  docId: 'SHOP-2026-000124-CANCEL'
                  isEinvoice: true
                  selectedProcess: P10
                  correctiveInvoice:
                    iicRef: 'A11EBF3F7B7C502D6AAF2321A7CE2CE9'
                  invoiceNotes: 'Anulim i faturës elektronike'
      responses:
        '200':
          $ref: '#/components/responses/InvoiceResult'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'

  /invoice/status:
    post:
      tags: [invoice]
      operationId: getInvoiceStatus
      summary: Kthen statusin e një fature
      description: |
        Kthen gjendjen e faturës me `docId`-in e dhënë. Nëse fatura nuk është e
        përfunduar, kërkesa provon ta përfundojë atë dhe kthen rezultatin.

        Kthen `400` nëse `docId` nuk gjendet.
      parameters:
        - $ref: '#/components/parameters/IntegrationApp'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/StatusInvoiceRequest'
            example:
              docId: 'SHOP-2026-000123'
      responses:
        '200':
          $ref: '#/components/responses/InvoiceResult'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'

  /invoice/pdf:
    post:
      tags: [invoice]
      operationId: getInvoicePdf
      summary: Kthen dokumentin e faturës si base64
      description: |
        | `pdfType`  | Dokumenti                         | Formati |
        |------------|-----------------------------------|---------|
        | `A4`       | Faturë tatimore A4                | PDF     |
        | `receipt`  | Kupon tatimor, sipas `paperWidth` | PNG     |
        | `eInvoice` | Fatura zyrtare elektronike        | PDF     |

        `eInvoice` kërkon që fatura të ketë `eic`; përndryshe kthehet `400`.
        `paperWidth` vlen vetëm për `receipt`, `lang` vetëm për `A4`.
      parameters:
        - $ref: '#/components/parameters/IntegrationApp'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/InvoicePdfRequest'
            examples:
              a4:
                summary: Faturë tatimore A4
                value:
                  iic: 'D21EBF3F7B7C502D6AAF2321A7CE2CE8'
                  pdfType: A4
                  lang: sq
              kupon:
                summary: Kupon tatimor 80mm
                value:
                  iic: 'D21EBF3F7B7C502D6AAF2321A7CE2CE8'
                  pdfType: receipt
                  paperWidth: 80
              elektronike:
                summary: Faturë elektronike
                value:
                  iic: 'D21EBF3F7B7C502D6AAF2321A7CE2CE8'
                  pdfType: eInvoice
      responses:
        '200':
          description: Dokumenti i gjeneruar
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: '#/components/schemas/PdfResponse'
                  - $ref: '#/components/schemas/EinvoicePdfResponse'
              examples:
                a4:
                  summary: A4 ose receipt
                  value:
                    base64: 'JVBERi0xLjQKJcfsj6IK...'
                    lang: sq
                elektronike:
                  summary: eInvoice
                  value:
                    base64: 'JVBERi0xLjQKJcfsj6IK...'
                    eic: '5e1ee62d-f4b5-49f8-bfdf-049703fbd244'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'

  /balance/initiate:
    post:
      tags: [balance]
      operationId: initiateBalance
      summary: Raporton gjendjen fillestare të arkës
      description: |
        Raportoni gjendjen fillestare një herë në fillim të çdo dite pune, për
        pajisjen fiskale përkatëse, përpara faturës së parë me pagesë cash. Mos e
        përsëritni për çdo faturë ose turn brenda së njëjtës ditë. Ndryshimet
        fizike të gjendjes gjatë turneve raportohen me `/balance/deposit` ose
        `/balance/withdraw`. Nuk ka endpoint të veçantë për mbylljen e turnit.
      parameters:
        - $ref: '#/components/parameters/IntegrationApp'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BalanceRequest'
            example:
              docId: '3cd36a41-d330-4aa2-85cc-cce60fa0f84a'
              amount: 10000
      responses:
        '200':
          $ref: '#/components/responses/BalanceResult'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'

  /balance/withdraw:
    post:
      tags: [balance]
      operationId: withdrawBalance
      summary: Raporton tërheqje nga arka
      parameters:
        - $ref: '#/components/parameters/IntegrationApp'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BalanceRequest'
            example:
              docId: 'SHIFT-2026-08-25-OUT-1'
              amount: 2500
              notes: 'Derdhje në bankë'
      responses:
        '200':
          $ref: '#/components/responses/BalanceResult'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'

  /balance/deposit:
    post:
      tags: [balance]
      operationId: depositBalance
      summary: Raporton derdhje në arkë
      parameters:
        - $ref: '#/components/parameters/IntegrationApp'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BalanceRequest'
            example:
              docId: 'SHIFT-2026-08-25-IN-1'
              amount: 5000
      responses:
        '200':
          $ref: '#/components/responses/BalanceResult'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'

  /utilities/get-taxpayers:
    post:
      tags: [utilities]
      operationId: getTaxpayers
      summary: Kërkon tatimpagues
      description: |
        Nëse `searchTerm` ka formatin e një NIPT-i, kërkimi bëhet me NIPT,
        përndryshe me emër. Përdoret për të kërkuar dhe plotësuar `buyer`, jo
        për verifikimin përfundimtar të statusit tatimor: përgjigjja nuk përmban
        status aktiv, pasiv ose të çregjistruar. Nuk është publikuar një kufi
        numerik kërkesash; përdorni debounce dhe mos dërgoni kërkesë për çdo tast.
      parameters:
        - $ref: '#/components/parameters/IntegrationApp'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GetTaxpayersRequest'
            example:
              searchTerm: 'Vodafone'
      responses:
        '200':
          description: Lista e tatimpaguesve
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Taxpayer'
              example:
                - Address: 'Rruga Pavaresia, kodi postal 1050, Kashar 61'
                  Country: 'ALB'
                  Name: 'FONDACIONI VODAFONE ALBANIA'
                  Tin: 'K72118452F'
                  Town: 'Tirane'
                - Address: 'Autostrada Tirane-Durres, Rruga Pavaresia, Nr.61, Kashar'
                  Country: 'ALB'
                  Name: 'VODAFONE ALBANIA'
                  Tin: 'K11715005L'
                  Town: 'Kashar'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'

  /utilities/get-operators:
    post:
      tags: [utilities]
      operationId: getOperators
      summary: Liston operatorët
      description: |
        Kthen operatorët e disponueshëm. `opCode` përdoret si `operatorCode` në
        kërkesat e fiskalizimit.
      responses:
        '200':
          description: Lista e operatorëve
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Operator'
              example:
                - name: 'test3'
                  opCode: 'gh537ez280'
                - name: 'User A'
                  opCode: 'aa111aa222'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'

components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

  parameters:
    IntegrationApp:
      name: integration-app
      in: header
      required: false
      description: >-
        Identifikuesi i qëndrueshëm i integrimit thirrës. Zëvendësoni vlerën
        shembull me identifikuesin që i është caktuar integrimit tuaj.
      schema:
        type: string
      example: erp-x

  responses:
    InvoiceResult:
      description: |
        Rezultati i fiskalizimit. Për një faturë elektronike të papërfunduar
        kthehen vetëm `orderId` dhe `error`.
      content:
        application/json:
          schema:
            anyOf:
              - $ref: '#/components/schemas/InvoiceResponse'
              - $ref: '#/components/schemas/InvoiceIncompleteResponse'
          examples:
            eZakonshme:
              summary: Faturë e fiskalizuar
              value:
                orderId: 'SHOP-2026-000123'
                fic: '52ca073b-536e-48e9-8678-cc0bf2202046'
                iic: 'D21EBF3F7B7C502D6AAF2321A7CE2CE8'
                link: 'https://efiskalizimi-app.tatime.gov.al/invoice-check/#/verify?iic=...'
                invoiceNumber: '12/2026/xx123xx123'
                invoiceOrderNumber: 12
                invoiceType: CASH
                totalPrice: 240
                totalPriceWithoutVat: 200
                totalVatAmount: 40
                operatorCode: 'ab123ab123'
                businessUnitCode: 'bu123bu123'
                tcrCode: 'xx123xx123'
                sellerName: 'Shitësi SHPK'
                sellerNuis: 'L93416401M'
                sellerAddress: 'Rruga e Durrësit'
            elektronike:
              summary: Faturë elektronike e përfunduar
              value:
                orderId: 'SHOP-2026-000124'
                fic: '52ca073b-536e-48e9-8678-cc0bf2202046'
                eic: '5e1ee62d-f4b5-49f8-bfdf-049703fbd244'
                iic: 'D21EBF3F7B7C502D6AAF2321A7CE2CE8'
                link: 'https://efiskalizimi-app.tatime.gov.al/invoice-check/#/verify?iic=...'
                invoiceNumber: '13/2026'
                invoiceOrderNumber: 13
                invoiceType: NONCASH
                totalPrice: 120000
            ePapërfunduar:
              summary: Faturë elektronike e papërfunduar — riprovoni me të njëjtin docId
              value:
                orderId: 'SHOP-2026-000124'
                error:
                  otherError: 'Provoni me vone'

    BalanceResult:
      description: Rezultati i raportimit të arkës
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/BalanceResponse'
          examples:
            sukses:
              value:
                orderId: '3cd36a41-d330-4aa2-85cc-cce60fa0f84a'
                fcdc: 'b5c3e1a2-9f44-4c3a-9c1e-2f0d7a5b8e10'
            gabim:
              value:
                orderId: '3cd36a41-d330-4aa2-85cc-cce60fa0f84a'
                error:
                  cisError:
                    faultEnv: 'env:CLIENT'
                    faultString: 'Invalid TCR code'
                    faultCode: '112'

    BadRequest:
      description: Kërkesë e pavlefshme
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            validim:
              summary: Gabim validimi
              value:
                message: 'selectedProcess duhet te jete nje nga: P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11'
                field: selectedProcess
            fushëEPanjohur:
              summary: Fushë e panjohur
              value:
                message: 'Unknown fields found, please remove them: orderTimestamp:2026-08-25'
            rregull:
              summary: Kufizim i faturës elektronike
              value:
                message: 'Klienti i faturës elektronike duhet të ketë një numër identifikues të llojit NIPT!'
            konkurencë:
              summary: Kërkesë paralele për të njëjtin dokument
              value:
                message: 'Një kërkesë tjetër po përpunohet!'

    Unauthorized:
      description: Token mungon, ka skaduar ose është i pavlefshëm
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            message: 'Not authorized'

  schemas:
    Error:
      type: object
      required: [message]
      properties:
        message:
          type: string
        field:
          type: string
          description: Fusha që dështoi, vetëm për gabimet e validimit

    CisError:
      type: object
      description: Gabim i kthyer nga sistemi i tatimeve
      properties:
        faultEnv:
          type: string
          description: |
            `env:CLIENT` — kërkesa është e pasaktë dhe s'ka kuptim të riprovohet.
            `env:SERVER` — gabim i përkohshëm.
          example: 'env:CLIENT'
        faultString:
          type: string
          example: 'Nuk është bërë raportimi i balancës ditore dhe fatura ka metoda pagese CASH!'
        faultCode:
          type: string
          example: '123'

    FiscalError:
      type: object
      description: Arsyeja pse dokumenti nuk u fiskalizua
      properties:
        cisError:
          $ref: '#/components/schemas/CisError'
        otherError:
          type: string
          description: Gabim i përkohshëm — riprovoni me të njëjtin `docId`
          example: 'Provoni me vone'
      additionalProperties: true

    Rebate:
      type: object
      description: Zbritje. Lejohet vetëm njëra nga të dyja fushat.
      properties:
        inPercentage:
          type: number
          example: 10
        inValue:
          type: number
          example: 500

    Currency:
      type: object
      description: Nëse mungon, përdoret `ALL` me kurs `1`.
      properties:
        code:
          type: string
          default: ALL
          example: EUR
        exRate:
          type: number
          description: Kursi ndaj LEK-ut. I detyrueshëm kur `code` nuk është `ALL`.
          example: 101.5

    Article:
      type: object
      required: [articleId, name, vatCode, price, units, soldIn]
      properties:
        articleId:
          type: string
          maxLength: 100
          description: Identifikuesi i artikullit në sistemin tuaj
          example: 'ART-1'
        name:
          type: string
          maxLength: 100
          example: 'Kafe'
        vatCode:
          type: string
          enum: [A, B, C, D, E, F, G, H, I, J, K, L]
          description: >-
            Kodi sipas statusit dhe konfigurimit fiskal të biznesit: A = 0% për
            biznes jo subjekt të TVSH-së, B = 20%, C = 0% furnizim i përjashtuar,
            D = 10%, E = 6%, J = 0% eksport mallrash. Mos përdorni kode të tjera
            A–L pa konfigurim të konfirmuar.
          example: 'B'
        price:
          type: number
          description: Çmimi për njësi, me TVSH, në monedhën e faturës
          example: 120
        units:
          type: number
          example: 2
        soldIn:
          type: string
          description: >-
            Kodi UN/CEFACT i njësisë matëse. Shkarkoni listën e mbështetur në
            https://easypos.al/downloads/lista-e-njesive-matese.xlsx
          example: 'XPP'
        totalPrice:
          type: number
          description: |
            Totali i rreshtit me TVSH. Nëse mungon, llogaritet si `price × units`.
          example: 240
        rebate:
          $ref: '#/components/schemas/Rebate'

    PaymentDetail:
      type: object
      description: E detyrueshme kur `type` është `ACCOUNT`
      required: [idNumber, name, bankName, swift_code, country, countryCode, currency]
      properties:
        idNumber:
          type: string
          description: IBAN ose numri i llogarisë
          example: 'AL47212110090000000235698741'
        name:
          type: string
          example: 'Shitësi SHPK'
        bankName:
          type: string
          example: 'BKT'
        swift_code:
          type: string
          example: 'ABCDEFGH'
        country:
          type: string
          example: 'Shqipëri'
        countryCode:
          type: string
          minLength: 2
          maxLength: 2
          example: 'AL'
        currency:
          type: string
          minLength: 3
          maxLength: 3
          example: 'ALL'

    Payment:
      type: object
      required: [type, amount]
      properties:
        type:
          type: string
          enum:
            - CASH
            - BANKNOTE
            - CARD
            - CHECK
            - SVOUCHER
            - COMPANY
            - ORDER
            - ACCOUNT
            - FACTORING
            - COMPENSATION
            - TRANSFER
            - WAIVER
            - KIND
            - OTHER
          description: |
            `CASH` është alias i `BANKNOTE`.

            Me para në dorë: `BANKNOTE`, `CARD`, `CHECK`, `SVOUCHER`, `COMPANY`,
            `ORDER`. Pa para në dorë: `ACCOUNT`, `FACTORING`, `COMPENSATION`,
            `TRANSFER`, `WAIVER`, `KIND`, `OTHER`.

            Metoda e parë përcakton nëse fatura është `CASH` apo `NONCASH`.
          example: ACCOUNT
        amount:
          type: number
          description: |
            Vlera në monedhën e faturës. Shuma e pagesave duhet të jetë saktësisht
            sa totali i faturës.
          example: 120000
        details:
          type: array
          description: E detyrueshme dhe jo bosh kur `type` është `ACCOUNT`
          items:
            $ref: '#/components/schemas/PaymentDetail'

    Buyer:
      type: object
      required: [buyerIDType, buyerIDNum, buyerName, buyerAddress, buyerTown, buyerCountry]
      properties:
        buyerIDType:
          type: string
          enum: [NUIS, ID, PASS, VAT, TAX, SOC, POINTS]
          description: Për faturat elektronike duhet të jetë `NUIS`.
          example: NUIS
        buyerIDNum:
          type: string
          description: Për `NUIS`, normalizojeni me trim dhe uppercase para validimit
          pattern: '^[A-Za-z][0-9]{8}[A-Za-z]$'
          example: 'K11715005L'
        buyerName:
          type: string
          example: 'VODAFONE ALBANIA'
        buyerAddress:
          type: string
          example: 'Autostrada Tiranë-Durrës, Rruga Pavarësia, Nr. 61'
        buyerTown:
          type: string
          example: 'Kashar'
        buyerCountry:
          type: string
          example: 'ALB'
        buyerCountryCode:
          type: string
          minLength: 2
          maxLength: 2
          description: Kodi ISO-2 i shtetit. Nëse mungon, merret `AL`.
          example: 'AL'

    CorrectiveInvoiceRef:
      type: object
      required: [iicRef]
      properties:
        iicRef:
          type: string
          description: |
            `iic` i faturës që korrigjohet. Fatura duhet të ekzistojë, të mos jetë
            vetë korrigjuese, dhe — nëse është elektronike — të ketë `eic`.
          example: 'D21EBF3F7B7C502D6AAF2321A7CE2CE8'
        issueDateTime:
          type: string
          format: date
          description: Nëse mungon, merret nga fatura origjinale.

    RegisterInvoiceRequest:
      type: object
      required: [docId]
      additionalProperties: false
      properties:
        docId:
          type: string
          minLength: 5
          maxLength: 200
          description: Identifikuesi juaj, unik për çdo dokument
          example: 'SHOP-2026-000123'
        operatorCode:
          type: string
          pattern: '^[a-z]{2}\d{3}[a-z]{2}\d{3}$'
          description: Nga `/utilities/get-operators`. Nëse mungon, zgjidhet automatikisht.
          example: 'ab123ab123'
        currency:
          $ref: '#/components/schemas/Currency'
        articles:
          type: array
          minItems: 1
          description: |
            I detyrueshëm, përveç kur `documentType` është `SUMMARY` — atëherë nuk
            dërgohet fare dhe rreshtat ndërtohen nga porositë e referuara.
          items:
            $ref: '#/components/schemas/Article'
        payment:
          type: array
          minItems: 1
          description: |
            I detyrueshëm, përveç kur `documentType` është `ORDER` — atëherë nuk
            dërgohet fare dhe gjenerohet nga shërbimi.
          items:
            $ref: '#/components/schemas/Payment'
        invoiceRebate:
          allOf:
            - $ref: '#/components/schemas/Rebate'
          description: Zbritje mbi të gjithë faturën, e shpërndarë mbi artikujt.
        buyer:
          $ref: '#/components/schemas/Buyer'
        correctiveInvoice:
          $ref: '#/components/schemas/CorrectiveInvoiceRef'
        invoiceNotes:
          type: string
          maxLength: 500
          example: 'Faleminderit!'
        documentType:
          type: string
          enum: [NORMAL, ORDER, SUMMARY, SELFISSUE, EXPORT]
          default: NORMAL
          description: |
            Lloji i dokumentit. Lejohet vetëm kur `isEinvoice` mungon ose është `false`.

            - `NORMAL` — faturë e zakonshme
            - `ORDER` — porosi; gjithnjë me para në dorë, `payment` nuk dërgohet
            - `SUMMARY` — faturë përmbledhëse e disa porosive; `articles` nuk dërgohen
            - `SELFISSUE` — vetëfaturim; kërkon `selfIssueType`
            - `EXPORT` — faturë eksporti
        selfIssueType:
          type: string
          enum: [AGREEMENT, DOMESTIC, ABROAD, SELF, OTHER]
          description: |
            Lloji i vetëfaturimit. I detyrueshëm dhe i lejuar vetëm kur
            `documentType` është `SELFISSUE`.

            Për `ABROAD`, furnitori te `buyer` duhet të jetë vetë lëshuesi i
            faturës dhe artikujt nuk mund të përziejnë TVSH zero me TVSH standarde.
        reverseCharge:
          type: boolean
          description: |
            Autongarkesë. Lejohet e vërtetë vetëm kur `documentType` është
            `SELFISSUE`.
        summaryInvoices:
          type: array
          minItems: 1
          items:
            type: string
            pattern: '^[0-9A-Fa-f]{32}$'
          description: |
            `iic`-të e porosive që përmblidhen. I detyrueshëm dhe i lejuar vetëm
            kur `documentType` është `SUMMARY`.

            Çdo porosi duhet të jetë e fiskalizuar, të mos jetë përdorur në një
            faturë tjetër përmbledhëse, dhe të jetë në të njëjtën monedhë.
          example: ['D21EBF3F7B7C502D6AAF2321A7CE2CE8']
        total:
          type: number
          description: |
            Totali i faturës përmbledhëse, që duhet të jetë saktësisht sa shuma e
            totaleve të porosive të referuara. I detyrueshëm dhe i lejuar vetëm
            kur `documentType` është `SUMMARY`.
          example: 7200
        supplyPeriod:
          type: object
          required: [start, end]
          description: |
            Periudha e furnizimit. Të dyja datat duhet të jenë brenda të njëjtit
            muaj kalendarik, me `start` jo më të madhe se `end`.
          properties:
            start:
              type: string
              format: date
              pattern: '^\d{4}-\d{2}-\d{2}$'
              example: '2026-03-01'
            end:
              type: string
              format: date
              pattern: '^\d{4}-\d{2}-\d{2}$'
              example: '2026-03-31'
        isEinvoice:
          type: boolean
          default: false
          description: Kur është `true`, fatura lëshohet si faturë elektronike.
        selectedProcess:
          type: string
          enum: [P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11]
          default: P1
          description: |
            Procesi i faturimit:
            `P4` pagesë paraprake · `P9` notë krediti · `P10` faturim korrigjues ·
            `P11` faturim i pjesshëm.
        selectedInvoiceType:
          type: string
          enum:
            [
              '82',
              '84',
              '325',
              '326',
              '380',
              '383',
              '386',
              '393',
              '394',
              '395',
              '575',
              '623',
              '780',
            ]
          description: |
            Nëse mungon, caktohet nga `selectedProcess`. Llojet `80`, `381`, `384`,
            `385` dhe `389` pranohen vetëm kur i cakton vetë procesi.
        payDeadline:
          type: string
          format: date
          pattern: '^\d{4}-\d{2}-\d{2}$'
          description: |
            Afati i pagesës — brenda vitit aktual dhe jo në të shkuarën. Nëse
            mungon, merret data e faturës.
          example: '2026-09-30'
        prepaidAmount:
          type: number
          minimum: 0
          multipleOf: 0.01
          default: 0
          description: |
            Vlera e parapaguar, në monedhën e faturës, me maksimum dy shifra pas
            presjes. E detyrueshme kur `selectedProcess` është `P4`; përndryshe
            injorohet.
          example: 50000

    CancelInvoiceRequest:
      type: object
      required: [docId, correctiveInvoice]
      additionalProperties: false
      properties:
        docId:
          type: string
          minLength: 5
          maxLength: 200
          example: 'SHOP-2026-000123-CANCEL'
        operatorCode:
          type: string
          pattern: '^[a-z]{2}\d{3}[a-z]{2}\d{3}$'
          example: 'ab123ab123'
        correctiveInvoice:
          $ref: '#/components/schemas/CorrectiveInvoiceRef'
        invoiceNotes:
          type: string
          maxLength: 500
        isEinvoice:
          type: boolean
          description: Nëse mungon, trashëgohet nga fatura origjinale.
        selectedProcess:
          type: string
          enum: [P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11]
          description: Për faturat elektronike, nëse mungon, merret `P10`.
        selectedInvoiceType:
          type: string
          enum:
            [
              '82',
              '84',
              '325',
              '326',
              '380',
              '383',
              '386',
              '393',
              '394',
              '395',
              '575',
              '623',
              '780',
            ]
        payDeadline:
          type: string
          format: date
          pattern: '^\d{4}-\d{2}-\d{2}$'
        prepaidAmount:
          type: number
          minimum: 0
          multipleOf: 0.01

    StatusInvoiceRequest:
      type: object
      required: [docId]
      additionalProperties: false
      properties:
        docId:
          type: string
          minLength: 5
          maxLength: 200
          example: 'SHOP-2026-000123'

    InvoicePdfRequest:
      type: object
      required: [iic]
      additionalProperties: false
      properties:
        iic:
          type: string
          pattern: '^[0-9A-Fa-f]{32}$'
          description: 32 karaktere heksadecimale
          example: 'D21EBF3F7B7C502D6AAF2321A7CE2CE8'
        pdfType:
          type: string
          enum: [A4, receipt, eInvoice]
          default: A4
        paperWidth:
          type: integer
          enum: [58, 80, 110]
          default: 80
        lang:
          type: string
          enum: [sq, en]
          example: sq

    BalanceRequest:
      type: object
      required: [docId, amount]
      additionalProperties: false
      properties:
        docId:
          type: string
          minLength: 5
          maxLength: 200
          description: >-
            Identifikues unik i operacionit, pa format semantik të detyrueshëm.
            Ripërdorni të njëjtën vlerë vetëm gjatë retry-t të të njëjtit operacion.
          example: '3cd36a41-d330-4aa2-85cc-cce60fa0f84a'
        amount:
          type: number
          description: Vlera në LEK
          example: 10000
        notes:
          type: string
          example: 'Derdhje në bankë'
        operatorCode:
          type: string
          pattern: '^[a-z]{2}\d{3}[a-z]{2}\d{3}$'
          example: 'ab123ab123'

    GetTaxpayersRequest:
      type: object
      required: [searchTerm]
      additionalProperties: false
      properties:
        searchTerm:
          type: string
          minLength: 3
          maxLength: 200
          description: NIPT ose emër biznesi
          example: 'K11715005L'

    InvoiceResponse:
      type: object
      description: Fatura e fiskalizuar
      properties:
        orderId:
          type: string
          description: '`docId` i dërguar në kërkesë'
        fic:
          type: string
          description: Kodi i faturës i lëshuar nga sistemi i tatimeve
        eic:
          type: string
          description: Kodi i faturës elektronike, vetëm kur `isEinvoice` është `true`
        iic:
          type: string
          description: Kodi identifikues i faturës
        link:
          type: string
          format: uri
          description: Lidhja e verifikimit publik të faturës
        error:
          $ref: '#/components/schemas/FiscalError'
        invoiceNumber:
          type: string
          example: '12/2026/xx123xx123'
        invoiceOrderNumber:
          type: integer
          example: 12
        invoiceType:
          type: string
          enum: [CASH, NONCASH]
        totalPrice:
          type: number
        totalPriceWithoutVat:
          type: number
        totalVatAmount:
          type: number
        taxFreeAmount:
          type: number
        goodsExport:
          type: number
        markUpAmount:
          type: number
        operatorCode:
          type: string
        businessUnitCode:
          type: string
        tcrCode:
          type: string
          description: Bosh për faturat elektronike
        sellerName:
          type: string
        sellerNuis:
          type: string
        sellerAddress:
          type: string

    InvoiceIncompleteResponse:
      type: object
      description: |
        Faturë elektronike e papërfunduar. Nuk kthehen `fic`, `eic`, `iic` apo
        `link` — riprovoni me të njëjtin `docId`.
      properties:
        orderId:
          type: string
        error:
          $ref: '#/components/schemas/FiscalError'

    PdfResponse:
      type: object
      description: Përgjigje për `A4` dhe `receipt`
      properties:
        base64:
          type: string
          description: Dokumenti i koduar në base64
        lang:
          type: string
          example: sq

    EinvoicePdfResponse:
      type: object
      description: Përgjigje për `eInvoice`
      properties:
        base64:
          type: string
          description: PDF-ja e koduar në base64
        eic:
          type: string
          example: '5e1ee62d-f4b5-49f8-bfdf-049703fbd244'

    BalanceResponse:
      type: object
      properties:
        orderId:
          type: string
          description: '`docId` i dërguar në kërkesë'
        fcdc:
          type: string
          description: Kodi i transaksionit i lëshuar nga sistemi i tatimeve
          example: 'b5c3e1a2-9f44-4c3a-9c1e-2f0d7a5b8e10'
        error:
          $ref: '#/components/schemas/FiscalError'

    Taxpayer:
      type: object
      properties:
        Tin:
          type: string
          example: 'K11715005L'
        Name:
          type: string
          example: 'VODAFONE ALBANIA'
        Address:
          type: string
        Town:
          type: string
        Country:
          type: string
          description: Kodi ISO 3166-1 alpha-3, p.sh. ALB për Shqipërinë
      additionalProperties: true

    Operator:
      type: object
      properties:
        name:
          type: string
          example: 'test3'
        opCode:
          type: string
          description: Përdoret si `operatorCode` në kërkesat e fiskalizimit
          example: 'gh537ez280'
