_Version: 1.0_

> This document is the LLM-friendly export of the API. It is regenerated on every request from the live OpenAPI spec. Use it as context when asking an AI assistant for help.

# fature.al API

API per integrimin me fature.al - sistemi i fiskalizimit dhe faturimit per bizneset ne Shqiperi.

## Identifikimi

Cdo kerkese ka dy nivele identifikimi: **kush** e ben (perdoruesi, me Bearer token) dhe **cili software** e ben (aplikacioni juaj, me client id dhe client secret).

```
Authorization: Bearer {api_token}
X-Client-Id: ft_id_...
X-Client-Secret: ft_sk_...
```

Token-in e gjeneroni nga **Konfigurime > API Tokens** ne panelin e fature.al, ose e merrni nga pergjigja e endpoint-it Register Company. Ai i perket klientit tuaj dhe ndryshon nga njeri klient te tjetri.

Client id dhe client secret i perkasin **aplikacionit tuaj**, jo klientit: jane te njejtat per te gjithe bizneset qe perdorin software-in tuaj. Shihni "Identifikoni aplikacionin tuaj" me poshte per menyren se si i merrni dhe si i rigjeneroni.

## Serverat

Cdo rruge ne kete dokument eshte relative ndaj adresave me poshte, prandaj `/invoice/cash` do te
thote `https://fature.al/api/v1/invoice/cash`.

| Mjedisi | URL |
|---------|-----|
| **Live** | `https://fature.al/api/v1` |
| **Sandbox/Demo** | `https://demo.fature.al/api/v1` |

## Dokumentet e tjera

API-ja botohet ne tre dokumente, sepse secili ka adrese baze te vetin.

| Dokumenti | Cfare mbulon | Adresa |
|-----------|--------------|--------|
| **v1** (ky dokument) | e gjithe API-ja e faturimit dhe e onboarding-ut | [`/docs/api`](/docs/api) |
| **v2** | klientet ne formatin e ri me objekte te ndara | [`/docs/api/v2`](/docs/api/v2) |
| **Partner** | porosite e Wolt per nje njesi te vetme | [`/docs/api/partner`](/docs/api/partner) |

Secili dokument botohet edhe si OpenAPI JSON (`/docs/api.json`) dhe si Markdown per asistentet AI
(`/docs/api.md`).

## Postman dhe mjete te tjera

Nuk shperndajme koleksion Postman, sepse do te vjeteronte sa here ndryshon API. Ne vend te tij
importoni direkt dokumentin OpenAPI, i cili gjenerohet ne cdo kerkese dhe eshte gjithmone i
perditesuar:

**Postman** > *Import* > *Link* > `https://fature.al/docs/api.json`

I njejti adresim vlen per Insomnia, Bruno, Swagger UI ose cdo gjenerues klientesh. Per v2 dhe per
partner API-n perdorni `/docs/api/v2.json` dhe `/docs/api/partner.json`.

Pas importimit vendosni `Authorization: Bearer <api_token>` bashke me `X-Client-Id` dhe
`X-Client-Secret` si variabla te koleksionit, dhe zgjidhni serverin Sandbox derisa integrimi te jete
gati.

## Seksionet kryesore

- **On Boarding** - regjistrimi i kompanise, certifikata elektronike, njesite e biznesit, perdoruesit, pajisjet fiskale (TCR), llogarite bankare
- **Invoice** - krijimi i faturave Cash, NonCash, E-Invoice, Order, Summary. Listimi, detajet, anullimi, printimi PDF
- **Arka Fiskale** - hapja dhe mbyllja e arkes per shitje me para ne dore, hyrjet dhe daljet e parave, balanca
- **Klienti** - kerkimi i kompanive ne regjistrin fiskal sipas NIPT, si dhe lista dhe menaxhimi i klienteve tuaj
- **Produkte** - katalogu i produkteve dhe kategorite e tyre
- **Llogarite bankare** - llogarite qe shfaqen ne faturat pa para ne dore dhe elektronike
- **Monedhat** - monedhat e kompanise dhe kursi i kembimit i dites
- **Fatura shoqeruese (WTN)** - leshimi dhe listimi i fletave shoqeruese te mallit
- **Faturat e blerjes** - terheqja e faturave te blerjes nga fiskalizimi
- **Reports** - permbledhja e shitjeve, TVSH, ecuria ditore, produktet dhe klientet kryesore, anullimet, arka
- **Dashboard** - permbledhja e dites per ekranin kryesor

## Rrjedha e integrimit (ne rastet kur behet onboarding e klienteve me api)

1. **Regjistro kompaninë** (`POST /register`) - merr token + branch ID
2. **Ngarko certifikaten** (`POST /on-boarding/certificate`)
3. **Konfiguro njesine e biznesit** (`POST /on-boarding/branch/{id}`) - vendos businessUnitCode
4. **Krijo pajisje fiskale** (`POST /on-boarding/fiscal-device`) - merr kodin TCR
5. **Konfiguro perdoruesin** (`POST /on-boarding/user/{id}`) - vendos operatorCode + fiscalTcrCode
6. **Fillo leshimin e faturave** - perdor endpoint-et e Invoice

## Formati i pergjigjes

Nje pergjigje e suksesshme ka gjithmone kete forme:
```json
{"status": true, "data": { ... }}
```

Nje gabim ka kete:
```json
{"status": false, "message": "Pershkrimi i gabimit", "errors": ["Mesazhi per perdoruesin"]}
```

Fusha eshte `status`, jo `success`. Fusha `errors` mungon kur gabimi nuk ka asgje per te shtuar
pertej `message`.

### Perjashtimi: gabimet e validimit

Kur kerkesa nuk kalon validimin, pergjigja kthehet me statusin **422** dhe perdor `success` ne vend
te `status`, sepse gjenerohet nga nje shtrese tjeter:
```json
{"success": false, "message": "Te dhena te pavlefshme", "errors": {"lines.0.quantity": ["..."]}}
```

Ketu `errors` eshte objekt, jo varg: celesi eshte fusha qe deshtoi, me shenimin e plote drejt
fushave te brendshme, p.sh. `lines.0.quantity` ose `client.id.type`.

### Disa gabime kthehen me statusin HTTP 200

Nje pjese e endpoint-eve i kthejne refuzimet e tyre me statusin **200** dhe me `status: false` ne
trup. Ndodh te `POST /register` (llogaria pa te drejte onboarding-u, NIPT i regjistruar tashme),
te te gjitha endpoint-et e arkes fiskale (perdorues pa pajisje fiskale, fonde te pamjaftueshme),
te `POST /on-boarding/*` dhe te listat e produkteve. Prandaj mos e lexoni `data` vetem sepse
statusi eshte 200: kontrolloni gjithmone `status` me pare. Ne specifikim keto endpoint-e e
tregojne kete duke pranuar te dyja format ne pergjigjen 200.

`GET /client/search` nuk eshte me nje prej tyre: kthen **404** kur NIPT-i nuk gjendet ne
regjistrin fiskal dhe **503** kur regjistri nuk arrihet, qe te dallohet nje biznes qe nuk
ekziston nga nje kontroll qe nuk u krye dot.

### Statusi 401 ka dy kuptime

Nje token i pavlefshem ose i skaduar kthen `{"message": "Unauthenticated."}`.

Endpoint-et qe varen nga nje modul (faturat, arka, fatura shoqeruese, faturat e blerjes) kthejne
gjithashtu **401** kur moduli nuk perfshihet ne abonimin tuaj, por me zarfin standard te gabimit
dhe me nje shpjegim ne `errors`. Dalloni midis tyre nga trupi: nje kerkese me token te sakte qe
merr 401 do te thote abonim, jo autentifikim, dhe rigjenerimi i token-it nuk e zgjidh.

## Limitet (Rate limiting)

API ka limit kerkesash per te mbrojtur sherbimin dhe per te garantuar performance per te gjithe perdoruesit. Kur arrihet limiti, server-i kthen statusin **HTTP 429 Too Many Requests** se bashku me header-in `Retry-After` (sekonda) qe tregon kohen e nevojshme per te ritestuar.

Limitet e tabeles me poshte jane vlerat e konfiguruara. Disa prej tyre mund te jene ende ne faze
vezhgimi, ku kalimi i tyre regjistrohet por kerkesa nuk refuzohet. Mos u mbeshtetni ne kete: ndertoni
integrimin qe t'i respektoje limitet dhe te trajtoje statusin 429 qe tani.

Limitet jane **per perdorues** (te lidhura me API token-in tuaj), me perjashtim te limitit te pergjithshem qe eshte per IP.

| Kategoria | Endpoint-et | Limit |
|-----------|-------------|-------|
| **I pergjithshem (per IP)** | te gjitha kerkesat e nivelit te API-t | 120/minute |
| **Default (per perdorues)** | te gjitha endpoint-et e mbrojtura me identifikim | 240/minute |
| **Fatura fiskale** | `POST /invoice/cash`, `/invoice/noncash`, `/invoice/e-invoice`, `/invoice/order`, `/invoice/summary`, `/invoice/cancel/*`, `/invoice/wtn` | 30/minute, 600/ore |
| **Bulk** | `POST /invoice/bulk-noncash` | 3/minute, 30/ore |
| **Printim PDF** | `GET /invoice/print/{id}`, `/invoice/print-eic/{eic}`, `/invoice/wtn/print/{id}` | 30/minute |
| **Kerkim klientesh** | `GET /client/search` | 90/minute |
| **Onboarding** | `POST /register`, `POST /on-boarding/*` | 30/minute, 600/ore (per perdorues) |
| **Raporte** | `GET /reports/*`, `GET /dashboard/summary` | 30/minute |
| **Veprime te ndjeshme** | `POST /account/delete` | 5/ore per perdorues, 20/ore per IP |
| **Wolt Partner API, lexim** | `GET /api/partner/v1/wolt/*` | 180/minute |
| **Wolt Partner API, shkrim** | `POST /api/partner/v1/wolt/orders/*` | 60/minute |

Kur perdorimi juaj eshte i larte ne menyre te qendrueshme dhe limitet bllokojne integrimin, na kontaktoni.

### Nje kerkese ne te njejten kohe per endpoint

Krahas limiteve me siper, shumica e endpoint-eve lejojne vetem **nje kerkese ne proces njekohesisht
per perdorues**. Nje kerkese e dyte drejt te njejtit endpoint, ndersa e para nuk ka mbaruar ende,
refuzohet. Ky eshte kufiri qe hasin me shpesh integrimet qe punojne me shume fije njekohesisht:
zgjidhja nuk eshte te riprovoni menjehere, por t'i radhisni kerkesat per perdorues.

Ky refuzim vjen me zarfin standard te gabimit. Ne varesi te endpoint-it statusi eshte **429** ose
**200 me `status: false`**, prandaj kontrolloni gjithmone `status`.

### Pergjigja kur arrihet limiti

```json
{
    "message": "Too Many Attempts."
}
```

Header-at e kthyer:
- `Retry-After: 30` - numri i sekondave para se te ritestoni
- `X-RateLimit-Limit` - limiti maksimal per dritaren aktuale
- `X-RateLimit-Remaining` - kerkesat e mbetura ne kete dritare

## Udhezime per implementimin

Disa praktika qe e bejne integrimin me te qendrueshem dhe shmangin gabimet me te shpeshta:

### Identifikoni aplikacionin tuaj

Aplikacioni juaj identifikohet me nje cift kredencialesh qe i dergoni ne cdo kerkese, krahas token-it te perdoruesit:

```
X-Client-Id: ft_id_a1b2c3d4e5f6g7h8i9j0k1l2
X-Client-Secret: ft_sk_...
```

- **Client id** fillon me `ft_id_` dhe eshte publik. **Client secret** fillon me `ft_sk_` dhe eshte i fshehte: trajtojeni si fjalekalim.
- Te dyja i perkasin aplikacionit tuaj, jo klientit. Nuk gjenerohen per cdo biznes dhe nuk duhet te perfundojne ne kod qe shperndahet dhe mund te lexohet nga te tjeret.
- Kredencialet e para i merrni nga fature.al kur regjistrohet integrimi juaj. Me pas i shihni dhe i rigjeneroni vete nga **Konfigurime > Zhvillues** ne llogarine tuaj ne fature.al, ku shihni edhe sa perdorues dhe sa biznese kane punuar permes aplikacionit tuaj ne 24 oret e fundit.

Secret-i shfaqet **vetem nje here**, ne momentin qe gjenerohet, dhe nuk mund te lexohet me pas. Ruajeni menjehere.

Nese e humbisni ose dyshoni se eshte kompromentuar, rigjenerojeni nga i njejti ekran. **Rigjenerimi
eshte i menjehershem dhe pa periudhe mbivendosjeje:** secret-i i vjeter nderpritet ne kerkesen e
pare qe vjen pas tij. Kjo eshte e qellimshme, sepse nje secret rigjenerohet pikerisht kur ka rrjedhur,
dhe mbajtja e tij gjalle do te mbante gjalle edhe ate qe e mori.

Prandaj rendi i veprimeve ka rendesi: pergatisni instalimet tuaja qe te marrin secret-in e ri, dhe
rigjenerojeni vetem kur jeni gati ta shperndani menjehere. Client id nuk ndryshon, keshtu qe ju
mbetet te zevendesoni nje vlere te vetme.

#### Vazhdoni te dergoni edhe header-in User-Agent

Krahas kredencialeve, ne cdo kerkese dergoni header-in `User-Agent` ne formatin `<emri i aplikacionit>/<versioni i build-it>`:

```
User-Agent: EmriIAplikacionit/2.4.1
```

- **Emri i aplikacionit** duhet te jete gjithmone i njejti: ne cdo kerkese, per cdo klient tuajin dhe ne cdo version te aplikacionit. Ky emer eshte identifikuesi i integrimit tuaj, prandaj mos e ndryshoni dhe mos e varioni sipas kompanise, pajisjes apo mjedisit (Live/Sandbox). Perdorni shkronja, numra ose shenjat `_ . + -`, filloni me nje shkronje dhe mos vendosni hapesira.
- **Versioni i build-it** ndryshon me cdo publikim te aplikacionit tuaj, p.sh. `2.4.1` ose `2026.07.13`. Pa hapesira dhe pa `/`.

Kredencialet tregojne cili aplikacion po flet, ndersa User-Agent-i tregon cili version i tij eshte ne perdorim. Kjo e fundit nuk nxirret dot nga kredencialet dhe na ndihmon te reagojme me shpejt kur raportoni nje problem. Nese kredencialet mungojne, User-Agent-i mbetet e vetmja menyre per te identifikuar integrimin tuaj.

#### Kalimi ne detyrim

Nese header-at **nuk dergohen fare**, kerkesa vazhdon normalisht dhe integrimi identifikohet vetem nga User-Agent-i. Kjo eshte periudha e kalimit. Cdo ofrues software-i njoftohet paraprakisht per daten nga e cila kredencialet behen te detyrueshme per aplikacionin e tij, dhe vetem pas asaj date kerkesat pa kredenciale refuzohen me statusin **401 Unauthorized**.

Nese header-at **dergohen por nuk verifikohen**, kerkesa refuzohet menjehere me **401 Unauthorized**, pa pritur asnje date. Nje client id qe nuk njihet ose nje secret i gabuar do te thote qe aplikacioni juaj nuk eshte i identifikuar, prandaj preferojme te ju njoftojme ne cast se sa ta pranojme heshtazi. Nese ende nuk i keni kredencialet, mos i dergoni header-at bosh ose me vlera provizore.

Pergjigja e refuzimit ndjek te njejtin format si gabimet e tjera:

```json
{
    "status": false,
    "message": "Kjo kerkese duhet te dergoje header-at X-Client-Id dhe X-Client-Secret."
}
```

| Shkaku | Refuzohet | Mesazhi |
|--------|-----------|---------|
| Header-at mungojne | vetem pas dates se detyrimit | Kjo kerkese duhet te dergoje header-at X-Client-Id dhe X-Client-Secret. |
| Client id nuk njihet | gjithmone | Client ID nuk njihet. |
| Client secret i gabuar ose mungon | gjithmone | Client secret nuk eshte i sakte. |
| Aplikacioni eshte pezulluar | gjithmone | Ky aplikacion integrimi eshte pezulluar. |

Filloni ta dergoni ciftin qe tani. Kerkesat me kredenciale te sakta punojne njesoj si me pare, prandaj nuk ka pse te pritet data e detyrimit.

### Testoni ne Sandbox para Live

Filloni implementimin gjithmone kundrejt `https://demo.fature.al`. Faturat e leshuara atje nuk kane vlere fiskale dhe mund te perdoren lirisht per testim. Kaloni ne `https://fature.al` vetem pasi rrjedha juaj te jete e plote dhe e provuar.

### Kontrolloni gjithmone fushen `status`

Mos u mbeshtetni vetem ne kodin HTTP: disa refuzime kthehen me statusin 200 (shih "Formati i
pergjigjes"). Para se te lexoni `data`, verifikoni qe `status` eshte `true`. Ne rast gabimi,
mesazhet vijne ne vargun `errors` dhe duhet te shfaqen ose te logohen. Vetem pergjigjet 422 te
validimit e quajne kete fushe `success`, ndaj nje klient i qendrueshem i lexon te dyja.

### Riprovimi dhe respektimi i limiteve

Kur merrni statusin **429**, prisni aq sa tregon header-i `Retry-After` para se te riprovoni dhe mos riprovoni ne menyre te vazhdueshme brenda nje cikli. Per gabimet e perkohshme te rrjetit (timeout, 5xx), perdorni riprovim me vonese progresive, p.sh. 1s, 2s, 4s.

### Fusha internalId

`internalId` eshte identifikuesi i fatures ne sistemin tuaj, te cilin ia kaloni fature.al-it ne cdo kerkese leshimi. Eshte fushe **e detyrueshme** (string) per te gjitha endpoint-et qe leshojne fatura: `POST /invoice/cash`, `/invoice/noncash`, `/invoice/e-invoice`, `/invoice/order`, `/invoice/summary` dhe `/invoice/bulk-noncash`.

- **Vlera:** cdo identifikues unik nga sistemi juaj, p.sh. numri juaj i fatures ose nje UUID. Shembull: `CASH-001`.
- **Uniciteti:** duhet te jete unik brenda kompanise suaj. Mbrojtja kundrejt dublikatave vepron per vitin kalendarik aktual.
- **Roli:** sherben si celes idempotence (shih me poshte) dhe ju lejon ta gjeni me vone faturen permes `POST /invoice/details/{internalId}`.

Nese mungon, kerkesa refuzohet me statusin **422**. fature.al nuk e kthen `internalId` ne pergjigjen e leshimit, prandaj ruani vete lidhjen mes `internalId` tuaj dhe vlerave qe kthehen (`id`, `number`, `iic`).

### Te dhenat e klientit

Objekti `client` percakton bleresin e fatures dhe ka tre rrjedha te ndryshme:

| Rasti | Cfare dergoni | Rezultati |
|-------|---------------|-----------|
| **Klient i rastit** | `client` mungon, ose `client: null` | Fatura leshohet per klientin e rastit te kompanise. Vlen per `POST /invoice/cash` dhe `/invoice/noncash` |
| **Klient i ruajtur ne fature.al** | vetem `client.internal_id` | Klienti merret nga fature.al ashtu si eshte. Fushat e tjera nuk lexohen |
| **Klient nga sistemi juaj** | `client.name` dhe te dhenat e tjera | Klienti kerkohet me emer dhe identifikues. Nese nuk ekziston, krijohet |

Ne rrjedhen e trete:

- **`client.name` behet i detyrueshem** sapo dergoni ndonje te dhene tjeter te klientit. Nje adrese ose nje NIPT pa emer refuzohet, sepse fatura fiskale do te mbetej pa bleresin qe pretendoni.
- **`client.address` dhe `client.city` duhen** per cdo klient te emeruar: adresa dhe qyteti i bleresit shkojne ne kerkesen drejt sistemit fiskal, i cili nuk pranon fatura ku ato mungojne. Nuk duhet te dergohen ne cdo fature: nese klienti ekziston tashme ne fature.al me adrese e qytet, kerkesa mund te mos i permende dhe vlerat e ruajtura ruhen. Nese dergoni vetem `client.address`, qyteti i ruajtur nuk fshihet.
- **`client.country`** eshte opsional. Pa te merret `ALB`. Per klientet jashte Shqiperise dergoni kodin ISO 3166-1 alpha-3, p.sh. `RKS` ose `ITA`.
- **`client.id`** identifikon bleresin: `{"type": "NUIS", "id": "L62221018T"}` per bizneset shqiptare, `VAT` ose `TAX` per bizneset e huaja, `ID`, `PASS` ose `SOC` per personat. NIPT-i nuk verifikohet ne regjistrin fiskal, keshtu qe edhe njeri i panjohur per fature.al pranohet dhe ruhet si klient i re.

Nese mungon nje e dhene e nevojshme, kerkesa refuzohet me statusin **400** dhe fusha `errors` thote sakte cfare duhet plotesuar, p.sh. `Klientit "Kompani Prove SHPK" i mungon qyteti.`. Fatura dhe klienti nuk ruhen ne kete rast, prandaj mund te riprovoni me te njejtin `internalId` pasi plotesoni te dhenat.

### Shmangni dyfishimin e faturave (idempotenca)

`internalId` (shih fushen me siper) eshte njekohesisht celesi i idempotences. E perdorim per te mos krijuar fatura dublikate.

Nje timeout ose nderprerje e rrjetit gjate leshimit nuk do te thote domosdoshmerisht qe fatura deshtoi. Ajo mund te jete ruajtur ose fiskalizuar tashme ne server. Prandaj, kur riprovoni, dergoni **te njejtin `internalId`** dhe asnjehere mos gjeneroni nje te ri per riprovim. Gjenerimi i nje `internalId` te ri eshte pikerisht ajo qe krijon dublikate.

Kur merr nje `internalId` qe ekziston tashme per kete vit, server-i nuk krijon fature te dyte. Kthen faturen ekzistuese dhe, nese ajo ishte ruajtur por jo e fiskalizuar, perpiqet ta perfundoje fiskalizimin para se ta ktheje.

Nese riprovoni shume shpejt, ndersa kerkesa e pare eshte ende duke u procesuar (brenda rreth 5 minutash), mund te merrni statusin **409**. Ne kete rast prisni pak dhe riprovoni, ose verifikoni gjendjen e fatures permes `POST /invoice/details/{internalId}`.

### Trajtoni fiskalizimin offline

Kur sherbimi i Administrates Tatimore eshte i paarritshem, fatura ruhet dhe fiskalizohet automatikisht me vone. Ne kete rast fatura ekziston dhe eshte e vlefshme, por mund te mos kete ende numrin fiskal (NIVF). Mos e trajtoni si gabim dhe mos e leshoni perseri.

### Ruajeni token-in te sigurt

Token-i jep akses te plote ne llogarine tuaj. Ruajeni ne server, jo ne kodin e shfletuesit apo ne aplikacione publike. Mos e vendosni ne kontrollin e versioneve dhe rigjenerojeni menjehere nese dyshoni se eshte kompromentuar.

### Ndiqni formatet e fushave nga specifikimi

Per formatet e sakta te datave, numrave dhe fushave te detyrueshme per cdo endpoint, mbeshtetuni ne skemat e OpenAPI te `/docs/api.json`. Dergoni vetem fushat e dokumentuara dhe ruani tipat e tyre.

## Servers

- `https://fature.al/api/v1` - Live
- `https://demo.fature.al/api/v1` - Sandbox

## Endpoints

### GET /account

**Summary:** Te dhenat e llogarise

Kthen te dhenat e perdoruesit te autentifikuar: emri, email, kodi fiskal dhe kompania.

**Tags:** Llogaria

**Responses:**

- `200`
- `401`

---

### GET /bank-accounts

**Summary:** Lista e llogarive bankare

Merr listen e llogarive bankare aktive te kompanise me faqosje dhe filtrim me tekst.

**Tags:** Llogaritë bankare

**Parameters:**

| Name | In | Required | Description |
|------|----|----------|-------------|
| `limit` | query | no | Numri i llogarive per faqe (max 100). |
| `offset` | query | no | Nga cila llogari te fillohet. |
| `query` | query | no | Kerkim ne emer te bankes, IBAN, SWIFT, mbajtes ose shenime. |

**Responses:**

- `200`
- `401`
- `429` - Kufiri i kerkesave u arrit. Kufiri per endpoint kthen zarfin standard te gabimit; kufiri i pergjithshem kthen vetem `message` bashke me header-in `Retry-After`.
- `500` - Gabim i papritur ne server.

---

### GET /cash-register/actions

**Summary:** Lista e veprimeve me arken

Merrni listen e veprimeve me arken fiskale (hyrje, dalje, hapje/mbyllje dite) me filtrim dhe faqosje.

**Tags:** Arka Fiskale

**Parameters:**

| Name | In | Required | Description |
|------|----|----------|-------------|
| `limit` | query | no | Numri i veprimeve per faqe. |
| `offset` | query | no | Nga cili veprim te fillohet. |
| `type` | query | no | Filtro sipas tipit: MONEY_IN, MONEY_OUT, OPEN_DAY, CLOSE_DAY. Disa tipe ndahen me presje. |
| `fromDate` | query | no | Data e fillimit (YYYY-MM-DD). |
| `toDate` | query | no | Data e perfundimit (YYYY-MM-DD). |

**Responses:**

- `200`
- `401`
- `500` - Gabim i papritur ne server.

---

### GET /cash-register/balance

**Summary:** Balanca e arkes fiskale

Merrni balancen aktuale ne ALL te arkes fiskale (TCR) te perdoruesit. Nese [toDate] nuk jepet, kthehet balanca e fundit.

**Tags:** Arka Fiskale

**Parameters:**

| Name | In | Required | Description |
|------|----|----------|-------------|
| `toDate` | query | no | Data deri te cila llogaritet balanca. Pa te kthehet balanca e fundit. |

**Responses:**

- `200` - Kur perdoruesi nuk ka pajisje fiskale, pergjigja kthehet me HTTP 200 dhe `status: false`.
- `401`
- `422` - Te dhenat nuk kaluan validimin. Kjo pergjigje perdor fushen `success`, jo `status`.
- `500` - Gabim i papritur ne server.

---

### POST /cash-register/close-balance

**Summary:** Mbyll balancen e arkes

Mbyllni balancen e arkes fiskale ne fund te dites. Nese arka nuk eshte e hapur, hapet automatikisht me balance 0.

**Tags:** Arka Fiskale

**Responses:**

- `200` - Kur perdoruesi nuk ka pajisje fiskale ose mbyllja deshton, pergjigja kthehet me HTTP 200 dhe `status: false`.
- `401`

---

### POST /cash-register/deposit

**Summary:** Hyrje ne arke (Deposit)

Bej nje hyrje parash ne arken fiskale (MONEY_IN). Kerkon qe perdoruesi te kete pajisje fiskale (TCR) te lidhur.

**Tags:** Arka Fiskale

**Request body content types:** application/json

**Responses:**

- `200` - Kur perdoruesi nuk ka pajisje fiskale ose arka nuk ka fonde te mjaftueshme, pergjigja kthehet me HTTP 200 dhe `status: false`.
- `401`
- `422` - Te dhenat nuk kaluan validimin. Kjo pergjigje perdor fushen `success`, jo `status`.

---

### POST /cash-register/open-balance

**Summary:** Hap balancen e arkes

Hapni balancen e arkes fiskale per te filluar shitjet me para ne dore. Perdoruesi duhet te kete pajisje fiskale (TCR) te lidhur.

**Tags:** Arka Fiskale

**Request body content types:** application/json

**Responses:**

- `200` - Kur perdoruesi nuk ka pajisje fiskale, kur balanca eshte negative, ose kur ruajtja deshton, pergjigja kthehet me HTTP 200 dhe `status: false`.
- `401`

---

### POST /cash-register/withdraw

**Summary:** Dalje nga arka (Withdraw)

Bej nje dalje parash nga arka fiskale (MONEY_OUT). Kerkon qe perdoruesi te kete pajisje fiskale (TCR) te lidhur.

**Tags:** Arka Fiskale

**Request body content types:** application/json

**Responses:**

- `200` - Kur perdoruesi nuk ka pajisje fiskale ose arka nuk ka fonde te mjaftueshme, pergjigja kthehet me HTTP 200 dhe `status: false`.
- `401`
- `422` - Te dhenat nuk kaluan validimin. Kjo pergjigje perdor fushen `success`, jo `status`.

---

### GET /client/search

**Summary:** Kerko klient sipas NIPT

Kerkoni nje kompani ne regjistrin fiskal duke perdorur NIPT/NUIS. Kthen te dhenat e kompanise nese gjendet.

**Tags:** Klienti

**Parameters:**

| Name | In | Required | Description |
|------|----|----------|-------------|
| `nuis` | query | yes | NIPT/NUIS i kompanise per te kerkuar. |

**Responses:**

- `200`
- `401`
- `404` - NIPT-i nuk gjendet ne regjistrin fiskal.
- `503` - Regjistri fiskal nuk u arrit, keshtu qe NIPT-i mbeti i pakontrolluar. Provoni perseri.

---

### GET /clients

**Summary:** Lista e klienteve

Merr listen e klienteve te kompanise me faqosje dhe filtrim me tekst.

**Tags:** Klienti

**Parameters:**

| Name | In | Required | Description |
|------|----|----------|-------------|
| `limit` | query | no | Numri i klienteve per faqe (max 100). |
| `offset` | query | no | Nga cili klient te fillohet. |
| `query` | query | no | Kerkim ne emer, mbiemer, NIPT, dokument, email ose telefon. |

**Responses:**

- `200`
- `401`
- `429` - Kufiri i kerkesave u arrit. Kufiri per endpoint kthen zarfin standard te gabimit; kufiri i pergjithshem kthen vetem `message` bashke me header-in `Retry-After`.
- `500` - Gabim i papritur ne server.

---

### POST /clients

**Summary:** Krijo klient

**Tags:** Klienti

**Request body content types:** application/json

**Responses:**

- `200`
- `401`
- `422` - Te dhenat nuk kaluan validimin. Kjo pergjigje perdor fushen `success`, jo `status`.
- `403` - Abonimi ka mbaruar, ose veprimi nuk lejohet per kete llogari.
- `409` - Ekziston tashme nje regjistrim me te njejtat te dhena.
- `429` - Kufiri i kerkesave u arrit. Kufiri per endpoint kthen zarfin standard te gabimit; kufiri i pergjithshem kthen vetem `message` bashke me header-in `Retry-After`.
- `500` - Gabim i papritur ne server.

---

### PUT /clients/{id}

**Summary:** Perditeso klient

Perditeson nje klient ekzistues. Trupi i kerkeses ka te njejtin format si POST /clients.

**Tags:** Klienti

**Parameters:**

| Name | In | Required | Description |
|------|----|----------|-------------|
| `id` | path | yes | ID e klientit. |

**Request body content types:** application/json

**Responses:**

- `200`
- `401`
- `422` - Te dhenat nuk kaluan validimin. Kjo pergjigje perdor fushen `success`, jo `status`.
- `403` - Abonimi ka mbaruar, ose veprimi nuk lejohet per kete llogari.
- `404` - Klienti nuk u gjet, ose nuk i perket kompanise suaj.
- `409` - Ekziston tashme nje klient me te njejtat te dhena.
- `429` - Kufiri i kerkesave u arrit. Kufiri per endpoint kthen zarfin standard te gabimit; kufiri i pergjithshem kthen vetem `message` bashke me header-in `Retry-After`.
- `500` - Gabim i papritur ne server.

---

### GET /clients/{id}/details

**Summary:** Detajet e klientit sipas ID

**Tags:** Klienti

**Parameters:**

| Name | In | Required | Description |
|------|----|----------|-------------|
| `id` | path | yes | ID e klientit. |

**Responses:**

- `200`
- `401`
- `404` - Klienti nuk u gjet, ose nuk i perket kompanise suaj.
- `500` - Gabim i papritur ne server.

---

### GET /currencies

**Summary:** Lista e monedhave

Kthen monedhat e konfiguruara për kompaninë,
me ALL gjithmonë në fillim.

**Tags:** Monedhat

**Responses:**

- `200`
- `401`

---

### GET /dashboard/summary

**Summary:** Permbledhja e dites

Nje pamje e shpejte e dites se sotme per ekranin kryesor: turni i hapur nese ka nje te tille,
shitjet e sotme dhe ato te dje per krahasim, gjendja e arkes dhe faturat e fundit. Pergjigja
ruhet ne cache per pak sekonda, prandaj nuk eshte burim per rakordim.

**Tags:** Dashboard

**Responses:**

- `200`
- `401`
- `429` - Kufiri i kerkesave u arrit: 30 kerkesa ne minute.

---

### GET /exchange-rates

**Summary:** Kursi i këmbimit

Kthen kursin e shitjes së ditës për çdo monedhë, sipas burimit të
zgjedhur. Të dhënat vijnë nga `https://api.kursi.al/api/rates` dhe
ruhen ne cache per 1h në server; klienti mund të mbajë snapshot-in e fundit
lokalisht për përdorim offline.

Burimet e mbështetura (vlera `source` në kërkesë):
  - `BOA`      → Banka e Shqipërisë (kursi zyrtar)
  - `BKT`      → Banka Kombëtare Tregtare
  - `Iliria98` → Këmbim Valutor "Iliria '98"
  - `ADON`     → Këmbim Valutor "Adon"

Burim i pa percaktuar kthehet automatikisht në `BOA`. Fusha `source` në
përgjigje është gjithmonë vlera e normalizuar.

**Tags:** Monedhat

**Parameters:**

| Name | In | Required | Description |
|------|----|----------|-------------|
| `source` | query | no | Burimi i kursit: BOA, BKT, Iliria98 ose ADON. |

**Responses:**

- `200`
- `401`

---

### GET /invoice

**Summary:** Lista e faturave

Merrni listen e faturave me filtrim dhe faqosje.

**Tags:** Invoice

**Parameters:**

| Name | In | Required | Description |
|------|----|----------|-------------|
| `limit` | query | no | Numri i faturave per faqe. |
| `offset` | query | no | Nga cila fature te fillohet. |
| `type` | query | no | Filtro sipas tipit: `CASH`, `NONCASH` ose `EINVOICE`. Disa tipe ndahen me presje. Cdo vlere jashte ketyre te treve injorohet pa gabim, dhe nese asnje nuk mbetet e vlefshme, filtri nuk zbatohet fare. |
| `fromDate` | query | no | Data e fillimit (YYYY-MM-DD). |
| `toDate` | query | no | Data e perfundimit (YYYY-MM-DD). |
| `query` | query | no | Kerko sipas numrit te fatures, emrit te bleresit ose NIPT-it. |

**Responses:**

- `200`
- `401`
- `422` - Formati i datave nuk eshte YYYY-MM-DD.
- `429` - Kufiri i kerkesave u arrit. Kufiri per endpoint kthen zarfin standard te gabimit; kufiri i pergjithshem kthen vetem `message` bashke me header-in `Retry-After`.
- `500` - Gabim i papritur ne server.

---

### POST /invoice/bulk-noncash

**Summary:** Krijo fatura pa para ne dore ne bllok (Bulk NonCash)

**Tags:** Invoice

**Request body content types:** application/json

**Responses:**

- `200` - Kthen nje objekt me nje hyrje per cdo `internalId`. Nje fature qe deshton mban zarfin e gabimit brenda hyrjes se vet, dhe statusi i pergjigjes mbetet 200.
- `401`

---

### POST /invoice/cancel-by-internal-id/{internalId}

**Summary:** Anulo fature sipas Internal ID

Anulon faturen duke perdorur ID-ne tuaj interne qe keni derguar kur keni krijuar faturen.

Pa body anulohet e gjithe fatura. Me `lines` anulohet vetem nje pjese e saj, me te njejtat rregulla
si tek anulimi sipas ID: vetem fatura Cash, produkt me te njejtin `product_code` dhe `product_name`,
dhe sasi qe vetem ulet ose mbetet e njejte.

**Tags:** Invoice

**Parameters:**

| Name | In | Required | Description |
|------|----|----------|-------------|
| `internalId` | path | yes | ID juaj interne, e derguar kur u krijua fatura. |

**Request body content types:** application/json

**Responses:**

- `200`
- `401`
- `422` - Fatura nuk mund te anulohet ne gjendjen e saj aktuale.
- `404` - Fatura nuk u gjet, ose nuk i perket kompanise suaj.
- `500` - Gabim i papritur ne server. Perfshin rastin kur anulimi nuk u regjistrua ne fiskalizim.

---

### POST /invoice/cancel/{invoiceId}

**Summary:** Anulo fature sipas ID

Anulon faturen dhe krijon regjistrim fiskal anulimi ne sistemin e tatimeve.

Pa body anulohet e gjithe fatura, si me pare.

Me `lines` anulohet vetem nje pjese e fatures, e mundur vetem per faturat Cash. Cdo rresht i derguar
duhet te ekzistoje ne faturen origjinale me te njejtin `product_code` dhe `product_name`, dhe sasia mund
vetem te ulet ose te mbetet e njejte. Produktet qe nuk i dergoni mbeten te shitura. Kur i njejti produkt
eshte faturuar ne dy rreshta me cmime te ndryshme, shtoni `price` per te zgjedhur rreshtin.

Fatura origjinale mbetet e hapur per anulime te metejshme derisa anulimet e pjesshme ta mbulojne te
gjithen, dhe vetem atehere shenohet si e anuluar.

**Tags:** Invoice

**Parameters:**

| Name | In | Required | Description |
|------|----|----------|-------------|
| `invoiceId` | path | yes | ID e fatures ne fature.al. |

**Request body content types:** application/json

**Responses:**

- `200`
- `401`
- `422` - Fatura nuk mund te anulohet ne gjendjen e saj aktuale.
- `404` - Fatura nuk u gjet, ose nuk i perket kompanise suaj.
- `500` - Gabim i papritur ne server. Perfshin rastin kur anulimi nuk u regjistrua ne fiskalizim.

---

### POST /invoice/cash

**Summary:** Krijo fature me para ne dore (Cash)

Objekti `client` nuk eshte i detyrueshem: pa te fatura leshohet per klientin e rastit. Sapo dergoni
ndonje te dhene te klientit, behen te nevojshme `client.name`, `client.address` dhe `client.city`,
sepse adresa dhe qyteti i bleresit shkojne ne sistemin fiskal. Adresen dhe qytetin mund t'i kete
edhe klienti i ruajtur me pare ne fature.al, keshtu qe nuk ka nevoje t'i dergoni ne cdo fature.
Kur mungon nje e dhene e nevojshme, kerkesa refuzohet me statusin 400 dhe fusha `errors` thote
sakte cfare duhet plotesuar.

**Tags:** Invoice

**Request body content types:** application/json

**Responses:**

- `200`
- `401`
- `422` - Te dhenat nuk kaluan validimin. Kjo pergjigje perdor fushen `success`, jo `status`. `internalId` qe mungon kthehet me zarfin standard te gabimit.
- `400` - Te dhena te paplota ose te pavlefshme. `errors` thote sakte cfare duhet plotesuar.
- `403` - Abonimi ka mbaruar, ose veprimi nuk lejohet per kete llogari.
- `409` - Nje fature me kete `internalId` po procesohet ose ekziston tashme per kete vit.
- `429` - Kufiri i kerkesave u arrit. Kufiri per endpoint kthen zarfin standard te gabimit; kufiri i pergjithshem kthen vetem `message` bashke me header-in `Retry-After`.
- `500` - Gabim i papritur ne server.
- `503` - Sherbimi i fiskalizimit eshte i paarritshem. Fatura ruhet dhe fiskalizohet automatikisht me vone.

---

### POST /invoice/details/{internalId}

**Summary:** Detajet e fatures sipas Internal ID

Merr detajet e nje fature duke perdorur ID-ne tuaj interne.

**Tags:** Invoice

**Parameters:**

| Name | In | Required | Description |
|------|----|----------|-------------|
| `internalId` | path | yes | ID juaj interne, e derguar kur u krijua fatura. |

**Responses:**

- `200`
- `401`
- `404` - Nuk u gjet asnje fature me kete `internalId`.
- `422` - `internalId` eshte bosh.
- `500` - Gabim i papritur ne server.

---

### POST /invoice/e-invoice

**Summary:** Krijo fature elektronike (E-Invoice)

Fatura dergohet automatikisht ne sistemin qendror te e-faturave. Klienti identifikohet me NIPT.

Bleresi shkon i plote ne sistemin e e-faturave, prandaj adresa dhe qyteti duhen ose ne kerkese
(`client.address`, `client.city`) ose te ruajtura me pare tek klienti ne fature.al. Kur mungon
nje e dhene e nevojshme, kerkesa refuzohet me statusin 400 dhe fusha `errors` thote sakte cfare
duhet plotesuar.

`process` dhe `doc_type` jane te detyrueshme: i pari shkon si ProfileID ne dokumentin UBL,
i dyti si lloji i dokumentit. Per nje fature te zakonshme shitjeje dergoni `process=P1` dhe
`doc_type=380`; nje note krediti kerkon `process=P9` dhe `doc_type=381`.

**Tags:** Invoice

**Request body content types:** application/json

**Responses:**

- `200`
- `401`
- `422` - Te dhenat nuk kaluan validimin. Kjo pergjigje perdor fushen `success`, jo `status`. `internalId` qe mungon kthehet me zarfin standard te gabimit.
- `400` - Te dhena te paplota ose te pavlefshme. `errors` thote sakte cfare duhet plotesuar.
- `403` - Abonimi ka mbaruar, ose veprimi nuk lejohet per kete llogari.
- `409` - Nje fature me kete `internalId` po procesohet ose ekziston tashme per kete vit.
- `429` - Kufiri i kerkesave u arrit. Kufiri per endpoint kthen zarfin standard te gabimit; kufiri i pergjithshem kthen vetem `message` bashke me header-in `Retry-After`.
- `500` - Gabim i papritur ne server.
- `503` - Sherbimi i fiskalizimit eshte i paarritshem. Fatura ruhet dhe fiskalizohet automatikisht me vone.

---

### POST /invoice/noncash

**Summary:** Krijo fature pa para ne dore (NonCash)

Perdoret per transaksione me transferte bankare, cek, etj.

Klienti identifikohet me `client.name` dhe, kur e dergoni, me `client.id`. Adresa dhe qyteti i
bleresit shkojne ne sistemin fiskal, prandaj duhen ose ne kerkese (`client.address`,
`client.city`) ose te ruajtura me pare tek klienti ne fature.al. Kur mungon nje e dhene e
nevojshme, kerkesa refuzohet me statusin 400 dhe fusha `errors` thote sakte cfare duhet plotesuar.

**Tags:** Invoice

**Request body content types:** application/json

**Responses:**

- `200`
- `401`
- `422` - Te dhenat nuk kaluan validimin. Kjo pergjigje perdor fushen `success`, jo `status`. `internalId` qe mungon kthehet me zarfin standard te gabimit.
- `400` - Te dhena te paplota ose te pavlefshme. `errors` thote sakte cfare duhet plotesuar.
- `403` - Abonimi ka mbaruar, ose veprimi nuk lejohet per kete llogari.
- `409` - Nje fature me kete `internalId` po procesohet ose ekziston tashme per kete vit.
- `429` - Kufiri i kerkesave u arrit. Kufiri per endpoint kthen zarfin standard te gabimit; kufiri i pergjithshem kthen vetem `message` bashke me header-in `Retry-After`.
- `500` - Gabim i papritur ne server.
- `503` - Sherbimi i fiskalizimit eshte i paarritshem. Fatura ruhet dhe fiskalizohet automatikisht me vone.

---

### POST /invoice/order

**Summary:** Krijo fature porosi (Order)

Fatura regjistrohet por pagesa nuk perfundon - perdoret me summary invoice.
payment_method vendoset automatikisht ne ORDER.

**Tags:** Invoice

**Request body content types:** application/json

**Responses:**

- `200`
- `401`
- `422` - Te dhenat nuk kaluan validimin. Kjo pergjigje perdor fushen `success`, jo `status`. `internalId` qe mungon kthehet me zarfin standard te gabimit.
- `400` - Te dhena te paplota ose te pavlefshme. `errors` thote sakte cfare duhet plotesuar.
- `403` - Abonimi ka mbaruar, ose veprimi nuk lejohet per kete llogari.
- `409` - Nje fature me kete `internalId` po procesohet ose ekziston tashme per kete vit.
- `429` - Kufiri i kerkesave u arrit. Kufiri per endpoint kthen zarfin standard te gabimit; kufiri i pergjithshem kthen vetem `message` bashke me header-in `Retry-After`.
- `500` - Gabim i papritur ne server.
- `503` - Sherbimi i fiskalizimit eshte i paarritshem. Fatura ruhet dhe fiskalizohet automatikisht me vone.

---

### GET /invoice/print-eic/{eic}

**Summary:** Shkarko PDF te fatures sipas EIC

Kthen skedarin PDF te fatures duke perdorur kodin EIC (UUID).

**Tags:** Invoice

**Parameters:**

| Name | In | Required | Description |
|------|----|----------|-------------|
| `eic` | path | yes | Kodi EIC i fatures elektronike. |

**Responses:**

- `200` - Kur EIC nuk gjendet, kthehet teksti `Document not found.` me statusin 200 dhe Content-Type text/html, jo PDF. Kontrolloni Content-Type para se ta ruani si PDF.
- `401`

---

### GET /invoice/print/{invoiceId}

**Summary:** Shkarko PDF te fatures sipas ID

Kthen dokumentin e fatures. Pa parametra kthehet formati i paracaktuar per tipin e fatures: kupon termik
per faturat Cash (sipas gjeresise 58/80mm te konfiguruar te perdoruesi), dokument A4 per faturat NonCash
dhe Estimate, dhe PDF-ja zyrtare e marre nga sistemi qeveritar per faturat elektronike.

Me parametrin `format` merrni te njejtat versione printimi qe ofron edhe paneli i fature.al:

| `format` | Tipi i fatures | Rezultati | Content-Type |
|----------|----------------|-----------|--------------|
| `a4` | Cash | Dokument A4 i fatures | application/pdf |
| `thermal` | NonCash | Kupon termik | application/pdf |
| `v2` | NonCash, Estimate | Dokument A4, versioni i gjere | application/pdf |
| `receipt` | Estimate | Kupon termik | application/pdf |
| `local` | EInvoice | Dokument A4 i gjeneruar nga fature.al, pa e kerkuar PDF-ne zyrtare | application/pdf |
| `local-thermal` | EInvoice | Kupon termik i gjeneruar nga fature.al | application/pdf |
| `html` | Cash | Kuponi termik si HTML, per ta derguar vete ne printer | text/html |
| `json` | te gjitha | Te dhenat e dokumentit ne JSON, per ta formatuar vete faturen | application/json |

Parametri `lang` (`en`, `it`, `de`) e perkthen dokumentin A4 te faturave NonCash, Estimate dhe EInvoice,
dhe kombinohet me `format`. Pa te, dokumenti kthehet shqip. Kuponat termike dhe faturat Cash mbeten
gjithmone shqip, sepse jane dokumente fiskale.

Per faturat Cash, parametri `copy_only=1` kthen kopjen e kuponit ne HTML ne vend te origjinalit.

Nje `format` qe nuk vlen per tipin e fatures nuk kthen gabim: kthehet formati i paracaktuar i atij tipi.

**Tags:** Invoice

**Parameters:**

| Name | In | Required | Description |
|------|----|----------|-------------|
| `invoiceId` | path | yes | ID e fatures ne fature.al. |
| `copy_only` | query | no | Vetem per faturat Cash: kthen kopjen e kuponit ne vend te origjinalit. |
| `format` | query | no | Versioni i dokumentit sipas tabeles me siper: a4, thermal, v2, receipt, local, local-thermal, html, json. |
| `lang` | query | no | Gjuha e dokumentit A4: en, it, de. Pa te dokumenti kthehet shqip. |

**Responses:**

- `200` - Tipi i permbajtjes varet nga `format`: PDF si parazgjedhje, `text/html` me `format=html`, dhe dokumenti i fatures ne JSON me `format=json`, gati per ta formatuar vete.
- `401`
- `404` - Fatura nuk u gjet, ose nuk i perket kompanise suaj.

---

### POST /invoice/summary

**Summary:** Krijo fature permbledhese (Summary)

Perfundon pagesen e nje ose me shume faturave Order. Duhet te specifikoni IIC-te e faturave order ne fushen order_invoices.

Rrjeshtat merren nga faturat Order dhe nuk dergohen ne kerkese. Pergjigja i liston ato fatura
ne `settledOrderInvoices`.

**Tags:** Invoice

**Request body content types:** application/json

**Responses:**

- `200`
- `401`
- `422` - Te dhenat nuk kaluan validimin. Kjo pergjigje perdor fushen `success`, jo `status`. `internalId` qe mungon kthehet me zarfin standard te gabimit.
- `400` - Te dhena te paplota ose te pavlefshme. `errors` thote sakte cfare duhet plotesuar.
- `403` - Abonimi ka mbaruar, ose veprimi nuk lejohet per kete llogari.
- `409` - Nje fature me kete `internalId` po procesohet ose ekziston tashme per kete vit.
- `429` - Kufiri i kerkesave u arrit. Kufiri per endpoint kthen zarfin standard te gabimit; kufiri i pergjithshem kthen vetem `message` bashke me header-in `Retry-After`.
- `500` - Gabim i papritur ne server.
- `503` - Sherbimi i fiskalizimit eshte i paarritshem. Fatura ruhet dhe fiskalizohet automatikisht me vone.

---

### GET /invoice/wtn

**Summary:** Lista e faturave shoqeruese (WTN)

Merr listen e faturave shoqeruese me faqosje dhe filtrim sipas datave.

**Tags:** Warehouse transfer Note (Fatura Shoqeruese)

**Parameters:**

| Name | In | Required | Description |
|------|----|----------|-------------|
| `limit` | query | no | Numri i faturave per faqe. |
| `offset` | query | no | Nga cila fature te fillohet. |
| `fromDate` | query | no | Data e fillimit (YYYY-MM-DD). |
| `toDate` | query | no | Data e perfundimit (YYYY-MM-DD). |

**Responses:**

- `500`
- `422`
- `200`
- `429`
- `401`

---

### POST /invoice/wtn

**Summary:** Krijo fature shoqeruese (WTN)

**Tags:** Warehouse transfer Note (Fatura Shoqeruese)

**Request body content types:** application/json

**Responses:**

- `500`
- `503`
- `200`
- `403`
- `429`
- `401`
- `422`

---

### GET /invoice/wtn/print/{invoiceId}

**Summary:** Te dhenat e fatures shoqeruese ne format printimi (JSON)

Kthen nje strukture JSON me te gjitha te dhenat per nje "print view".

**Tags:** Warehouse transfer Note (Fatura Shoqeruese)

**Parameters:**

| Name | In | Required | Description |
|------|----|----------|-------------|
| `invoiceId` | path | yes | ID e fatures shoqeruese ne fature.al. |

**Responses:**

- `200`
- `404`
- `401`

---

### GET /invoice/wtn/{id}/details

**Summary:** Detajet e fatures shoqeruese sipas ID

**Tags:** Warehouse transfer Note (Fatura Shoqeruese)

**Parameters:**

| Name | In | Required | Description |
|------|----|----------|-------------|
| `id` | path | yes | ID e fatures shoqeruese ne fature.al. |

**Responses:**

- `500`
- `200`
- `404`
- `401`

---

### GET /invoice/{id}/details

**Summary:** Detajet e fatures sipas ID

Merrni detajet e plota te nje fature sipas ID-se ne sistem.

**Tags:** Invoice

**Parameters:**

| Name | In | Required | Description |
|------|----|----------|-------------|
| `id` | path | yes | ID e fatures ne fature.al. |

**Responses:**

- `200`
- `401`
- `429` - Kufiri i kerkesave u arrit. Kufiri per endpoint kthen zarfin standard te gabimit; kufiri i pergjithshem kthen vetem `message` bashke me header-in `Retry-After`.
- `500` - Gabim i papritur ne server.

---

### POST /on-boarding/bank-account

**Summary:** Krijo llogari bankare

Krijoni nje llogari bankare per kompaninë. Llogaria bankare shfaqet ne faturat elektronike dhe jo-cash si informacion pagese per klientin.

**Tags:** On Boarding

**Request body content types:** application/json

**Responses:**

- `200` - Kur ruajtja e llogarise deshton, pergjigja kthehet me HTTP 200 dhe `status: false`.
- `401`
- `422` - Te dhenat nuk kaluan validimin. Kjo pergjigje perdor fushen `success`, jo `status`.

---

### POST /on-boarding/branch

**Summary:** Krijo njesi biznesi (Branch)

Krijoni nje njesi biznesi te re per kompanine tuaj. Lloji jepet ne fushen `type` si enum:
`main` per seline qendrore dhe `secondary` per nje njesi dytesore. Kompania mund te kete
vetem nje seli qendrore, prandaj `main` refuzohet nese ajo ekziston (kodi 409).

Numri i njesive varet nga abonimi. Kur limiti eshte arritur kerkesa refuzohet me kodin 403.

Kodi i biznesit (`businessUnitCode`) mund te dergohet me vone me `POST /on-boarding/branch/{id}`,
por eshte i domosdoshem per leshimin e faturave nga kjo njesi.

**Tags:** On Boarding

**Request body content types:** application/json

**Responses:**

- `200` - Kur krijimi deshton per nje arsye tjeter, pergjigja kthehet me HTTP 200 dhe `status: false`.
- `401`
- `422` - Te dhenat nuk kaluan validimin. Kjo pergjigje perdor fushen `success`, jo `status`.
- `403` - Abonimi nuk lejon me njesi biznesi.
- `409` - Kompania ka tashme nje seli qendrore.

---

### POST /on-boarding/branch/{id}

**Summary:** Perditeso njesine e biznesit (Branch)

Perditesoni emrin, adresen, administratorin dhe kodin e biznesit per nje njesi biznesi ekzistuese. Kodi i biznesit (businessUnitCode) eshte i domosdshem per leshimin e faturave.

**Tags:** On Boarding

**Parameters:**

| Name | In | Required | Description |
|------|----|----------|-------------|
| `id` | path | yes | ID e njesise se biznesit. |

**Request body content types:** application/json

**Responses:**

- `200` - Kur njesia nuk gjendet ose ruajtja deshton, pergjigja kthehet me HTTP 200 dhe `status: false`.
- `401`

---

### POST /on-boarding/certificate

**Summary:** Ngarko certifikaten elektronike

Ngarkoni certifikaten elektronike (.p12 ose .pfx) per kompaninë. Fjalekalimi duhet te jete i sakte dhe NIPT-i ne certifikate duhet te perputhet me NIPT-in e kompanise.

**Sandbox (DEMO):** ne instancen DEMO ky endpoint kthen `success` per cdo certifikate dhe cdo fjalekalim. `expiresAt` qe kthehet eshte +1 vit nga sot.

**Tags:** On Boarding

**Request body content types:** multipart/form-data

**Responses:**

- `200` - Kur fjalekalimi eshte i gabuar ose NIPT-i i certifikates nuk perputhet me kompanine, pergjigja kthehet me HTTP 200 dhe `status: false`.
- `401`
- `422` - Te dhenat nuk kaluan validimin. Kjo pergjigje perdor fushen `success`, jo `status`.

---

### POST /on-boarding/fiscal-device

**Summary:** Krijo pajisje fiskale (TCR)

Regjistron nje pajisje fiskale te re ne sistemin e tatimeve dhe kthen kodin TCR. Ky kod perdoret per faturat me para ne dore dhe duhet te lidhet me perdoruesin perkates.

**Tags:** On Boarding

**Request body content types:** application/json

**Responses:**

- `200` - Kur regjistrimi i pajisjes ne fiskalizim deshton, pergjigja kthehet me HTTP 200 dhe `status: false`.
- `401`
- `422` - Te dhenat nuk kaluan validimin. Kjo pergjigje perdor fushen `success`, jo `status`.

---

### POST /on-boarding/user

**Summary:** Krijo perdorues te ri

Krijoni nje perdorues te ri per kompaninë me kodin e operatorit dhe pajisjen fiskale. Kthen token API per kete perdorues.

**Tags:** On Boarding

**Request body content types:** application/json

**Responses:**

- `200` - Kur email-i eshte ne perdorim, kur njesia nuk gjendet, ose kur ruajtja deshton, pergjigja kthehet me HTTP 200 dhe `status: false`.
- `401`

---

### POST /on-boarding/user/{id}

**Summary:** Perditeso perdoruesin

Perditesoni emrin, kodin e operatorit, pajisjen fiskale dhe njesine e biznesit per nje perdorues ekzistues. Kodi i operatorit eshte i domosdshem per leshimin e faturave.

**Tags:** On Boarding

**Parameters:**

| Name | In | Required | Description |
|------|----|----------|-------------|
| `id` | path | yes | ID e perdoruesit. |

**Request body content types:** application/json

**Responses:**

- `200` - Kur perdoruesi nuk gjendet ose ruajtja deshton, pergjigja kthehet me HTTP 200 dhe `status: false`.
- `401`

---

### GET /ping

**Summary:** Ping

Kontrollo nese API eshte aktiv. Kthen timestamp dhe IP.

**Tags:** Ping

**Responses:**

- `200`
- `401`

---

### GET /product/categories

**Summary:** Lista e kategorive

Merrni listen e kategorive te produkteve per kompaninë tuaj. Kthehen te gjitha ne nje pergjigje
te vetme, pa faqosje.

**Tags:** Produkte

**Responses:**

- `200` - Kur limiti i kerkesave arrihet ose ndodh nje gabim i papritur, pergjigja kthehet me HTTP 200 dhe `status: false`.
- `401`

---

### GET /products

**Summary:** Lista e produkteve

Katalogu i produkteve te kompanise. Perjashtohen produktet e fshira dhe ato qe nuk jane per
shitje, prandaj kjo eshte lista qe mund ta perdorni per te ndertuar nje arke ose nje katalog.

## Filtrat

Te gjithe parametrat jane opsionale dhe kombinohen me njeri-tjetrin. Nje kerkese pa asnje
parameter kthen te gjithe katalogun, njesoj si me pare.

| Parametri | Cfare ben |
|-----------|-----------|
| `query` | Kerkim ne emer, kod ose pershkrim. Perputhja eshte e pjesshme dhe nuk dallon shkronjat e medha |
| `id_category` | Vetem produktet e nje kategorie, sipas `id` nga `GET /product/categories` |
| `service` | `true` kthen vetem sherbimet, `false` vetem artikujt e inventarit |
| `limit` dhe `offset` | Faqosja. Pa `limit` kthehet i gjithe rezultati dhe `offset` nuk zbatohet |

## Faqosja

`data` mbetet lista e produkteve, ashtu si ka qene gjithmone. Numeruesit vijne ne `pagination`
krahas saj dhe jo brenda saj, qe nje program i shkruar para filtrave te vazhdoje te lexoje
`data` si me pare, pa asnje ndryshim.

`pagination.total` eshte numri i produkteve qe i pergjigjen filtrave, ndersa
`pagination.records` eshte sa u kthyen ne kete faqe. Kur nuk dergoni `limit`, te dyja jane te
njejta, `pagination.limit` kthehet `null` dhe `offset` nuk merret parasysh: faqosja ka kuptim
vetem kur i dergoni te dy bashke.

Per te marre faqen e dyte me nga 50 produkte: `?limit=50&offset=50`. Vazhdoni derisa
`offset + records` te arrije `total`.

```
GET /products?query=kafe&id_category=3&limit=50
```

**Tags:** Produkte

**Parameters:**

| Name | In | Required | Description |
|------|----|----------|-------------|
| `query` | query | no | Kerkim ne emer, kod ose pershkrim te produktit. |
| `id_category` | query | no | Vetem produktet e kesaj kategorie, nga GET /product/categories. |
| `limit` | query | no | Sa produkte te kthehen, deri ne 500. Pa te kthehet i gjithe katalogu. |
| `offset` | query | no | Nga cili produkt te fillohet. Zbatohet vetem bashke me `limit`. |
| `service` | query | no | true kthen vetem sherbimet, false vetem artikujt e inventarit. Pa te kthehen te dyja. |

**Responses:**

- `200` - Kur limiti i kerkesave arrihet ose ndodh nje gabim i papritur, pergjigja kthehet me HTTP 200 dhe `status: false`.
- `401`

---

### POST /products

**Summary:** Krijo produkt

Krijon nje produkt te ri per kompaninë tuaj. Kodi gjenerohet automatikisht nese nuk jepet. Njesia matese derivohet nga unit_code.

**Tags:** Produkte

**Request body content types:** application/json

**Responses:**

- `200`
- `401`
- `422` - Te dhenat nuk kaluan validimin. Kjo pergjigje perdor fushen `success`, jo `status`.
- `403` - Abonimi ka mbaruar, ose veprimi nuk lejohet per kete llogari.
- `409` - Ekziston tashme nje regjistrim me te njejtat te dhena.
- `429` - Kufiri i kerkesave u arrit. Kufiri per endpoint kthen zarfin standard te gabimit; kufiri i pergjithshem kthen vetem `message` bashke me header-in `Retry-After`.
- `500` - Gabim i papritur ne server.

---

### PUT /products/{id}

**Summary:** Perditeso produkt

Perditeson nje produkt ekzistues. Trupi i kerkeses ka te njejtin format si POST /products.

**Tags:** Produkte

**Parameters:**

| Name | In | Required | Description |
|------|----|----------|-------------|
| `id` | path | yes | ID e produktit. |

**Request body content types:** application/json

**Responses:**

- `200`
- `401`
- `422` - Te dhenat nuk kaluan validimin. Kjo pergjigje perdor fushen `success`, jo `status`.
- `403` - Abonimi ka mbaruar, ose veprimi nuk lejohet per kete llogari.
- `404` - Produkti nuk u gjet, ose nuk i perket kompanise suaj.
- `409` - Ekziston tashme nje produkt me kete kod.
- `429` - Kufiri i kerkesave u arrit. Kufiri per endpoint kthen zarfin standard te gabimit; kufiri i pergjithshem kthen vetem `message` bashke me header-in `Retry-After`.
- `500` - Gabim i papritur ne server.

---

### GET /products/{id}/details

**Summary:** Detajet e produktit sipas ID

Merrni detajet e nje produkti sipas id-se per kompaninë tuaj.

**Tags:** Produkte

**Parameters:**

| Name | In | Required | Description |
|------|----|----------|-------------|
| `id` | path | yes | ID e produktit. |

**Responses:**

- `200`
- `401`
- `404` - Produkti nuk u gjet, ose nuk i perket kompanise suaj.
- `500` - Gabim i papritur ne server.

---

### GET /purchase-invoices

**Summary:** Lista e faturave te blerjes

Merrni faturat e blerjes nga fiskalizimi. Per cdo fature terhiqen te dhenat
e plota (artikujt, shitesi, bleresi, menyrat e pageses).

**Tags:** Purchase Invoice

**Parameters:**

| Name | In | Required | Description |
|------|----|----------|-------------|
| `page` | query | no | Faqja e listes nga fiskalizimi. Perserit me page+1 derisa items te kthehet bosh. |
| `fromDate` | query | no | Data e fillimit (YYYY-MM-DD). Pa te merret sot. |
| `toDate` | query | no | Data e perfundimit (YYYY-MM-DD). Pa te merret sot. |
| `fic` | query | no | Filtro sipas FIC per nje fature te vetme. |

**Responses:**

- `200`
- `401`
- `422` - Formati i datave nuk eshte YYYY-MM-DD.
- `500` - Gabim i papritur ne server.
- `502` - Fiskalizimi u pergjigj me nje gabim.
- `503` - Sherbimi i fiskalizimit eshte i paarritshem.

---

### GET /register

**Summary:** Ping (Register)

Kontrollo nese API eshte aktiv per regjistrimin e kompanive.

**Tags:** On Boarding

**Responses:**

- `200` - Kur llogaria juaj nuk eshte e autorizuar per onboarding, pergjigja kthehet me HTTP 200 dhe `status: false`.
- `401`

---

### POST /register

**Summary:** Regjistro kompani te re

Regjistron nje kompani te re ne fature.al. Kerkon token special te autorizuar nga fature.al. Kthen token API per perdoruesin e krijuar dhe ID e njesise se biznesit.

**Sandbox (DEMO):** ne instancen DEMO, dergimi i NIPT-it `L62221018T` aktivizon rrjedhen sandbox: nuk krijohet kompani e re, por krijohet nje perdorues + njesi biznesi nen kompanine ekzistuese sandbox dhe ju kthehet nje `api_token` real qe e perdorni per hapat e tjere te onboarding-ut. Email-i shtohet me sufiks `+sandbox-XXXXXXXX` qe te lejojme thirrje te perseritura me te njejtin email. Ne `PRODUCTION` ky NIPT trajtohet normalisht.

**Tags:** On Boarding

**Request body content types:** application/json

**Responses:**

- `200` - Kur llogaria nuk eshte e autorizuar per onboarding, kur NIPT-i eshte i regjistruar tashme, ose kur nuk gjendet ne regjistrin fiskal, pergjigja kthehet me HTTP 200 dhe `status: false`.
- `401`
- `422` - Te dhenat nuk kaluan validimin. Kjo pergjigje perdor fushen `success`, jo `status`.

---

### GET /reports/by-operator

**Summary:** Shitjet sipas operatorit

Sa fatura leshoi dhe sa vlere beri secili operator ne periudhe.

**Tags:** Reports

**Parameters:**

| Name | In | Required | Description |
|------|----|----------|-------------|
| `from` | query | yes | Data e fillimit, e perfshire. |
| `to` | query | yes | Data e perfundimit, e perfshire. |

**Responses:**

- `200`
- `401`
- `422` - Datat mungojne ose nuk jane ne formatin YYYY-MM-DD.
- `429` - Kufiri i kerkesave u arrit: 30 raporte ne minute.

---

### GET /reports/by-tcr

**Summary:** Shitjet sipas pajisjes fiskale

Sa fatura leshoi dhe sa vlere beri secila pajisje fiskale (TCR) ne periudhe.

**Tags:** Reports

**Parameters:**

| Name | In | Required | Description |
|------|----|----------|-------------|
| `from` | query | yes | Data e fillimit, e perfshire. |
| `to` | query | yes | Data e perfundimit, e perfshire. |

**Responses:**

- `200`
- `401`
- `422` - Datat mungojne ose nuk jane ne formatin YYYY-MM-DD.
- `429` - Kufiri i kerkesave u arrit: 30 raporte ne minute.

---

### GET /reports/cash-register

**Summary:** Gjendja e arkes per nje dite

Hapja, mbyllja dhe mbyllja e pritur e arkes fiskale per nje dite, me shitjet sipas menyres se 
pageses dhe levizjet e parave. Pa `date` merret dita e sotme.

**Tags:** Reports

**Parameters:**

| Name | In | Required | Description |
|------|----|----------|-------------|
| `date` | query | no | Dita e raportit. Pa te merret sot. |

**Responses:**

- `200`
- `401`
- `422` - Datat mungojne ose nuk jane ne formatin YYYY-MM-DD.
- `429` - Kufiri i kerkesave u arrit: 30 raporte ne minute.
- `500` - Gabim i papritur ne server.

---

### GET /reports/cash-register/closing

**Summary:** Raporti i mbylljes se arkes

Raporti i fundit i dites: totalet e shitjeve, produktet e shitura dhe levizjet e parave per 
turnin qe u mbyll. Pa `date` merret dita e sotme.

**Tags:** Reports

**Parameters:**

| Name | In | Required | Description |
|------|----|----------|-------------|
| `date` | query | no | Dita e raportit. Pa te merret sot. |

**Responses:**

- `200`
- `401`
- `422` - Datat mungojne ose nuk jane ne formatin YYYY-MM-DD.
- `429` - Kufiri i kerkesave u arrit: 30 raporte ne minute.
- `500` - Gabim i papritur ne server.

---

### GET /reports/daily-trend

**Summary:** Ecuria ditore

Nje pike per cdo dite te periudhes, qofte si vlere bruto qofte si numer faturash, sipas 
`metric`.

**Tags:** Reports

**Parameters:**

| Name | In | Required | Description |
|------|----|----------|-------------|
| `from` | query | yes | Data e fillimit, e perfshire. |
| `to` | query | yes | Data e perfundimit, e perfshire. |
| `metric` | query | no | Cfare mat seria: vlera bruto apo numri i faturave. Pa te merret `gross`. |

**Responses:**

- `200`
- `401`
- `422` - Datat mungojne ose nuk jane ne formatin YYYY-MM-DD.
- `429` - Kufiri i kerkesave u arrit: 30 raporte ne minute.

---

### GET /reports/reversals

**Summary:** Faturat e anulluara

Faturat e anulluara ne periudhe, me faturen origjinale qe secila korrigjon.

**Tags:** Reports

**Parameters:**

| Name | In | Required | Description |
|------|----|----------|-------------|
| `from` | query | yes | Data e fillimit, e perfshire. |
| `to` | query | yes | Data e perfundimit, e perfshire. |
| `limit` | query | no | Sa rreshta te kthehen, deri ne 500. |

**Responses:**

- `200`
- `401`
- `422` - Datat mungojne ose nuk jane ne formatin YYYY-MM-DD.
- `429` - Kufiri i kerkesave u arrit: 30 raporte ne minute.

---

### GET /reports/sales-summary

**Summary:** Permbledhje e shitjeve

Totalet e shitjeve per nje periudhe, te ndara sipas menyres se pageses, tipit te fatures, 
shkalles se TVSH dhe dites. Perfshin edhe sa fatura u anulluan. Vlerat jane ne ALL.

**Tags:** Reports

**Parameters:**

| Name | In | Required | Description |
|------|----|----------|-------------|
| `from` | query | yes | Data e fillimit, e perfshire. |
| `to` | query | yes | Data e perfundimit, e perfshire. |

**Responses:**

- `200`
- `401`
- `422` - Datat mungojne ose nuk jane ne formatin YYYY-MM-DD.
- `429` - Kufiri i kerkesave u arrit: 30 raporte ne minute.

---

### GET /reports/top-clients

**Summary:** Klientet kryesore

Klientet e renditura sipas vleres se faturuar ne periudhe.

**Tags:** Reports

**Parameters:**

| Name | In | Required | Description |
|------|----|----------|-------------|
| `from` | query | yes | Data e fillimit, e perfshire. |
| `to` | query | yes | Data e perfundimit, e perfshire. |
| `limit` | query | no | Sa rreshta te kthehen, deri ne 500. |

**Responses:**

- `200`
- `401`
- `422` - Datat mungojne ose nuk jane ne formatin YYYY-MM-DD.
- `429` - Kufiri i kerkesave u arrit: 30 raporte ne minute.

---

### GET /reports/top-products

**Summary:** Produktet me te shitura

Produktet e renditura sipas te ardhurave ose sipas sasise se shitur.

**Tags:** Reports

**Parameters:**

| Name | In | Required | Description |
|------|----|----------|-------------|
| `from` | query | yes | Data e fillimit, e perfshire. |
| `to` | query | yes | Data e perfundimit, e perfshire. |
| `limit` | query | no | Sa produkte te kthehen, deri ne 200. |
| `sort` | query | no | Renditja: sipas te ardhurave ose sipas sasise. Pa te merret `revenue`. |

**Responses:**

- `200`
- `401`
- `422` - Datat mungojne ose nuk jane ne formatin YYYY-MM-DD.
- `429` - Kufiri i kerkesave u arrit: 30 raporte ne minute.

---

### GET /reports/vat

**Summary:** Raporti i TVSH

TVSH e mbledhur nga shitjet dhe ajo e paguar ne blerje, me diferencen qe rezulton. Rreshtat 
ndahen ne te tatueshem sipas shkalles dhe te perjashtuar sipas llojit te perjashtimit.

**Tags:** Reports

**Parameters:**

| Name | In | Required | Description |
|------|----|----------|-------------|
| `from` | query | yes | Data e fillimit, e perfshire. |
| `to` | query | yes | Data e perfundimit, e perfshire. |

**Responses:**

- `200`
- `401`
- `422` - Datat mungojne ose nuk jane ne formatin YYYY-MM-DD.
- `429` - Kufiri i kerkesave u arrit: 30 raporte ne minute.

---

### GET /reports/wtn

**Summary:** Raporti i faturave shoqeruese

Fletet shoqeruese te periudhes, te grupuara sipas gjendjes fiskale, me destinacionet e 
perdorura.

**Tags:** Reports

**Parameters:**

| Name | In | Required | Description |
|------|----|----------|-------------|
| `from` | query | yes | Data e fillimit, e perfshire. |
| `to` | query | yes | Data e perfundimit, e perfshire. |

**Responses:**

- `200`
- `401`
- `422` - Datat mungojne ose nuk jane ne formatin YYYY-MM-DD.
- `429` - Kufiri i kerkesave u arrit: 30 raporte ne minute.

---

## Full OpenAPI specification

For complete schemas, examples and request/response bodies, fetch the JSON spec:

```
https://demo.fature.al/docs/api.json
```
