# fature.al API Version 1.0.0. Base URL: `https://fature.al` ## API versions | Version | Status | Endpoints | | --- | --- | --- | | `v2` | previous | 4 | | `v1` | current | 60 | Write new integrations against `v1`. Every endpoint below states the version it belongs to, and any endpoint with a newer edition links to it. ## Si te fillosh ### Hyrje Ky eshte dokumentacioni i API-t te fature.al. Me te leshoni fatura te fiskalizuara nga sistemi juaj, pa u marre me certifikata, nenshkrim XML apo SOAP me sistemin qendror. ## Ne pak rreshta | | | | --- | --- | | Versioni per te ndertuar | `v1` | | Versione ne perdorim | `v1` dhe `v2` | | Prodhim | `https://fature.al` | | Sandbox | `https://demo.fature.al` | | Formati | JSON ne kerkese dhe ne pergjigje | | Identifikimi | Token i perdoruesit, plus cift kredencialesh per aplikacionin | Rruga e plote e nje endpoint-i e permban versionin, pra `https://fature.al/api/v1/invoice`. ## Cfare mbulon Faturat jane thelbi, por API-ja shkon pertej tyre: - **Faturat**, ne te kater llojet: cash, jo-cash, elektronike dhe flete shoqeruese. - **Klientet dhe produktet**, si te dhena qe ndahen mes sistemit tuaj dhe fature.al. - **Arka fiskale**, me hapjen, mbylljen dhe levizjet e parave. - **Raportet**, te llogaritura ne server dhe jo ne kodin tuaj. - **Faturat e blerjes**, te terhequra nga sistemi fiskal pa i kerkuar gje furnitorit. - **Regjistrimi**, per ofruesit qe hapin llogari per klientet e tyre. Nje pamje e plote e asaj qe mund te ndertohet eshte tek [Cfare mund te ndertoni](/api-reference/pages/use-cases.html). ## Zarfi i pergjigjes Cdo pergjigje ka te njejten forme. Sukses: ```json { "status": true, "data": { } } ``` Gabim: ```json { "status": false, "message": "...", "errors": [] } ``` Perjashtimi i vetem eshte deshtimi i validimit ne disa endpoint-e te `v1`, i cili perdor `success` ne vend te `status`. Prandaj lexoni gjithmone me pare kodin HTTP. ## Nga ku te filloni Nese nuk keni thirrur ende asgje, [Fillimi i shpejte](/api-reference/pages/quickstart.html) ju con nga token-i deri te fatura e pare. ### Fillimi i shpejte Ky udhezues ju con nga zeroja deri te nje fature e fiskalizuar. Zgjat pak minuta dhe nuk kerkon asgje te instaluar pervec `curl`. ## 1. Merrni token-in Token-i eshte i perdoruesit, jo i kompanise. Gjenerojeni nga fature.al te **Konfigurime > API Tokens**. Ai identifikon si perdoruesin ashtu edhe biznesin ne emer te te cilit leshohen faturat, prandaj cdo thirrje e mban: ```bash -H 'Authorization: Bearer TOKEN_I_JUAJ' ``` Nese jeni nje ofrues qe shet nje program per shume biznese, aplikacioni juaj merr edhe nje cift kredencialesh qe dergohen krahas token-it: ```bash -H 'X-Client-Id: ft_id_...' -H 'X-Client-Secret: ft_sk_...' ``` Cifti tregon **cili program** po therret, ndersa token-i tregon **kush** po e perdor. Te dyja duhen kur aplikacioni juaj kalon ne zbatim te detyrueshem. ## 2. Provoni lidhjen `GET /api/v1/ping` nuk prek asgje dhe kthen kohen e serverit. Eshte menyra me e shpejte per te vertetuar se token-i lexohet: ```bash curl 'https://fature.al/api/v1/ping' \ -H 'Authorization: Bearer TOKEN_I_JUAJ' ``` ```json { "status": true, "data": { "pong": 1788547330, "ip": ["81.2.3.4"] } } ``` Nese merrni `401`, token-i nuk po arrin. Kontrolloni qe header-i quhet `Authorization` dhe qe fjala `Bearer` eshte para tij. Pas kesaj, `GET /api/v1/account` ju kthen te dhenat e llogarise dhe te biznesit, pra konfirmon se po punoni mbi kompanine e duhur. ## 3. Leshoni faturen e pare Nje fature jo-cash eshte fillimi me i thjeshte, sepse nuk kerkon pajisje fiskale te zgjedhur nga ju: ```bash curl -X POST 'https://fature.al/api/v1/invoice/noncash' \ -H 'Authorization: Bearer TOKEN_I_JUAJ' \ -H 'Content-Type: application/json' \ -d '{ "internalId": "TEST-0001", "payment_method": "TRANSFER", "client": { "name": "Klient Provë", "address": "Rruga e Kavajes 12", "city": "Tirane" }, "lines": [ { "product_name": "Sherbim", "product_code": "SRV-01", "unit": "Cope", "unit_code": "C62", "quantity": 1, "price": 1000, "total": 1000, "vat": 20 } ] }' ``` Pergjigja mban gjithcka qe duhet ruajtur prane shitjes tuaj: ```json { "status": true, "data": { "invoice": { "id": 40312, "number": "1/2026", "iic": "8FE72E2ACD1C500A83F8C89B4E2E3E1D", "fic": "b3f1c0a2-4d5e-4f60-9a71-2c3d4e5f6071", "verifyURL": "https://efiskalizimi-app.tatime.gov.al/invoice-check/#/verify?...", "pdf": "https://fature.al/api/v1/invoice/print/40312" } } } ``` ## internalId eshte celesi juaj `internalId` eshte numri qe fatura ka ne sistemin tuaj, dhe fature.al e ruan ashtu sic e dergoni. Ai ben dy pune: - **Ndalon faturat e dyfishta.** I njejti `internalId` brenda te njejtit vit kthen `409` ne vend qe te leshoje nje fature te dyte. Prandaj nje riprovim pas nje lidhjeje qe u nderpre eshte i sigurt: ose leshohet nje fature, ose merrni `409`. - **Ju kursen ruajtjen e ID-se sone.** `POST /api/v1/invoice/details/{internalId}` dhe `POST /api/v1/invoice/cancel-by-internal-id/{internalId}` punojne me numrin tuaj, pra nuk keni pse te mbani `id` e fature.al ne bazen tuaj. ## Zarfi i pergjigjes Nje pergjigje e suksesshme ka gjithmone `status: true` dhe te dhenat brenda `data`. Nje gabim ka `status: false` bashke me `message` dhe `errors`. Perjashtimi i vetem eshte deshtimi i validimit, `422`, i cili perdor `success: false` ne vend te `status`. Nese kontrolloni vetem `status`, nje pergjigje `422` do t'ju duket sikur nuk ka statusin fare. Kontrolloni me pare kodin HTTP. ## Me tej - [Raste perdorimi](/api-reference/pages/use-cases.html) tregon rrjedhat e plota qe ndertohen me shpesh. - [Fatura elektronike](/api-reference/pages/e-invoice.html) mbulon e-faturat, notat e kreditit dhe ato te debitit. - [Faqezimi](/api-reference/pages/pagination.html) shpjegon si lexohen listat e gjata. ### Cfare mund te ndertoni Fiskalizimi eshte i detyrueshem per cdo shitje ne Shqiperi, dhe ndertimi i tij nga e para do te thote certifikata dixhitale, nenshkrim XML, SOAP me sistemin qendror, mbajtje e TCR-ve dhe nje plan per momentin kur sherbimi i tatimeve nuk pergjigjet. Kjo API e ben ate pune. Ju dergoni nje fature si JSON dhe merrni nje dokument te fiskalizuar, me IIC, NIVF, URL verifikimi dhe PDF. Sistemi juaj nuk e di qe ekziston SOAP. ## Kush ndertohet mbi te **Programe kontabiliteti dhe ERP.** Fatura leshohet aty ku eshte shitja, jo ne nje faqe te dyte qe operatori duhet ta hape. Klientet dhe produktet rrine te sinkronizuara ne te dy anet. **Dyqane online.** Porosia e paguar behet fature ne te njejtin cast, dhe bleresi merr PDF-in bashke me konfirmimin, pa nderhyrje njerezore. **Programe arke, bar dhe restorant.** Porosia hapet kur tavolina ulet dhe mbyllet me nje pagese te vetme, me faturat e ndermjetme te lidhura vete. **Aplikacione vertikale.** Nje program qe njeh mire nje zanat, inventarin e nje bari ose porosite e nje furre, merr faturimin ligjor pa u marre me te. **Ofrues qe shesin te njejtin program shume bizneseve.** Nje instalim, shume kompani, secila me identitetin e vet fiskal. ## Fiskalizim pa e ndertuar vete Ky eshte thelbi. Cfare merrni pa e shkruar: - **Te kater llojet e dokumentit.** Cash, jo-cash, e-fature dhe fature shoqeruese, secili me rregullat e veta. Shihni [Llojet e faturave](/api-reference/pages/invoice-types.html). - **Certifikatat.** Nenshkrimi dixhital, skadimi dhe rinovimi jane pune e jona. - **Pajisjet fiskale.** TCR-te, njesite e biznesit dhe kodet e operatoreve zgjidhen vete nga token-i qe dergoni. - **Numerimi.** Numri rendor per biznes, vit dhe TCR ruhet i sakte edhe kur dy kerkesa vijne ne te njejtin cast. - **Rikthimi pas nderprerjes.** Kur sistemi i tatimeve nuk pergjigjet, fatura ruhet dhe fiskalizohet me vone. Shitja nuk ndalon. - **Dokumenti per bleresin.** PDF dhe URL verifikimi qe hapet me QR, pa gjeneruar gje. Praktikisht kjo do te thote se nje ekip qe do te kalonte muaj te tere mbi fiskalizimin e nis javen e pare duke leshuar fatura te vertetuara. ## Te dhena qe nuk i keni ju Kjo pjese kalon me shpesh pa u vene re, dhe eshte aty ku API-ja jep me shume nga sa kerkohet prej saj. **Regjistri i NIPT-eve.** `GET /client/search` kerkon nje kompani ne regjistrin fiskal me NIPT dhe kthen emrin, adresen, qytetin dhe nje shenje `verified`. Formulari juaj i klientit te ri kerkon nje fushe te vetme dhe i mbush vete te tjerat, ndersa nje NIPT i gabuar kapet para se te dale ne fature. **Faturat e blerjes, nga tatimet.** `GET /purchase-invoices` sjell faturat qe ju kane leshuar juve, ashtu sic i ka regjistruar sistemi fiskal. Furnitoret nuk ju dergojne gje: dokumentet vijne me artikujt, shitesin, TVSH-ne dhe menyren e pageses. Kjo mundeson rakordim blerjesh dhe TVSH pa asnje hap manual. **Kursi i kembimit i dites.** `GET /exchange-rates` kthen kursin e shitjes per cdo monedhe nga Banka e Shqiperise, BKT, Iliria '98 ose Adon, sipas asaj qe zgjidhni. Pergjigja ruhet ne cache ne server dhe mban `fetchedAt`, prandaj klienti juaj mund ta mbaje snapshot-in e fundit dhe te punoje edhe pa internet. Nese keni ndertuar nje lexues kursesh diku ne kodin tuaj, kjo e zevendeson. ## Provizionim i klienteve tuaj, pa nderhyrje Nje ofrues programi nuk do qe cdo klient i ri te prese dike qe t'i hapi llogarine. Grupi i onboarding-ut e ben te gjithe rrugen nga API-ja: 1. `POST /register` krijon kompanine dhe ju kthen nje `api_token` pune. 2. `POST /on-boarding/branch` shton njesine e biznesit. 3. `POST /on-boarding/fiscal-device` regjistron TCR-ne. 4. `POST /on-boarding/certificate` ngarkon certifikaten elektronike. 5. `POST /on-boarding/user` dhe `/on-boarding/bank-account` mbyllin konfigurimin. Ne fund klienti juaj leshon fatura pa e hapur asnjehere fature.al. Ky grup eshte i mbyllur si parazgjedhje dhe hapet per partneret, prandaj kerkoni akses para se ta planifikoni. Ne instancen DEMO ka nje rrjedhe sandbox qe ju kthen nje token te vertete pa krijuar kompani, keshtu qe integrimin e provoni sa here te doni. ## Raportet llogariten ne server Nje liste faturash e lexuar faqe pas faqeje dhe e mbledhur ne kodin tuaj eshte e ngadalte dhe gabon lehte. Raportet e bejne mbledhjen ne bazen e te dhenave dhe kthejne shifren: | Raporti | Cfare jep | | --- | --- | | `reports/sales-summary` | Shitjet per nje periudhe | | `reports/vat` | TVSH e mbledhur, sipas normes | | `reports/daily-trend` | Ecuria dite pas dite, per grafik | | `reports/top-clients`, `reports/top-products` | Renditjet | | `reports/by-operator`, `reports/by-tcr` | Kush shiti dhe nga cila pajisje | | `reports/cash-register`, `reports/cash-register/closing` | Gjendja dhe mbyllja e arkes | | `reports/reversals` | Faturat e anuluara | Nje panel drejtuesi ndertohet mbi keto pa mbajtur asnje kopje te te dhenave. ## Arka si sistem me vete Grupi i arkes fiskale hap dhe mbyll balancen, regjistron hyrje dhe dalje parash, dhe jep raportin e mbylljes. Nje program arke merr keshtu turnin, rakordimin e fundit te dites dhe historikun e veprimeve pa i ndertuar vete. `GET /dashboard/summary` mbyll pamjen: turni i hapur, shitjet e sotme perballe atyre te djeshme, gjendja e arkes dhe faturat e fundit, ne nje thirrje te vetme. Eshte menduar per ekranin kryesor, jo per rakordim, sepse pergjigja ruhet ne cache per pak sekonda. ## Levizja e mallit Fleta shoqeruese mbulon mallin qe udheton pa u shitur ende: nga magazina ne dyqan, tek doganat, ne panair. Kerkohet nga ligji dhe shpesh harrohet ne integrime, prandaj `POST /invoice/wtn` ju kursen nje siperfaqe te tere. ## Kanale shitjeje te gatshme Nese biznesi shet ne Wolt, `/api/partner/v1/wolt` sjell porosite, i pranon, i refuzon dhe i fiskalizon. Kanali eshte i lidhur tashme, prandaj nuk ka nevoje ta ndertoni. ## Nga ku te filloni - [Fillimi i shpejte](/api-reference/pages/quickstart.html) ju con te fatura e pare. - [Llojet e faturave](/api-reference/pages/invoice-types.html) tregon cilin endpoint te thirrni dhe me cfare. - [Fatura elektronike](/api-reference/pages/e-invoice.html) mbulon e-faturat dhe korrigjimet e tyre. ### Identifikimi Te gjitha endpoint-et kerkojne identifikim. Nuk ka asnje endpoint publik. ## Token-i i perdoruesit Token-i eshte i perdoruesit, jo i kompanise, dhe gjenerohet nga fature.al te **Konfigurime > API Tokens**. Ai identifikon njeheresh perdoruesin dhe biznesin ne emer te te cilit leshohen faturat. ```bash Authorization: Bearer TOKEN_I_JUAJ ``` ## Kredencialet e aplikacionit Nje ofrues qe shet nje program per shume biznese merr edhe nje cift kredencialesh, te cilat dergohen krahas token-it: ```bash X-Client-Id: ft_id_... X-Client-Secret: ft_sk_... ``` Te dyja bashke pergjigjen dy pyetjeve te ndryshme: | Cfare dergoni | Cfare tregon | | --- | --- | | `Authorization` | **Kush** po e perdor programin | | `X-Client-Id` me `X-Client-Secret` | **Cili program** po therret | Kredencialet nuk e zevendesojne token-in dhe nuk hapin asnje te drejte me vete. ## Nje kerkese e plote ```bash curl 'https://fature.al/api/v1/account' \ -H 'Authorization: Bearer TOKEN_I_JUAJ' \ -H 'X-Client-Id: ft_id_...' \ -H 'X-Client-Secret: ft_sk_...' \ -H 'Accept: application/json' ``` ## Kur nuk kalon - **`401`**: token-i mungon, eshte i gabuar ose eshte revokuar. Kontrolloni qe header-i quhet `Authorization` dhe qe fjala `Bearer` eshte para tij. - **`403`**: token-i eshte i vlefshem, por llogaria nuk ka te drejten per kete veprim, ose abonimi ka mbaruar. Kredencialet e derguara gabim refuzohen gjithmone me `401`, edhe kur dergimi i tyre nuk eshte ende i detyrueshem per aplikacionin tuaj. ## Rotacioni Kur nje sekret rrjedh, rotacioni e shfuqizon ate menjehere, pa periudhe mbivendosjeje. Client id-ja mbetet e njejta, prandaj sherbimi juaj rifillon me nje vlere te vetme te ndryshuar. ### Versionet e API-t Ndertoni mbi **`v1`**. Ai mban te gjithe siperfaqen: faturat, e-faturat, arken fiskale, klientet, produktet, raportet, fletet shoqeruese dhe faturat e blerjes. `v2` nuk eshte pasardhesi i `v1`. Eshte nje format i ri qe deri tani mbulon vetem klientet, dhe ekziston krahas `v1`, jo mbi te. ## Cfare mban secili | Versioni | Endpoint-e | Cfare mbulon | | --- | --- | --- | | `v1` | 60 | E gjithe API-ja | | `v2` | 4 | Vetem klientet, ne formatin e ri | Numri i vogel i `v2` nuk tregon nje version qe sapo ka nisur te zevendesoje `v1`. Ai tregon qe `v2` eshte hapur per nje ceshtje te vetme, formen e te dhenave te klientit, dhe se asgje tjeter nuk eshte prekur. Nese sistemi juaj leshon fatura, ju duhet `v1`. Nuk ka rruge tjeter: `v2` nuk ka endpoint fature. ## Kur ia vlen te perdorni v2 `v2` i ndan te dhenat e klientit ne objekte me vete per kompanine, personin, adresen dhe kontaktin, ne vend te fushave te sheshta te `v1`. Nese sistemi juaj i mban keshtu tashme, `v2` ju kursen perkthimin ne te dyja drejtimet. Te dy versionet shkruajne mbi te njejtat te dhena. Nje klient i krijuar me `v1` lexohet me `v2` dhe anasjelltas, prandaj perdorimi i te dyve njeheresh eshte i lejueshem: `v2` per klientet dhe `v1` per gjithcka tjeter. ## Nje ndryshim qe duhet ditur Ne nje deshtim validimi, statusi `422`, te dy versionet kthejne fusha te ndryshme: ```json // v1 { "success": false, "message": "...", "errors": { "lines": ["..."] } } // v2 { "status": false, "message": "...", "errors": { "company.name": ["..."] } } ``` `v1` perdor `success` vetem ketu. Ne cdo pergjigje tjeter, te suksesshme ose te gabuar, te dy versionet perdorin `status`. Prandaj lexoni gjithmone me pare kodin HTTP dhe pastaj fushat e trupit. ## Partner API nuk eshte nje version i trete `/api/partner/v1` sherben integrimin me Wolt dhe ka nje publik te vetin: nje njesi e vetme, porosite e saj, pranimi, refuzimi dhe fiskalizimi i tyre. Nuk eshte nje version i `v1` dhe nuk e zevendeson ate. Nese nuk po integroni Wolt, ai grup nuk ju perket. ## Asgje nuk eshte ne dalje Asnje nga versionet nuk ka date perfundimi dhe asnje nuk eshte shpallur i vjeteruar. Nje integrim i shkruar sot mbi `v1` nuk ka afat qe duhet ndjekur. Versioni eshte pjese e rruges, pra kerkesa e thote vete cilin do. Nuk ka negocim me header dhe nuk ka version te nenkuptuar: nje thirrje pa `/v1` ose `/v2` ne rruge nuk shkon askund. ### Gabimet Gabimet kthehen me nje kod HTTP te zakonshem dhe nje trup JSON. ## Trupi i gabimit ```json { "status": false, "message": "Pershkrimi i gabimit", "errors": ["cfare shkoi keq"] } ``` Ne nje deshtim validimi fusha `errors` eshte objekt i ndare sipas fushes, jo varg: ```json { "success": false, "message": "Te dhenat nuk jane te vlefshme", "errors": { "lines": ["Fatura duhet te kete te pakten nje rresht"] } } ``` **Ky eshte perjashtimi i vetem nga zarfi standard**, dhe vlen per disa endpoint-e te `v1`. Prandaj lexoni gjithmone me pare kodin HTTP dhe pastaj fushat e trupit: nje program qe kontrollon vetem `status` e sheh nje `422` sikur te mos kete status fare. ## Kodet qe perdor kjo API | Kodi | Kuptimi | Cfare te beni | | --- | --- | --- | | `400` | Te dhena te paplota | `errors` thote sakte cfare mungon. Zakonisht adresa ose qyteti i bleresit | | `403` | Nuk lejohet | Abonimi ka mbaruar, ose llogaria nuk ka kete te drejte | | `404` | Nuk u gjet | Burimi nuk ekziston, ose nuk i perket kompanise suaj | | `409` | Ekziston tashme | Nje fature me kete `internalId` eshte leshuar ose po procesohet | | `422` | Validimi deshtoi | Rregulloni te dhenat. Mos riprovoni te njejten kerkese | | `429` | Kufiri u arrit | Prisni sa thote `Retry-After` | | `500` | Gabim i papritur | Provoni perseri me vone | | `503` | Fiskalizimi i paarritshem | **Fatura eshte ruajtur.** Mos e riprovoni | ## Dy kode qe nuk jane deshtime `409` dhe `503` duken si gabime, por nuk kerkojne riprovim, dhe riprovimi i tyre ben dem: - **`409`** do te thote qe fatura ekziston. Nje `internalId` i derguar dy here kthen `409` ne vend qe te leshoje nje fature te dyte, pra mbrojtja ka funksionuar. - **`503`** do te thote qe sistemi i tatimeve nuk u arrit, por fatura u ruajt dhe fiskalizohet vete me vone. Lexoni gjendjen me `POST /api/v1/invoice/details/{internalId}`, ku `fic` mbetet `null` derisa te kryhet. Ne te dyja rastet, nje cikel riprovimi vetem shton kerkesa qe nuk ndryshojne asgje. ### Kufiri i kerkesave Kufijte numerohen per token. Kalimi i tyre kthen `429 Too Many Requests`. ## Dy burime kufiri, dy pergjigje | Burimi | Trupi | Header-at | |---|---|---| | Middleware | `{"message": "Too Many Attempts."}` | `Retry-After`, `X-RateLimit-Limit`, `X-RateLimit-Remaining` | | Kod | `{"status": false, "message": "", "errors": ["..."]}` | asnje | Kur ka `Retry-After`, prisni ate numer sekondash. Kur nuk ka, prisni intervalin nga tabela perkatese me poshte. ## Kufiri i pergjithshem | Thirresi | Kufiri | Numerohet per | |---|---|---| | I identifikuar | 300 / min | token | | I paidentifikuar | 120 / min | IP | Vlen per cdo endpoint, para cdo kufiri tjeter. ## Anulimet | Endpoint | Kufiri | |---|---| | `POST /invoice/cancel/{id}`, `POST /invoice/cancel-by-internal-id/{internalId}` | 30 / min, 600 / ore | Numerohet per token. Anulimi mban numrin e vet rendor dhe eshte nje thirrje fiskale si leshimi, ndaj ka te njejtin buxhet me te. ## Intervali minimal Keto endpoint-e kane nje interval minimal mes dy thirrjeve te te njejtit token. | Endpoint | Intervali | Pergjigja | |---|---|---| | `GET /products` | 10 s | `200` me `status: false` | | `GET /product/categories` | 10 s | `200` me `status: false` | | `POST /products`, `PUT /products/{id}` | 10 s | `429` | | `GET /clients` | 10 s | `429` | | `POST /clients`, `PUT /clients/{id}` | 10 s | `429` | | `POST /api/v2/clients`, `PATCH /api/v2/clients/{id}` | 10 s | `429` | | `GET /bank-accounts` | 10 s | `429` | | `GET /invoice/wtn`, `POST /invoice/wtn` | 30 s | `429` | Dy rreshtat e pare kthejne `200`, jo `429`. Lexoni `status` dhe jo vetem kodin HTTP. `GET /api/v2/clients` sherbehet nga kodi i `v1` dhe ndan intervalin e `GET /clients`. `POST /invoice/wtn` e ka kufirin efektiv 2 / min. ## Endpoint-et qe kryhen nje nga nje Numri rendor eshte MAX+1 per biznes dhe vit, per cash edhe per TCR. Keto endpoint-e marrin nje bllokim para se te punojne. | Endpoint | Bllokimi per | Pritja | Ne skadim | |---|---|---|---| | `POST /invoice/cash`, `/invoice/order`, `/invoice/summary` | biznes + TCR | 1 s | `429` | | `POST /invoice/noncash`, `/invoice/e-invoice` | biznes | 1 s | `429` | | `GET /invoice` | token | 1 s | `429` | | `GET /invoice/{id}/details` | token | 1 s | `429` | | `POST /invoice/cancel/{id}`, `/invoice/cancel-by-internal-id/{internalId}` | sipas tipit te fatures | 1 s | `429` | Anulimi pret ne te njejten radhe me leshimin e tipit qe kthen, sepse dokumenti korrigjues merr numrin nga e njejta sekuence. Nje anulim fature cash pret pas leshimeve cash te te njejtit TCR. Nje leshim e mban bllokimin rreth 0.13 s. `POST /invoice/bulk-noncash` e merr dhe e liron per cdo fature brenda bllokut. Per leshimin e faturave ky bllokim eshte kufiri qe ndeshni, bashke me kufirin e pergjithshem me siper. Paralelizmi nuk jep me shume fatura, vetem me shume pritje. ## Wolt Partner API | Endpoint-et | Kufiri | |---|---| | Leximet, perfshire feed-in e ngjarjeve | 180 / min | | Shkrimet | 60 / min | ## Buxheti per grup Cdo endpoint i perket nje grupi. Keta numra jane buxheti me te cilin eshte dimensionuar API-ja, maten per cdo token dhe do te zbatohen. Ndertoni brenda tyre. | Grupi | Buxheti | Endpoint-et | |---|---|---| | I zakonshem | 240 / min | cdo endpoint `v1` dhe `v2` jashte grupeve me poshte | | Fiskal | 30 / min, 600 / ore | `POST /invoice/cash`, `/invoice/noncash`, `/invoice/e-invoice`, `/invoice/order`, `/invoice/summary`, `/invoice/wtn`, `POST /invoice/cancel/{id}`, `POST /invoice/cancel-by-internal-id/{internalId}`, `GET /purchase-invoices` | | Bllok | 3 / min, 30 / ore | `POST /invoice/bulk-noncash` | | Printim | 30 / min | `GET /invoice/print/{id}`, `GET /invoice/print-eic/{eic}`, `GET /invoice/wtn/print/{id}` | | Raporte | 30 / min | `GET /reports/*`, `GET /dashboard/summary` | | Kerkim | 90 / min | `GET /client/search` | | Regjistrim | 30 / min, 600 / ore | `POST /register`, `POST /on-boarding/*` | ## Praktika - Kerkoni faqe me te medha, jo me shume faqe. Shihni [Faqezimi](/api-reference/pages/pagination.html). - Terhiqni faqet nje pas nje, jo paralelisht. - Per shume fatura perdorni `POST /api/v1/invoice/bulk-noncash`. Buxheti numeron kerkesa, jo fatura. - Mbani ne cache katalogun, kategorite dhe monedhat. Ato jane listat me interval minimal. ### Faqezimi Shumica e listave faqezohen me `limit` dhe `offset`, dhe numeruesit kthehen ne nje objekt `pagination`. Por jo te gjitha listat sillen njesoj, dhe dallimet kane rendesi kur shkruani nje cikel qe lexon gjithcka. ## Tabela e shkurter | Endpoint | Parametrat | `total` | Kufiri i `limit` | | --- | --- | --- | --- | | `GET /invoice` | `limit`, `offset` | jo | pa kufi | | `GET /invoice/wtn` | `limit`, `offset` | jo | pa kufi | | `GET /clients` | `limit`, `offset` | po | 100 | | `GET /api/v2/clients` | `limit`, `offset` | po | 100 | | `GET /bank-accounts` | `limit`, `offset` | po | 100 | | `GET /products` | `limit`, `offset` | po | 500 | | `GET /purchase-invoices` | `page` | jo | nuk zbatohet | Pa `limit` merret `20`, dhe pa `offset` merret `0`. Perjashtim ben lista e produkteve, e cila pa `limit` kthen te gjithe katalogun. ## Listat me total Klientet dhe llogarite bankare kthejne `total`, pra e dini qe ne faqen e pare sa faqe ju presin: ```bash curl 'https://fature.al/api/v1/clients?limit=100&offset=0' \ -H 'Authorization: Bearer TOKEN_I_JUAJ' ``` ```json { "status": true, "data": { "items": [ ... ], "pagination": { "records": 100, "total": 842, "limit": 100, "offset": 0 } } } ``` `records` eshte sa erdhen ne kete faqe, `total` eshte sa ekzistojne gjithsej. Vazhdoni me `offset += limit` derisa `offset` te kaloje `total`. ## Listat pa total Lista e faturave dhe ajo e fleteve shoqeruese nuk e llogarisin totalin, sepse mbi miliona rreshta ai numerim do te kushtonte me shume se vete faqja. `pagination` i tyre ka vetem numeruesit e faqes: ```json { "items": [ ... ], "pagination": { "records": 20, "limit": 20, "offset": 0, "type": "EINVOICE", "query": null } } ``` Ndaloni kur faqja vjen me e shkurter se `limit`, jo kur arrini nje total: ```bash offset=0 while :; do n=$(curl -s "https://fature.al/api/v1/invoice?limit=100&offset=$offset" \ -H "Authorization: Bearer $TOKEN" | jq '.data.pagination.records') [ "$n" -lt 100 ] && break offset=$((offset + 100)) done ``` Lista e faturave nuk e kufizon `limit`, por kjo nuk do te thote se duhet kerkuar gjithcka njeheresh: nje faqe shume e madhe ngadaleson pergjigjen dhe rrit mundesine qe kerkesa te skadoje. Faqe nga 100 deri ne 500 punojne mire. `pagination` kthen edhe `type` me `query`, pra filtrat qe zbatoi. Kjo ndihmon kur ciklin e shkruani mbi disa filtra njeheresh. ## Produktet e mbajne pagination jashte data Lista e produkteve eshte e vjeter sa vete API-ja, dhe forma e saj nuk ndryshohet dot pa prishur integrimet qe e lexojne. Prandaj `data` ka mbetur vargu i thjeshte qe ka qene gjithmone, dhe `pagination` rri **krahas** tij, jo brenda: ```json { "status": true, "data": [ { "id": 1, "code": "SRV-01", "name": "Sherbim" } ], "pagination": { "records": 1, "total": 340, "limit": 20, "offset": 0 } } ``` Pra `data[0]` eshte nje produkt, ndersa tek listat e tjera `data.items[0]` eshte elementi. Nje program i shkruar para se filtrat te ekzistonin lexon sot sakte ate qe lexonte me pare. Pa `limit` kthehet i gjithe katalogu dhe `limit` mbetet `null` ne pergjigje. Sapo e dergoni, ai kufizohet ne 500. Kjo liste ka edhe nje kufi kerkesash me vete: nje thirrje cdo 10 sekonda. Kur e kaloni, pergjigja kthen zarfin e gabimit, por me status HTTP `200`, jo `429`. Kontrolloni fushen `status` te trupit, jo vetem kodin. ## Faturat e blerjes numerohen me faqe `GET /purchase-invoices` nuk lexon nga baza jone, por nga sistemi i fiskalizimit, dhe ai faqezohet me numer faqeje qe fillon nga `1`: ```bash curl 'https://fature.al/api/v1/purchase-invoices?fromDate=2026-09-01&toDate=2026-09-30&page=1' \ -H 'Authorization: Bearer TOKEN_I_JUAJ' ``` `pagination` kthen `records` dhe `page`. Perseritni me `page + 1` derisa `items` te kthehet bosh. Pa `fromDate` dhe `toDate` merret dita e sotme, jo e gjithe historia. ## Renditja Listat kthehen nga me e reja tek me e vjetra, sipas `id` zbrites. Kjo do te thote se nje fature e re e leshuar gjate kohes qe ju lexoni faqet i zhvendos rreshtat nje pozicion me poshte, dhe nje rresht mund ta shihni dy here. Kur lexoni nje periudhe te mbyllur, kufizojeni me `fromDate` dhe `toDate`. Nje periudhe qe ka mbaruar nuk pranon me rreshta te rinj, prandaj faqet mbeten te qendrueshme sa kohe qe cikli punon. ## Shembuj ### Llojet e faturave Cdo lloj fature ka endpoint-in e vet, dhe trupi i kerkeses ndryshon me shume nga sa duket. E njejta fature e derguar tek `/invoice/cash` dhe tek `/invoice/e-invoice` refuzohet nga i dyti, sepse e-fatura kerkon fusha qe arka nuk i njeh. | Dokumenti | Endpoint | Kur perdoret | | --- | --- | --- | | Cash | `POST /invoice/cash` | Pagesa kryhet ne moment, ne arke | | Jo-cash | `POST /invoice/noncash` | Pagesa vjen me vone, me transferte ose ne llogari | | E-fature | `POST /invoice/e-invoice` | Bleresi eshte biznes dhe fatura shkon ne sistemin e e-faturave | | Porosi | `POST /invoice/order` | Konsumi ka nisur, pagesa nuk ka perfunduar | | Permbledhese | `POST /invoice/summary` | Mbyll nje ose me shume porosi me nje pagese | | Bllok jo-cash | `POST /invoice/bulk-noncash` | Shume fatura jo-cash ne nje kerkese | | Flete shoqeruese | `POST /invoice/wtn` | Mall qe leviz, jo shitje | ## Fatura cash `payment_method` eshte i detyrueshem dhe pranon `BANKNOTE`, `CARD`, `CHECK`, `SVOUCHER`, `COMPANY` ose `ORDER`. Klienti nuk eshte i detyrueshem. Pa `client` fatura leshohet per klientin e rastit, qe eshte rasti normal i nje arke: ```bash curl -X POST 'https://fature.al/api/v1/invoice/cash' \ -H 'Authorization: Bearer TOKEN_I_JUAJ' \ -H 'Content-Type: application/json' \ -d '{ "internalId": "ARK-2026-0001", "payment_method": "BANKNOTE", "lines": [ { "product_name": "Kafe", "product_code": "KAF-001", "unit": "cope", "quantity": 2, "price": 150, "total": 300, "vat": 20 } ] }' ``` Sapo dergoni qofte edhe nje fushe te klientit, `client.name` behet i nevojshem, dhe bashke me te adresa me qytetin, ose ne kerkese ose te ruajtura me pare tek klienti. ### Dy kombinime qe lidhen me menyren e pageses Dy fusha varen plotesisht nga `payment_method`, dhe te dyja jane te ndaluara kur menyra nuk perputhet. Kjo eshte gabimi me i shpeshte ne kete endpoint. **`COMPANY` kerkon `company_card`.** Pa te CIS-i e kthen faturen: ```json { "internalId": "ARK-2026-0002", "payment_method": "COMPANY", "company_card": "4111-2233", "lines": [ ... ] } ``` **`SVOUCHER` kerkon `vouchers`.** Numrat jane ne formen numer-vit-NIPT, nuk perseriten brenda te njejtes fature, dhe nuk kalojne 20: ```json { "internalId": "ARK-2026-0003", "payment_method": "SVOUCHER", "vouchers": ["12-2026-K51501011M", "13-2026-K51501011M"], "lines": [ ... ] } ``` Dergimi i `company_card` me `BANKNOTE`, ose i `vouchers` me `CARD`, refuzohet. Nuk ka vend ku ato te shkojne ne dokumentin fiskal, prandaj nuk pranohen ne heshtje. ## Fatura jo-cash `payment_method` ketu nuk eshte i detyrueshem, dhe pranon vlera te tjera nga cash-i: `ACCOUNT`, `COMPENSATION`, `FACTORING`, `KIND`, `OTHER`, `TRANSFER`, `WAIVER`. `client.name` duhet, pervec kur dergoni `client.internal_id` te nje klienti te ruajtur. Llogaria bankare shkruhet ne fature ne tri menyra, sipas asaj qe keni ne dore: ```json { "bank_account": 42 } ``` ```json { "bank_account_iban": "AL35202111090000000001234567" } ``` ```json { "bankAccount": { "name": "BKT", "iban": "AL35202111090000000001234567", "currency": "ALL", "swift": "NCBAALTX", "holder": "Ei3 Software Solution shpk" } } ``` E para tregon nje llogari qe e keni ne fature.al, e dyta e gjen me IBAN, e treta e shkruan te plote. Forma e trete e ruan llogarine si llogari te kompanise suaj, dhe nje IBAN qe ekziston tashme riperdoret ne vend qe te dyfishohet, keshtu qe mund ta dergoni ne cdo fature pa i mbushur llogarite. E njejta forme pranohet edhe nga `POST /invoice/e-invoice`. Nje tarife shtese shkon vecmas nga rreshtat: ```json { "fee": { "fee_type": "PACK", "fee_amount": 50 } } ``` ### Note krediti dhe note debiti Nje fature jo-cash korrigjohet nga nje fature tjeter jo-cash. Dergoni `doc_type` bashke me `original_invoice_iic`, IIC-ne qe ju ktheu fatura origjinale: ```json { "internalId": "NK-2026-000037", "doc_type": "381", "original_invoice_iic": "8FE72E2ACD1C500A83F8C89B4E2E3E1D", "client": { "name": "Alpha SHPK" }, "lines": [ ... ] } ``` `381` eshte note krediti dhe ul vleren qe bleresi ju detyrohet, `383` eshte note debiti dhe e rrit. Pa `doc_type`, ose me `380`, fatura eshte e zakonshme. Origjinali duhet te jete fature jo-cash e fiskalizuar, e paanuluar dhe ende e korrigjueshme. Rreshtat qe dergoni jane rreshtat e korrigjimit, jo ata te fatures origjinale, dhe vlerat shkojne pozitive: drejtimin e percakton `doc_type`, jo shenja e numrave. Per te kthyer nje fature te plote perdorni endpoint-in e anulimit. ## E-fatura E-fatura ka rregullat e veta dhe nje faqe te veten: [Fatura elektronike](/api-reference/pages/e-invoice.html). Ndryshimet kryesore nga faturat e mesiperme jane tri: `client` eshte i detyrueshem me NIPT, cdo rresht kerkon `unit_code`, dhe `doc_type` me `process` duhen gjithmone. ## Porosi dhe permbledhese Keto te dyja punojne ne cift. Porosia regjistron konsumin qe ka nisur, permbledhesja e mbyll pagesen. Perdoren tipikisht ne bar dhe restorant, ku tavolina hapet dhe paguhet me vone. **Hapi 1, porosia.** Mos dergoni `payment_method`: ai vendoset vete ne `ORDER`. ```bash curl -X POST 'https://fature.al/api/v1/invoice/order' \ -H 'Authorization: Bearer TOKEN_I_JUAJ' \ -H 'Content-Type: application/json' \ -d '{ "internalId": "POR-2026-0044", "lines": [ { "product_name": "Birre", "product_code": "BIR-01", "unit": "cope", "quantity": 3, "price": 300, "total": 900, "vat": 20 } ] }' ``` Ruani `iic` qe ju kthehet. Ai eshte celesi me te cilin porosia mbyllet. **Hapi 2, permbledhesja.** Ketu nuk dergohen rreshta fare: ata merren nga vete porosite. Dergoni IIC-te e tyre, dhe `payment_method` qe pranon vetem `BANKNOTE` ose `CARD`: ```bash curl -X POST 'https://fature.al/api/v1/invoice/summary' \ -H 'Authorization: Bearer TOKEN_I_JUAJ' \ -H 'Content-Type: application/json' \ -d '{ "internalId": "PRM-2026-0021", "payment_method": "CARD", "order_invoices": [ "8FE72E2ACD1C500A83F8C89B4E2E3E1D", "A1B2C3D4E5F60718293A4B5C6D7E8F90" ] }' ``` Nje permbledhese mbyll disa porosi njeheresh, prandaj nje tavoline me tri porosi te hapura paguhet me nje dokument te vetem. Pergjigja i liston ato tek `settledOrderInvoices`. ## Bllok jo-cash `POST /invoice/bulk-noncash` merr nje varg `invoices`, ku secili element eshte i njejti trup si nje fature jo-cash e vetme: ```json { "invoices": [ { "internalId": "AB-001", "client": { "name": "Klient A" }, "lines": [ ... ] }, { "internalId": "AB-002", "client": { "name": "Klient B" }, "lines": [ ... ] } ] } ``` Pergjigja eshte nje objekt me celes `internalId`, dhe statusi mbetet `200` edhe kur ndonje fature brenda deshton. Kontrolloni cdo hyrje me vete. ## Zbritjet Nje fature zbritet e gjitha, me `invoice_discount_type` dhe `invoice_discount_value`, dhe rreshtat mbeten ashtu si i dergoni: ```json { "invoice_discount_type": "percent", "invoice_discount_value": 10 } ``` Vlen per cash, jo-cash, e-fature dhe permbledhese, por jo per porosi. Nje rresht i vetem zbritet me `lines[].discount`, perqindje mbi cmimin e njesise, me `price` te plote dhe `total` tashme te ulur: ```json { "product_name": "Kafe", "product_code": "KAF-001", "unit": "cope", "quantity": 2, "price": 150, "discount": 10, "total": 270, "vat": 20 } ``` Rregullat e plota dhe shembujt me numra jane tek [Zbritjet ne fature](/api-reference/pages/discounts.html). ## Flete shoqeruese Fleta shoqeruese nuk eshte shitje: shoqeron mall qe leviz nga nje pike ne tjetren. Prandaj trupi i saj nuk ngjan me asnje nga te mesipermet, dhe rreshtat quhen `invoice_lines`, jo `lines`. Kerkohen `vehPlates`, `valueOfGoods` dhe `invoice_lines`. Pjesa tjeter ka vlera te parazgjedhura: ```bash curl -X POST 'https://fature.al/api/v1/invoice/wtn' \ -H 'Authorization: Bearer TOKEN_I_JUAJ' \ -H 'Content-Type: application/json' \ -d '{ "vehPlates": "AA123BB", "valueOfGoods": 45000, "type": "WTN", "transaction": "TRANSFER", "vehOwnership": "OWNER", "startPoint": "WAREHOUSE", "destinPoint": "STORE", "startCity": "Tirane", "invoice_lines": [ { "product_name": "Miell", "product_code": "MLL-01", "unit": "kg", "quantity": 500, "price": 90, "total": 45000 } ] }' ``` Vlerat e lejuara jane te fiksuara: `type` eshte `WTN` ose `SALE`, `transaction` eshte `TRANSFER`, `EXAMINATION`, `SALES` ose `DOOR`, `vehOwnership` eshte `OWNER` ose `THIRDPARTY`, ndersa `startPoint` me `destinPoint` marrin `ANOTHER`, `CUSTOMS`, `EXHIBITION`, `OTHER`, `SALE`, `STORE` ose `WAREHOUSE`. ## Anulimi i plote dhe i pjesshem Pa trup anulohet e gjithe fatura, sido qe te jete lloji i saj: ```bash curl -X POST 'https://fature.al/api/v1/invoice/cancel/40312' \ -H 'Authorization: Bearer TOKEN_I_JUAJ' ``` Me `lines` anulohet vetem nje pjese, dhe kjo eshte e mundur **vetem per faturat cash**: ```json { "lines": [ { "product_name": "Kafe", "product_code": "KAF-001", "quantity": 1, "price": 150 } ] } ``` Cdo rresht duhet te ekzistoje ne faturen origjinale me te njejtin `product_code` dhe `product_name`, dhe sasia mund vetem te ulet. 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. Nje fature qe u leshua me zbritje mbi te gjithe faturen anulohet vetem e plote. Zbritja eshte shperndare mbi te gjitha normat e TVSH-se se dokumentit, keshtu qe anulimi i vetem disa rreshtave do ta prishte TVSH-ne. Fatura mbetet e hapur per anulime te metejshme derisa ato ta mbulojne te gjithen, dhe vetem atehere shenohet si e anuluar. ## Cfare ndryshon mes tyre Kjo tabele eshte arsyeja pse nje trup i kopjuar nga nje lloj ne tjetrin refuzohet: | Fusha | Cash | Jo-cash | E-fature | Porosi | | --- | --- | --- | --- | --- | | `payment_method` | e detyrueshme | opsionale | opsionale | nuk dergohet | | `client` | opsional | opsional | **i detyrueshem** | opsional | | `client.nuis` | nuk perdoret | nuk perdoret | **i detyrueshem** | nuk perdoret | | `lines.*.vat` | **e detyrueshme** | opsionale | opsionale | e detyrueshme | | `lines.*.unit_code` | nuk kerkohet | nuk kerkohet | **i detyrueshem** | nuk kerkohet | | `doc_type` | nuk perdoret | opsional, per note krediti ose debiti | **i detyrueshem** | nuk perdoret | | `process` | nuk perdoret | nuk perdoret | **i detyrueshem** | nuk perdoret | | `fee` | nuk perdoret | opsional | nuk perdoret | nuk perdoret | | Zbritje mbi faturen | po | po | po | jo, shkon tek permbledhesja | | Anulim i pjesshem | po | jo | jo | jo | Fusha te perbashketa per te gjitha: `internalId`, `lines` me te pakten nje rresht, dhe `currency` me `exchange_rate` kur fatura nuk eshte ne leke. ## Kur biznesi nuk eshte ne skemen e TVSH-se Nje biznes jashte skemes se TVSH-se nuk leshon dot fatura me TVSH, prandaj cdo rresht regjistrohet me `vat` `0` dhe me perjashtim `TAX_FREE`, sido qe ta dergoni fushen. Kerkesa nuk refuzohet dhe asgje nuk ju paralajmeron: fatura del pa TVSH. Kete e vendos konfigurimi i biznesit ne fature.al, jo kerkesa, keshtu qe po ta shihni nje fature pa TVSH aty ku prisnit 20 per qind, kontrolloni skemen e biznesit para se te kontrolloni trupin qe derguat. ### Fatura elektronike Nje fature elektronike shkon ne sistemin qendror te e-faturave, jo vetem ne fiskalizim. Kjo sjell dy gjera qe faturat e tjera nuk i kane: bleresi duhet te jete i identifikuar me NIPT dhe me adrese te plote, dhe dokumenti duhet te thote se cfare lloji eshte. Leshohet me `POST /api/v1/invoice/e-invoice`. ## Bleresi duhet te jete i plote Bleresi shkon i plote ne sistemin e e-faturave, prandaj adresa dhe qyteti jane te nevojshme. Mund t'i dergoni ne kerkese si `client.address` dhe `client.city`, ose t'i keni ruajtur me pare tek klienti ne fature.al. Kur mungon njera, kerkesa refuzohet me `400` dhe fusha `errors` thote sakte cfare duhet plotesuar. Kur klienti ekziston tashme ne fature.al, dergoni vetem `client.internal_id`. Atehere klienti gjendet me te dhe fushat e tjera nuk lexohen fare: ```json { "client": { "internal_id": 8812 } } ``` Ndryshe duhen `client.nuis`, `client.name` dhe `client.country`. `country` eshte kod ISO 3166-1 alpha-3, pra `ALB`, `RKS`, `USA`. ## doc_type dhe process Te dyja jane te detyrueshme. `process` shkon si ProfileID ne dokumentin UBL, dhe `doc_type` si lloji i dokumentit. | Dokumenti | `doc_type` | `process` | Kerkon `original_invoice_iic` | | --- | --- | --- | --- | | Fature shitjeje | `380` | `P1` | jo | | Note krediti | `381` | `P9` | po | | Note debiti | `383` | `P9` | po | Nje note krediti dhe nje note debiti korrigjojne nje fature tjeter, prandaj kerkojne `original_invoice_iic`, IIC-ne qe ju ktheu fatura origjinale. Pa te kerkesa refuzohet me `422`. Per llojet e tjera te dokumentit ajo fushe nuk pranohet. Per te kthyer nje fature te plote mos leshoni note krediti. Perdorni endpoint-in e anulimit, i cili e shenon origjinalin si te kthyer. Lista e plote e vlerave qe pranohen per te dyja fushat eshte ne faqen e endpoint-it. ## Nota krediti dhe nota debiti Te dyja korrigjojne nje fature qe eshte regjistruar tashme, dhe te dyja leshohen nga i njejti endpoint si nje fature e zakonshme. Ndryshimi eshte drejtimi: nota krediti e ul vleren qe bleresi ju detyrohet, nota debiti e rrit. Te dyja kerkojne `original_invoice_iic`, IIC-ne qe ju ktheu fatura origjinale. Ajo shkon si BillingReference ne dokumentin UBL dhe si reference korrigjimi ne regjistrimin e CIS, keshtu qe bleresi dhe sistemi qendror e dine sakte cilen fature po korrigjoni. Pa te kerkesa refuzohet me `422`. Rreshtat qe dergoni jane rreshtat e korrigjimit, jo rreshtat e fatures origjinale. Dergoni vetem ate qe po korrigjoni, me vleren e diferences. ### Nota krediti: zbritje pas faturimit Fatura `412/2026` doli 12,000 leke. I zbritet 2,000 leke sepse sherbimi u nderpre per nje muaj. Leshoni nje note krediti per diferencen, jo per te gjithe faturen: ```bash curl -X POST 'https://fature.al/api/v1/invoice/e-invoice' \ -H 'Authorization: Bearer TOKEN_I_JUAJ' \ -H 'Content-Type: application/json' \ -d '{ "internalId": "NK-2026-000037", "process": "P9", "doc_type": "381", "original_invoice_iic": "8FE72E2ACD1C500A83F8C89B4E2E3E1D", "payment_method": "TRANSFER", "client": { "nuis": "L62221018T", "name": "Ei3 Software Solution shpk", "address": "Rruga e Kavajes 12", "city": "Tirane", "country": "ALB" }, "lines": [ { "product_name": "Zbritje per nderprerje sherbimi", "product_code": "ABO-01", "unit": "Cope", "unit_code": "C62", "quantity": 1, "price": 2000, "total": 2000, "vat": 20 } ] }' ``` Vlerat dergohen pozitive. Eshte `doc_type=381` qe e ben dokumentin zbritje, jo shenja e numrave. ### Nota debiti: vlere e nenfaturuar E njejta fature doli 2,000 leke me pak sepse nje ore pune nuk u llogarit. Nje note debiti e shton diferencen mbi faturen origjinale: ```bash curl -X POST 'https://fature.al/api/v1/invoice/e-invoice' \ -H 'Authorization: Bearer TOKEN_I_JUAJ' \ -H 'Content-Type: application/json' \ -d '{ "internalId": "ND-2026-000012", "process": "P9", "doc_type": "383", "original_invoice_iic": "8FE72E2ACD1C500A83F8C89B4E2E3E1D", "payment_method": "TRANSFER", "client": { "nuis": "L62221018T", "name": "Ei3 Software Solution shpk", "address": "Rruga e Kavajes 12", "city": "Tirane", "country": "ALB" }, "lines": [ { "product_name": "Ore pune shtese", "product_code": "SRV-02", "unit": "Ore", "unit_code": "HUR", "quantity": 2, "price": 1000, "total": 2000, "vat": 20 } ] }' ``` Pergjigja eshte e njejta si e nje fature: nota merr `id`, `number`, `iic`, `fic` dhe `eic` te vetat. Eshte nje dokument me vete, jo nje ndryshim mbi faturen e vjeter, dhe origjinali mbetet i vlefshem ashtu sic u leshua. ### Cilin te zgjidhni | Situata | Dokumenti | | --- | --- | | Bleresi kthen mallin ose anulon te gjithe porosine | Anulim, jo note krediti | | Zbritje, mall i demtuar, sherbim i pakryer pjeserisht | Note krediti, `381` | | Fatura doli me pak se sa duhej | Note debiti, `383` | | Gabim ne NIPT ose ne emrin e bleresit | Anulim, pastaj fature e re | Anulimi ndryshon nga te dyja: ai e shenon origjinalin si te kthyer, ndersa nje note e le faturen te hapur dhe i qendron perkrah si dokument korrigjues. ## Rreshtat Cdo rresht kerkon `product_name`, `product_code`, `unit`, `unit_code`, `quantity`, `price` dhe `total`. `unit` eshte teksti qe lexon njeriu, ndersa `unit_code` eshte kodi qe mban dokumenti fiskal. Kodin e jep thirresi, sepse zgjedhja e nje kodi te parazgjedhur ne heshtje dergonte e-fatura qe lexonin "Cope" per rreshta qe operatori i kishte shenuar m2. Vlerat me te perdorura jane `C62` per cope, `MTK` per meter katror, `LTR` per liter dhe `KGM` per kilogram. `E4` eshte kilogrami bruto dhe `DT` toni i thate, prandaj per peshen e zakonshme dergoni `KGM` ose `TNE`. `vat` pranon `0`, `6`, `10` ose `20`. Kur nje rresht eshte i perjashtuar nga TVSH-ja, dergoni `vat_exempt_type` me nje nga `TYPE_1`, `TYPE_2`, `EXPORT_OF_GOODS` ose `TAX_FREE`. ## Monedha dhe kursi Kur fatura eshte ne monedhe te huaj, dergoni `currency` bashke me `exchange_rate`. `exchange_rate` eshte sa leke vlen nje njesi e monedhes se fatures. Pa te, ose me nje vlere jo pozitive, merret `1`. Per monedha qe vlejne me pak se nje lek, si JPY ose HUF, dergoni vlere nen 1. Ky eshte gabimi qe behet me shpesh: kursi shkon ne drejtimin lek-per-njesi, jo anasjelltas. ## Cfare ju kthehet Pergjigja e suksesshme mban `id`, `number`, `iic`, `fic`, `verifyURL` dhe `pdf`. `eic` eshte i pranishem vetem tek nje fature elektronike qe e ka marre tashme, prandaj trajtojeni si mungese te celesit dhe jo si `null`. Kur ekziston, `pdf` tregon PDF-in zyrtar te e-fatures, jo tonin. `fic` mbetet `null` derisa nje fiskalizim i shtyre te kryhet. Kjo ndodh kur sherbimi i fiskalizimit ishte i paarritshem ne castin e leshimit dhe kerkesa ktheu `503`. ## Shkarkimi i PDF-it me EIC ```bash curl 'https://fature.al/api/v1/invoice/print-eic/2e9b6f31-d712-4c45-8cc0-9faf24c805a3' \ -H 'Authorization: Bearer TOKEN_I_JUAJ' \ -o fatura.pdf ``` Kujdes me nje EIC qe nuk gjendet: pergjigja eshte teksti `Document not found.` me status `200` dhe `Content-Type: text/html`, jo nje PDF. Kontrolloni `Content-Type` para se ta ruani skedarin. ## Gabimet qe hasen me shpesh | Statusi | Kuptimi | | --- | --- | | `400` | Te dhena te paplota. `errors` thote sakte cfare mungon, zakonisht adresa ose qyteti i bleresit. | | `403` | Abonimi ka mbaruar, ose llogaria nuk ka te drejten EINVOICE. | | `409` | Nje fature me kete `internalId` ekziston ose po procesohet per kete vit. | | `422` | Validimi deshtoi. Kjo pergjigje perdor fushen `success`, jo `status`. | | `503` | Fiskalizimi i paarritshem. Fatura eshte ruajtur dhe do te fiskalizohet vete me vone. | Zarfi i gabimit eshte i njejte kudo pervec `422`, i cili kthen `success: false` bashke me `errors` te ndare sipas fushes. Nje `internalId` qe mungon kthehet me zarfin standard, jo me ate te validimit. ### Zbritjet ne fature Nje fature e leshuar nga API-ja zbritet ne dy menyra, dhe te dyja mund te zbatohen mbi te njejtin dokument: | Zbritja | Fushat | Si lexohet vlera | Ku zbatohet | | --- | --- | --- | --- | | mbi te gjithe faturen | `invoice_discount_type` me `invoice_discount_value` | perqindje ose vlere fikse me TVSH, sipas tipit | mbi shumen e rreshtave, e shperndare mbi normat e TVSH-se | | mbi nje rresht | `lines[].discount` | gjithmone perqindje, nga 0 ne 100 | mbi cmimin e njesise se atij rreshti | Kur te dyja dergohen bashke, se pari zbritet rreshti dhe pastaj zbritja e fatures zbatohet mbi totalin qe del. ## Zbritja mbi te gjithe faturen | Fusha | Vlerat | Kuptimi | | --- | --- | --- | | `invoice_discount_type` | `percent` ose `amount` | si lexohet vlera | | `invoice_discount_value` | numer jo negativ | sa zbritet | Punojne vetem ne cift. Njera pa tjetren, ose nje vlere `0`, e le faturen pa zbritje dhe nuk kthen gabim, prandaj mos prisni nje `422` per te kuptuar se zbritja nuk u zbatua: lexoni `amount.discount` ne pergjigje. | Tipi | Si lexohet vlera | Kufiri | | --- | --- | --- | | `percent` | perqindje mbi totalin me TVSH | mbi 100 lexohet si 100 | | `amount` | vlere **me TVSH**, ne monedhen e fatures | mbi totalin lexohet si totali | `amount` eshte gjithmone ne monedhen e fatures, jo ne leke. Nje fature ne euro me `invoice_discount_value: 50` zbritet 50 euro. ## Shembull me perqindje Nje fature prej 300 leke me TVSH 20 dhe nje zbritje prej 10 per qind: ```bash curl -X POST 'https://fature.al/api/v1/invoice/cash' \ -H 'Authorization: Bearer TOKEN_I_JUAJ' \ -H 'Content-Type: application/json' \ -d '{ "internalId": "ARK-2026-0101", "payment_method": "BANKNOTE", "invoice_discount_type": "percent", "invoice_discount_value": 10, "lines": [ { "product_name": "Kafe", "product_code": "KAF-001", "unit": "cope", "quantity": 2, "price": 150, "total": 300, "vat": 20 } ] }' ``` | Vlera | Para zbritjes | Pas zbritjes | | --- | --- | --- | | Totali me TVSH | 300.00 | 270.00 | | Baza pa TVSH | 250.00 | 225.00 | | TVSH | 50.00 | 45.00 | Klienti paguan 30 leke me pak, ndersa `amount.discount` ne pergjigje eshte **25.00**. Kjo nuk eshte mosperputhje: `discount` mban pjesen pa TVSH te zbritjes, sepse ashtu shkon zbritja ne dokumentin fiskal dhe ne UBL. Zbritja qe ndjen klienti eshte diferenca ne `amount.gross`. ## Fatura me disa norma TVSH-je Zbritja shperndahet mbi grupet e TVSH-se sipas peshes se secilit ne total, dhe TVSH-ja rillogaritet mbi vleren e ulur te secilit grup. Nje fature me nje rresht 1,000 me TVSH 20 dhe nje rresht 500 me TVSH 6, e zbritur me `amount: 300`: | Norma | Totali para | Pjesa e zbritjes | Baza pas | TVSH pas | | --- | --- | --- | --- | --- | | 20 | 1,000.00 | 200.00 | 666.67 | 133.33 | | 6 | 500.00 | 100.00 | 377.36 | 22.64 | | **Gjithsej** | **1,500.00** | **300.00** | **1,044.03** | **155.97** | Pergjigja kthen `amount.gross` 1,200.00 dhe `amount.discount` 261.00, qe eshte pjesa pa TVSH e atyre 300 lekeve. ## Tarifa mbetet jashte zbritjes Ne faturat jo-cash, `fee` nuk hyn ne bazen e zbritjes. Zbritet shuma e rreshtave, dhe tarifa i shtohet totalit te ulur. Nje fature me rreshta 1,000, tarife 50 dhe zbritje 10 per qind zbret 100 leke, jo 105, dhe totali del 950. ## Zbritja mbi nje rresht `lines[].discount` eshte perqindja e zbritjes se atij rreshti, nga 0 ne 100. Fusha eshte opsionale: nje trup qe nuk e permend fare, ose e dergon bosh, kalon pikerisht si me pare dhe nuk kthen kurre gabim per shkak te saj. Kontrolli me poshte prek vetem rreshtat qe dergojne nje zbritje. `price` mbetet cmimi i plote i njesise dhe `total` vjen tashme i ulur, sepse ashtu e mban zbritjen dokumenti fiskal: perqindje mbi cmimin, bashke me nje total tashme te zbritur. Rregulli i vetem qe duhet mbajtur eshte ky: ``` total = price * quantity * (100 - discount) / 100 ``` Nje `total` qe nuk perputhet me ate shifer e refuzon kerkesen me `400`, dhe `errors` tregon cili eshte rreshti dhe cila vlere pritej. Nuk e llogarisim ne vend tuaj me qellim: nje `total` i barabarte me `price * quantity` do te dukej njelloj si nje rresht qe e ka zbritjen tashme brenda cmimit, dhe zbatimi i saj perseri do ta zbriste dy here nje fature qe pastaj fiskalizohet. Nje kafe 150 leke me TVSH 20, dy cope, e zbritur 10 per qind: ```bash curl -X POST 'https://fature.al/api/v1/invoice/cash' \ -H 'Authorization: Bearer TOKEN_I_JUAJ' \ -H 'Content-Type: application/json' \ -d '{ "internalId": "ARK-2026-0102", "payment_method": "BANKNOTE", "lines": [ { "product_name": "Kafe", "product_code": "KAF-001", "unit": "cope", "quantity": 2, "price": 150, "discount": 10, "total": 270, "vat": 20 }, { "product_name": "Uje", "product_code": "UJE-01", "unit": "cope", "quantity": 1, "price": 100, "total": 100, "vat": 20 } ] }' ``` | Vlera e rreshtit | Pa zbritje | Me 10 per qind | | --- | --- | --- | | Totali me TVSH | 300.00 | 270.00 | | Baza pa TVSH | 250.00 | 225.00 | | TVSH | 50.00 | 45.00 | Ne pergjigje, ai rresht kthen `discount_rate` 10, `unitPrice` 135 dhe `total` 270. `discount` kthen 25.00, sepse si tek zbritja e fatures mban pjesen pa TVSH. Nje perqindje jashte intervalit 0 deri 100 refuzohet me `422`. ## Te dyja mbi te njejten fature Kur nje fature mban zbritje rreshti dhe zbritje mbi te gjithe faturen, radha eshte e fiksuar: se pari zbriten rreshtat, pastaj zbritja e fatures zbatohet mbi totalin qe del prej tyre. Kafeja e mesiperme, e zbritur edhe 10 per qind mbi faturen, jep 270 dhe pastaj 243. ## Ku pranohet | Endpoint | Mbi faturen | Mbi rreshtin | | --- | --- | --- | | `POST /invoice/cash` | po | po | | `POST /invoice/noncash` | po | po | | `POST /invoice/e-invoice` | po | po | | `POST /invoice/order` | jo, shihni me poshte | po | | `POST /invoice/summary` | po | vjen nga porosite | | `POST /invoice/bulk-noncash` | po, brenda cdo fature te bllokut | po | **Porosia nuk zbritet e gjitha.** Permbledhesja i kopjon rreshtat nga porosite, keshtu qe nje zbritje mbi te gjithe porosine nuk kalon dot tek ajo dhe tavolina do te paguante me shume se sa tregoi porosia. Ajo vendoset mbi permbledhesen. Zbritja per rresht kalon: ruhet mbi rreshtin e porosise dhe permbledhesja e merr bashke me te, prandaj nuk dergohet perseri mbi permbledhesen. Zbritja nuk varet nga konfigurimet e kompanise ne fature.al: cilesimet e ekranit te fatures ndikojne vetem tek forma qe plotesohet me dore, ndersa API-ja e zbaton zbritjen sa here qe e dergoni. ## Anulimi i nje fature me zbritje Nje fature me zbritje mbi te gjithe faturen **anulohet vetem e plote**. Zbritja eshte shperndare mbi te gjitha normat e TVSH-se se dokumentit, keshtu qe anulimi i vetem disa rreshtave do ta prishte TVSH-ne. ```bash curl -X POST 'https://fature.al/api/v1/invoice/cancel/40312' \ -H 'Authorization: Bearer TOKEN_I_JUAJ' ``` Nje kerkese me `lines` mbi nje fature te tille refuzohet me `422` dhe me shpjegimin perkates ne `errors`. ## Zbritje pas faturimit Kur fatura ka dale dhe zbritja bihet dakord me pas, ajo nuk vendoset mbi faturen: leshohet nje note krediti per diferencen, qe eshte dokument me vete dhe i lidhur me origjinalin. Rruga e plote eshte tek [Fatura elektronike](/api-reference/pages/e-invoice.html), dhe per faturat jo-cash e njejta gje behet me `doc_type: "381"` bashke me `original_invoice_iic`. ## Cfare kthehet ne pergjigje Zbritja nuk kthehet nga endpoint-i i leshimit, i cili kthen faturen fiskale (`id`, `number`, `iic`, `fic`). Shihet tek `GET /invoice/{id}/details`: ```json { "amount": { "currency": "ALL", "gross": 270.00, "net": 225.00, "vat": 45.00, "discount": 25.00, "discount_all": 25.00 } } ``` `discount` eshte zbritja mbi te gjithe faturen, pa TVSH. `discount_all` eshte e njejta vlere e kthyer ne leke, dhe ndryshon nga `discount` vetem kur fatura eshte ne monedhe te huaj. Zbritjet e rreshtave nuk hyjne ketu: secila qendron mbi rreshtin e vet, tek `lines[].discount_rate` dhe `lines[].discount`. ## Klienti (v2) Versioni 2 i endpoint-eve te klientit. Perdor nje format te ri me objekte te ndara (`company`/`person`/`address`/`contact`) dhe nje fushe diskriminuese `type` (company|person). Identifikuesi jepet si objekt `id` me `type` dhe `value`. Lloji (`type`) eshte i pandryshueshem ne editim. ### GET /api/v2/clients Lista e klienteve Merr listen e klienteve te kompanise me faqosje dhe filtrim me tekst. Faqezohet me `limit` dhe `offset`. `limit` kufizohet ne **100** dhe `pagination` kthen edhe `total`, prandaj e dini qe ne faqen e pare sa faqe ju presin: vazhdoni me `offset += limit` derisa `offset` te kaloje `total`. Full URL: `https://fature.al/api/v2/clients` API version: `v2`. Authentication: required (bearer token). #### Query parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `limit` | integer | no | Numri i klienteve per faqe (max 100). Defaults to `20`. | | `offset` | integer | no | Nga cili klient te fillohet. Defaults to `0`. | | `query` | string | no | Kerkim ne emer, mbiemer, NIPT, dokument, email ose telefon. | #### Example request ```bash curl -X GET 'https://fature.al/api/v2/clients' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — OK | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.items` | array | | | `data.items[].id` | integer | | | `data.items[].name` | string | | | `data.items[].client_type` | string, nullable | | | `data.items[].company_name` | string, nullable | | | `data.items[].company_type` | string, nullable | | | `data.items[].nipt` | string, nullable | | | `data.items[].first_name` | string, nullable | | | `data.items[].surname` | string, nullable | | | `data.items[].birthday` | string, nullable | | | `data.items[].id_type` | string, nullable | | | `data.items[].id_num` | string, nullable | | | `data.items[].nationality_code` | string, nullable | | | `data.items[].nationality_id` | integer, nullable | | | `data.items[].telephone` | string, nullable | | | `data.items[].email` | string, nullable | | | `data.items[].address` | string, nullable | | | `data.items[].city` | string, nullable | | | `data.items[].customer_number` | string, nullable | | | `data.items[].created_at` | string, nullable | | | `data.pagination` | object | | | `data.pagination.records` | integer | | | `data.pagination.total` | integer | | | `data.pagination.limit` | integer | | | `data.pagination.offset` | integer | | ```json { "status": true, "data": { "items": [ { "id": 1, "name": "Jane Doe", "client_type": "client type", "company_name": "Jane Doe", "company_type": "company type", "nipt": "nipt", "first_name": "Jane", "surname": "Jane Doe", "birthday": "birthday", "id_type": "id type", "id_num": "id num", "nationality_code": "nationality code", "nationality_id": 1, "telephone": "+15551234567", "email": "jane@example.com", "address": "1 Example Street", "city": "Berlin", "customer_number": "customer number", "created_at": "created at" } ], "pagination": { "records": 1, "total": 4200, "limit": 25, "offset": 0 } } } ``` **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`. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **500** — Gabim i papritur ne server. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` ### POST /api/v2/clients Krijo klient (v2) Trupi eshte nje bashkim i diskriminuar nga fusha `type`, e cila pranon `company` ose `person`. Plotesohet vetem objekti qe i perket llojit. | `type` | Objekti | Fushat e detyrueshme | | --- | --- | --- | | `company` | `company` | `name`, `id` | | `person` | `person` | `first_name`, `last_name`, `id` | ## Identifikuesi Jepet gjithmone si objekt `id` me `type` dhe `value`, dhe vlerat e lejuara varen nga lloji: - kompani: `nuis`, `vat`, `tax`; - person: `id`, `passport`, `social`. ## Objektet e perbashketa `address` (`line`, `city`, `country` me tre shkronja) dhe `contact` (`phone`, `email`) jane opsionale dhe vlejne per te dy llojet. `company.category` pranon `business`, `bank` ose `exchange`. Changed since `v1`: - no longer accepts the body parameter `nationality_code` - no longer accepts the body parameter `nationality_id` - no longer accepts the body parameter `telephone` - no longer accepts the body parameter `email` - no longer accepts the body parameter `gender` - no longer accepts the body parameter `birthday` - requires a new body parameter `type` - requires a new body parameter `company` - requires a new body parameter `person` - 201 no longer returns `data.client.name` - 201 no longer returns `data.client.client_type` - 201 no longer returns `data.client.company_name` - 201 no longer returns `data.client.company_type` - 201 no longer returns `data.client.nipt` - 201 no longer returns `data.client.first_name` - 201 no longer returns `data.client.surname` - 201 no longer returns `data.client.birthday` - 201 no longer returns `data.client.id_type` - 201 no longer returns `data.client.id_num` - 201 no longer returns `data.client.nationality_code` - 201 no longer returns `data.client.nationality_id` - 201 no longer returns `data.client.telephone` - 201 no longer returns `data.client.email` - 201 `data.client.address` changed from `string, nullable` to `object` - 201 no longer returns `data.client.city` - accepts a new optional body parameter `address` - accepts a new optional body parameter `contact` - 201 `data.client.address` is now never null - 201 now returns `data.client.type` - 201 now returns `data.client.company` - 201 now returns `data.client.company.name` - 201 now returns `data.client.company.category` - 201 now returns `data.client.company.id` - 201 now returns `data.client.company.id.type` - 201 now returns `data.client.company.id.value` - 201 now returns `data.client.person` - 201 now returns `data.client.person.first_name` - 201 now returns `data.client.person.last_name` - 201 now returns `data.client.person.birthday` - 201 now returns `data.client.person.id` - 201 now returns `data.client.person.id.type` - 201 now returns `data.client.person.id.value` - 201 now returns `data.client.address.line` - 201 now returns `data.client.address.city` - 201 now returns `data.client.address.country` - 201 now returns `data.client.contact` - 201 now returns `data.client.contact.phone` - 201 now returns `data.client.contact.email` - 201 now returns `data.client.verified` - 201 now returns `data.client.updated_at` Full URL: `https://fature.al/api/v2/clients` API version: `v2`. Authentication: required (bearer token). #### Body parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `type` | string | yes | Lloji i klientit, i cili vendos se cili objekt plotesohet: `company` ose `person`. Ne editim eshte i pandryshueshem, prandaj nje `type` i ndryshem nga ai ekzistues refuzohet me `422`. | | `company` | object | yes | Required depending on type. | | `company.name` | string, maxLength 255, nullable | yes | Required depending on type. | | `company.category` | string, nullable | no | | | `company.id` | object | yes | Required depending on type. | | `company.id.type` | string | yes | Required when company.id is present. | | `company.id.value` | string, maxLength 20 | yes | Required when company.id is present. | | `person` | object | yes | Required depending on type. | | `person.first_name` | string, maxLength 255, nullable | yes | Required depending on type. | | `person.last_name` | string, maxLength 255, nullable | yes | Required depending on type. | | `person.birthday` | string, nullable | no | | | `person.id` | object | yes | Required depending on type. | | `person.id.type` | string | yes | Required when person.id is present. | | `person.id.value` | string, maxLength 255 | yes | Required when person.id is present. | | `address` | object, nullable | no | Adresa e klientit. Opsionale, dhe e njejta per te dy llojet. | | `address.line` | string, maxLength 255, nullable | no | | | `address.city` | string, maxLength 50, nullable | no | | | `address.country` | string, minLength 3, maxLength 3, nullable | no | | | `contact` | object, nullable | no | Kontaktet e klientit: telefoni dhe email-i. Opsionale. | | `contact.phone` | string, maxLength 255, nullable | no | | | `contact.email` | string, maxLength 255, nullable | no | | | `customer_number` | string, maxLength 30, nullable | no | Numri juaj i klientit, nese e mbani nje te tille ne sistemin tuaj. | #### Example request ```bash curl -X POST 'https://fature.al/api/v2/clients' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "type": "company", "company": { "name": "Jane Doe", "category": "category", "id": { "type": "type", "value": "value" } }, "person": { "first_name": "Jane", "last_name": "Doe", "birthday": "2026-01-15T09:30:00Z", "id": { "type": "type", "value": "value" } }, "address": { "line": "line", "city": "Berlin", "country": "USx" }, "contact": { "phone": "+15551234567", "email": "jane@example.com" }, "customer_number": "CL-00412" }' ``` #### Responses **201** — Created | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.client` | object | | | `data.client.id` | integer | | | `data.client.type` | string | `company` or `person` | | `data.client.company` | object, nullable | Filled when `type` is `company`, null otherwise | | `data.client.company.name` | string, nullable | | | `data.client.company.category` | string, nullable | `business`, `bank` or `exchange`, or null when unclassified | | `data.client.company.id` | object | | | `data.client.company.id.type` | any | `nuis`, `vat` or `tax` on a company; `id`, `passport` or `social` on a person | | `data.client.company.id.value` | any | The identifier itself, null when the client has none recorded | | `data.client.person` | object, nullable | Filled when `type` is `person`, null otherwise | | `data.client.person.first_name` | string, nullable | | | `data.client.person.last_name` | string, nullable | | | `data.client.person.birthday` | string, nullable | Date of birth (YYYY-MM-DD) | | `data.client.person.id` | object | | | `data.client.person.id.type` | any | `nuis`, `vat` or `tax` on a company; `id`, `passport` or `social` on a person | | `data.client.person.id.value` | any | The identifier itself, null when the client has none recorded | | `data.client.address` | object | | | `data.client.address.line` | string, nullable | Street address | | `data.client.address.city` | string, nullable | | | `data.client.address.country` | string, nullable | ISO 3166-1 alpha-3 country code | | `data.client.contact` | object | | | `data.client.contact.phone` | string, nullable | | | `data.client.contact.email` | string, nullable | | | `data.client.customer_number` | string, nullable | Your own reference for this client, when one was given | | `data.client.verified` | boolean | Whether the identifier was confirmed against the fiscal register | | `data.client.created_at` | string, nullable | Creation timestamp, ISO 8601 | | `data.client.updated_at` | string, nullable | Last update timestamp, ISO 8601 | ```json { "status": true, "data": { "client": { "id": 1, "type": "type", "company": { "name": "Jane Doe", "category": "category", "id": { "type": "type", "value": "value" } }, "person": { "first_name": "Jane", "last_name": "Doe", "birthday": "birthday", "id": { "type": "type", "value": "value" } }, "address": { "line": "line", "city": "Berlin", "country": "US" }, "contact": { "phone": "+15551234567", "email": "jane@example.com" }, "customer_number": "customer number", "verified": true, "created_at": "created at", "updated_at": "updated at" } } } ``` **403** — Abonimi ka mbaruar, ose veprimi nuk lejohet per kete llogari. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **409** — Ekziston tashme nje regjistrim me te njejtat te dhena. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **422** — Te dhenat nuk kaluan validimin. Kjo pergjigje perdor fushen `success`, jo `status`. | Field | Type | Description | | --- | --- | --- | | `success` | boolean | Always false | | `message` | string | A single summary line, the same for every validation failure | | `errors` | object | The failing fields, each with the messages for it. Dotted keys point into nested objects and array items, e.g. `lines.0.quantity` | ```json { "success": true, "message": "Hello there", "errors": [] } ``` **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`. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **500** — Gabim i papritur ne server. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` ### GET /api/v2/clients/{id} Detajet e klientit (v2) Kthen klientin ne formatin e ri, me objekte te ndara: `company` ose `person` sipas `type`, plus `address` dhe `contact`. Eshte i njejti klient qe kthen edhe `v1`, vetem i strukturuar ndryshe. Nje klient i krijuar me `v1` lexohet ketu pa asnje hap tjeter. Full URL: `https://fature.al/api/v2/clients/{id}` API version: `v2`. Authentication: required (bearer token). #### Path parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `id` | integer | yes | ID e klientit. | #### Example request ```bash curl -X GET 'https://fature.al/api/v2/clients/42' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — OK | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.client` | object | | | `data.client.id` | integer | | | `data.client.type` | string | `company` or `person` | | `data.client.company` | object, nullable | Filled when `type` is `company`, null otherwise | | `data.client.company.name` | string, nullable | | | `data.client.company.category` | string, nullable | `business`, `bank` or `exchange`, or null when unclassified | | `data.client.company.id` | object | | | `data.client.company.id.type` | any | `nuis`, `vat` or `tax` on a company; `id`, `passport` or `social` on a person | | `data.client.company.id.value` | any | The identifier itself, null when the client has none recorded | | `data.client.person` | object, nullable | Filled when `type` is `person`, null otherwise | | `data.client.person.first_name` | string, nullable | | | `data.client.person.last_name` | string, nullable | | | `data.client.person.birthday` | string, nullable | Date of birth (YYYY-MM-DD) | | `data.client.person.id` | object | | | `data.client.person.id.type` | any | `nuis`, `vat` or `tax` on a company; `id`, `passport` or `social` on a person | | `data.client.person.id.value` | any | The identifier itself, null when the client has none recorded | | `data.client.address` | object | | | `data.client.address.line` | string, nullable | Street address | | `data.client.address.city` | string, nullable | | | `data.client.address.country` | string, nullable | ISO 3166-1 alpha-3 country code | | `data.client.contact` | object | | | `data.client.contact.phone` | string, nullable | | | `data.client.contact.email` | string, nullable | | | `data.client.customer_number` | string, nullable | Your own reference for this client, when one was given | | `data.client.verified` | boolean | Whether the identifier was confirmed against the fiscal register | | `data.client.created_at` | string, nullable | Creation timestamp, ISO 8601 | | `data.client.updated_at` | string, nullable | Last update timestamp, ISO 8601 | ```json { "status": true, "data": { "client": { "id": 1, "type": "type", "company": { "name": "Jane Doe", "category": "category", "id": { "type": "type", "value": "value" } }, "person": { "first_name": "Jane", "last_name": "Doe", "birthday": "birthday", "id": { "type": "type", "value": "value" } }, "address": { "line": "line", "city": "Berlin", "country": "US" }, "contact": { "phone": "+15551234567", "email": "jane@example.com" }, "customer_number": "customer number", "verified": true, "created_at": "created at", "updated_at": "updated at" } } } ``` **404** — Klienti nuk u gjet, ose nuk i perket kompanise suaj. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **500** — Gabim i papritur ne server. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` ### PATCH /api/v2/clients/{id} Perditeso klient (v2) I njejti trup si `POST`, me nje kufizim: - **`type` eshte i pandryshueshem.** Nje kompani nuk behet person dhe as e kunderta. Nese dergoni nje `type` te ndryshem nga ai ekzistues, kerkesa refuzohet me `422`. Full URL: `https://fature.al/api/v2/clients/{id}` API version: `v2`. Authentication: required (bearer token). #### Path parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `id` | integer | yes | ID e klientit. | #### Body parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `type` | string | yes | Lloji i klientit, i cili vendos se cili objekt plotesohet: `company` ose `person`. Ne editim eshte i pandryshueshem, prandaj nje `type` i ndryshem nga ai ekzistues refuzohet me `422`. | | `company` | object | yes | Required depending on type. | | `company.name` | string, maxLength 255, nullable | yes | Required depending on type. | | `company.category` | string, nullable | no | | | `company.id` | object | yes | Required depending on type. | | `company.id.type` | string | yes | Required when company.id is present. | | `company.id.value` | string, maxLength 20 | yes | Required when company.id is present. | | `person` | object | yes | Required depending on type. | | `person.first_name` | string, maxLength 255, nullable | yes | Required depending on type. | | `person.last_name` | string, maxLength 255, nullable | yes | Required depending on type. | | `person.birthday` | string, nullable | no | | | `person.id` | object | yes | Required depending on type. | | `person.id.type` | string | yes | Required when person.id is present. | | `person.id.value` | string, maxLength 255 | yes | Required when person.id is present. | | `address` | object, nullable | no | Adresa e klientit. Opsionale, dhe e njejta per te dy llojet. | | `address.line` | string, maxLength 255, nullable | no | | | `address.city` | string, maxLength 50, nullable | no | | | `address.country` | string, minLength 3, maxLength 3, nullable | no | | | `contact` | object, nullable | no | Kontaktet e klientit: telefoni dhe email-i. Opsionale. | | `contact.phone` | string, maxLength 255, nullable | no | | | `contact.email` | string, maxLength 255, nullable | no | | | `customer_number` | string, maxLength 30, nullable | no | Numri juaj i klientit, nese e mbani nje te tille ne sistemin tuaj. | #### Example request ```bash curl -X PATCH 'https://fature.al/api/v2/clients/42' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "type": "company", "company": { "name": "Jane Doe", "category": "category", "id": { "type": "type", "value": "value" } }, "person": { "first_name": "Jane", "last_name": "Doe", "birthday": "2026-01-15T09:30:00Z", "id": { "type": "type", "value": "value" } }, "address": { "line": "line", "city": "Berlin", "country": "USx" }, "contact": { "phone": "+15551234567", "email": "jane@example.com" }, "customer_number": "CL-00412" }' ``` #### Responses **200** — OK | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.client` | object | | | `data.client.id` | integer | | | `data.client.type` | string | `company` or `person` | | `data.client.company` | object, nullable | Filled when `type` is `company`, null otherwise | | `data.client.company.name` | string, nullable | | | `data.client.company.category` | string, nullable | `business`, `bank` or `exchange`, or null when unclassified | | `data.client.company.id` | object | | | `data.client.company.id.type` | any | `nuis`, `vat` or `tax` on a company; `id`, `passport` or `social` on a person | | `data.client.company.id.value` | any | The identifier itself, null when the client has none recorded | | `data.client.person` | object, nullable | Filled when `type` is `person`, null otherwise | | `data.client.person.first_name` | string, nullable | | | `data.client.person.last_name` | string, nullable | | | `data.client.person.birthday` | string, nullable | Date of birth (YYYY-MM-DD) | | `data.client.person.id` | object | | | `data.client.person.id.type` | any | `nuis`, `vat` or `tax` on a company; `id`, `passport` or `social` on a person | | `data.client.person.id.value` | any | The identifier itself, null when the client has none recorded | | `data.client.address` | object | | | `data.client.address.line` | string, nullable | Street address | | `data.client.address.city` | string, nullable | | | `data.client.address.country` | string, nullable | ISO 3166-1 alpha-3 country code | | `data.client.contact` | object | | | `data.client.contact.phone` | string, nullable | | | `data.client.contact.email` | string, nullable | | | `data.client.customer_number` | string, nullable | Your own reference for this client, when one was given | | `data.client.verified` | boolean | Whether the identifier was confirmed against the fiscal register | | `data.client.created_at` | string, nullable | Creation timestamp, ISO 8601 | | `data.client.updated_at` | string, nullable | Last update timestamp, ISO 8601 | ```json { "status": true, "data": { "client": { "id": 1, "type": "type", "company": { "name": "Jane Doe", "category": "category", "id": { "type": "type", "value": "value" } }, "person": { "first_name": "Jane", "last_name": "Doe", "birthday": "birthday", "id": { "type": "type", "value": "value" } }, "address": { "line": "line", "city": "Berlin", "country": "US" }, "contact": { "phone": "+15551234567", "email": "jane@example.com" }, "customer_number": "customer number", "verified": true, "created_at": "created at", "updated_at": "updated at" } } } ``` **403** — Abonimi ka mbaruar, ose veprimi nuk lejohet per kete llogari. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **404** — Klienti nuk u gjet, ose nuk i perket kompanise suaj. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **409** — Ekziston tashme nje klient me te njejtat te dhena. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **422** — Te dhenat nuk kaluan validimin. Kjo pergjigje perdor fushen `success`, jo `status`. Perfshin edhe rastin kur `type` ndryshon nga ai ekzistues. | Field | Type | Description | | --- | --- | --- | | `success` | boolean | Always false | | `message` | string | A single summary line, the same for every validation failure | | `errors` | object | The failing fields, each with the messages for it. Dotted keys point into nested objects and array items, e.g. `lines.0.quantity` | ```json { "success": true, "message": "Hello there", "errors": [] } ``` **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`. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **500** — Gabim i papritur ne server. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` ## Ping (v1) Nje thirrje qe nuk prek asgje, per te provuar lidhjen dhe token-in. ### GET /api/v1/ping Ping Kontrollo nese API eshte aktiv. Kthen timestamp dhe IP. Full URL: `https://fature.al/api/v1/ping` API version: `v1`. Authentication: required (bearer token). #### Example request ```bash curl -X GET 'https://fature.al/api/v1/ping' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — OK | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.pong` | integer | | | `data.ip` | array | | ```json { "status": true, "data": { "pong": 1, "ip": [ "ip" ] } } ``` ## Regjistrimi (v1) Ne kete koleksion perfshihen endpoint-et qe ju lejojne te regjistroni nje kompani ne fature.al dhe te plotesoni te dhenat e nevojshme per ta bere gati per leshimin e faturave. **Workflow:** 1. Regjistroni kompanine (`POST /register`). 2. Perditesoni njesine e biznesit (branch) me `businessUnitCode`, i cili merret nga self-care dhe ruhet te njesia e biznesit. 3. Perditesoni perdoruesin me `operatorCode`, i cili merret nga self-care. 4. Ngarkoni certifikaten elektronike se bashku me fjalekalimin perkates, te cilin e merrni nga e-Albania. 5. Ruani llogarite bankare qe kompania do te perdore per faturat pa para ne dore ose per faturat elektronike (eInvoice). **Nese kompania do te leshoje fatura me para ne dore:** 6. Ruani pajisjen fiskale (fiscal device) dhe kodi i kthyer `fiscalTcrCode` duhet te ruhet te perdoruesi qe do te leshoje keto lloj faturash, njesoj si te pika 3. **Shtimi i perdoruesve te rinj:** Mund te shtoni me shume perdorues nese eshte e nevojshme, por per secilin duhet te plotesohen: - Nje email unik, p.sh. `dicka-unike@domaini-juaj.com` - Pajisja fiskale, sipas pikes 6 - Kodi i operatorit, sipas pikes 3 > **Shenim:** Cdo perdorues do te operoje me `api_token`-in e vet, te cilin e merr pasi te regjistrohet. **Sandbox (vetem ne instancen DEMO):** Per te testuar te gjithe flow-in e onboarding-ut pa krijuar nje kompani te re, perdorni NIPT-in sandbox `L62221018T` ne thirrjen `POST /register`. Sjellja: - Nuk krijohet kompani e re; perdoruesi dhe njesia e biznesit krijohen nen kompanine ekzistuese sandbox `L62221018T`. - Email-i qe dergoni shtohet me nje sufiks unik (`+sandbox-XXXXXXXX`) ne DB, keshtu qe mund ta riperseritni `POST /register` me te njejtin email pa goditur unique-key. - `POST /on-boarding/certificate` ne DEMO kthen `success` per cdo certifikate (`.p12` ose `.pfx`) dhe cdo fjalekalim, pa e validuar fjalekalimin apo NIPT-in brenda certifikates. Data `expiresAt` qe kthehet eshte +1 vit nga sot. - Hapat e tjere (`branch`, `user`, `bank-account`, `fiscal-device`) ekzekutohen normalisht ne kompanine sandbox. Ne `PRODUCTION` keto sjellje sandbox jane jo-aktive. NIPT `L62221018T` trajtohet si cdo NIPT tjeter. ### GET /api/v1/register Ping (Register) Kontrollo nese API eshte aktiv per regjistrimin e kompanive. Full URL: `https://fature.al/api/v1/register` API version: `v1`. Authentication: required (bearer token). #### Example request ```bash curl -X GET 'https://fature.al/api/v1/register' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — Kur llogaria juaj nuk eshte e autorizuar per onboarding, pergjigja kthehet me HTTP 200 dhe `status: false`. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` ### POST /api/v1/register 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. Full URL: `https://fature.al/api/v1/register` API version: `v1`. Authentication: required (bearer token). #### Body parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `name` | string, maxLength 255 | yes | Emri tregtar i kompanise qe po regjistrohet. | | `address` | string, maxLength 255 | yes | Adresa e selise se kompanise, ashtu sic eshte regjistruar. | | `administrator` | string, maxLength 255 | yes | Emri i administratorit te kompanise. | | `phone` | string, maxLength 50 | yes | Telefoni i kontaktit i kompanise. | | `email` | string, maxLength 255 | yes | Email-i i perdoruesit te pare, ai qe do te administroje llogarine. | | `issuerInVat` | boolean, nullable | no | A eshte kompania e regjistruar per TVSH. Percakton nese faturat dalin me TVSH. | | `lastNonCashEInvoiceNumber` | string, maxLength 50, nullable | no | Numri i fundit i perdorur ne sistemin e meparshem, qe numerimi te vazhdoje nga aty dhe te mos rifilloje nga 1. | #### Example request ```bash curl -X POST 'https://fature.al/api/v1/register' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "name": "Ei3 Software Solution shpk", "address": "Rruga e Kavajes 12, Tirane", "administrator": "Festim Peposhi", "phone": "+355 69 000 0000", "email": "admin@example.com", "issuerInVat": true, "lastNonCashEInvoiceNumber": 412 }' ``` #### 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`. **201** — Created | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.user` | object | | | `data.user.token` | string | | | `data.user.id` | integer | | | `data.branch` | object | | | `data.branch.id` | integer | | | `data.branch.name` | string | | ```json { "status": true, "data": { "user": { "token": "a1b2c3d4e5f6", "id": 1 }, "branch": { "id": 1, "name": "Jane Doe" } } } ``` **422** — Te dhenat nuk kaluan validimin. Kjo pergjigje perdor fushen `success`, jo `status`. | Field | Type | Description | | --- | --- | --- | | `success` | boolean | Always false | | `message` | string | A single summary line, the same for every validation failure | | `errors` | object | The failing fields, each with the messages for it. Dotted keys point into nested objects and array items, e.g. `lines.0.quantity` | ```json { "success": true, "message": "Hello there", "errors": [] } ``` ### POST /api/v1/on-boarding/branch/{id} Perditeso njesine e biznesit (Branch) Perditesoni emrin, adresen, administratorin dhe kodin e biznesit per nje njesi biznesi ekzistuese. Kodi i biznesit (businessUnitCode) eshte i domosdoshem per leshimin e faturave. Full URL: `https://fature.al/api/v1/on-boarding/branch/{id}` API version: `v1`. Authentication: required (bearer token). #### Path parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `id` | integer | yes | ID e njesise se biznesit. | #### Example request ```bash curl -X POST 'https://fature.al/api/v1/on-boarding/branch/12' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — Kur njesia nuk gjendet ose ruajtja deshton, pergjigja kthehet me HTTP 200 dhe `status: false`. **201** — Created | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.branch` | object | | | `data.branch.id` | integer | | | `data.branch.name` | string | | | `data.branch.businessUnitCode` | string | | ```json { "status": true, "data": { "branch": { "id": 1, "name": "Jane Doe", "businessUnitCode": "businessUnitCode" } } } ``` ### POST /api/v1/on-boarding/user/{id} Perditeso perdoruesin Perditesoni emrin, kodin e operatorit, pajisjen fiskale dhe njesine e biznesit per nje perdorues ekzistues. Kodi i operatorit eshte i domosdoshem per leshimin e faturave. Full URL: `https://fature.al/api/v1/on-boarding/user/{id}` API version: `v1`. Authentication: required (bearer token). #### Path parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `id` | integer | yes | ID e perdoruesit. | #### Example request ```bash curl -X POST 'https://fature.al/api/v1/on-boarding/user/7' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — Kur perdoruesi nuk gjendet ose ruajtja deshton, pergjigja kthehet me HTTP 200 dhe `status: false`. **201** — Created | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.user` | object | | | `data.user.id` | integer | | | `data.user.name` | string | | | `data.user.operatorCode` | string | | ```json { "status": true, "data": { "user": { "id": 1, "name": "Jane Doe", "operatorCode": "operatorCode" } } } ``` ### POST /api/v1/on-boarding/certificate Ngarko certifikaten elektronike Ngarkoni certifikaten elektronike (.p12 ose .pfx) per kompanine. 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. Full URL: `https://fature.al/api/v1/on-boarding/certificate` API version: `v1`. Authentication: required (bearer token). #### Body parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `certificate_file` | string, nullable | no | Certifikata elektronike si skedar, ne formatin PFX. Me te nenshkruhen faturat qe dergohen ne fiskalizim, prandaj pa nje certifikate te vlefshme nuk leshohet dot fature. | | `password` | string, nullable | no | Fjalekalimi i skedarit PFX. Pa te certifikata nuk hapet dot dhe nenshkrimi deshton. | #### Example request ```bash curl -X POST 'https://fature.al/api/v1/on-boarding/certificate' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "certificate_file": "certificate file", "password": "correct-horse-battery" }' ``` #### Responses **200** — Kur fjalekalimi eshte i gabuar ose NIPT-i i certifikates nuk perputhet me kompanine, pergjigja kthehet me HTTP 200 dhe `status: false`. **201** — Created | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.cert` | object | | | `data.cert.expiresAt` | string | | ```json { "status": true, "data": { "cert": { "expiresAt": "expiresAt" } } } ``` **422** — Te dhenat nuk kaluan validimin. Kjo pergjigje perdor fushen `success`, jo `status`. | Field | Type | Description | | --- | --- | --- | | `success` | boolean | Always false | | `message` | string | A single summary line, the same for every validation failure | | `errors` | object | The failing fields, each with the messages for it. Dotted keys point into nested objects and array items, e.g. `lines.0.quantity` | ```json { "success": true, "message": "Hello there", "errors": [] } ``` ### POST /api/v1/on-boarding/bank-account Krijo llogari bankare Krijoni nje llogari bankare per kompanine. Llogaria bankare shfaqet ne faturat elektronike dhe jo-cash si informacion pagese per klientin. Full URL: `https://fature.al/api/v1/on-boarding/bank-account` API version: `v1`. Authentication: required (bearer token). #### Body parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `name` | string, nullable | no | Emri i bankes, ai qe shfaqet ne fature krahas IBAN-it. | | `holder` | string, nullable | no | Mbajtesi i llogarise, zakonisht emri i kompanise. | | `iban` | string, nullable | no | IBAN-i i llogarise, ai qe shfaqet ne fature qe klienti te paguaje. | | `swift` | string, nullable | no | Kodi SWIFT/BIC i bankes, i nevojshem per pagesa nga jashte. | | `currency` | string, nullable | no | Monedha e llogarise. Nje llogari mban nje monedhe te vetme. | | `notes` | string, nullable | no | Shenime qe shoqerojne llogarine ne fature. | #### Example request ```bash curl -X POST 'https://fature.al/api/v1/on-boarding/bank-account' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "name": "BKT", "holder": "Ei3 Software Solution shpk", "iban": "AL35202111090000000001234567", "swift": "NCBAALTX", "currency": "ALL", "notes": "notes" }' ``` #### Responses **200** — Kur ruajtja e llogarise deshton, pergjigja kthehet me HTTP 200 dhe `status: false`. **201** — Created | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.bankAccount` | object | | | `data.bankAccount.id` | integer | | | `data.bankAccount.iban` | string | | ```json { "status": true, "data": { "bankAccount": { "id": 1, "iban": "iban" } } } ``` **422** — Te dhenat nuk kaluan validimin. Kjo pergjigje perdor fushen `success`, jo `status`. | Field | Type | Description | | --- | --- | --- | | `success` | boolean | Always false | | `message` | string | A single summary line, the same for every validation failure | | `errors` | object | The failing fields, each with the messages for it. Dotted keys point into nested objects and array items, e.g. `lines.0.quantity` | ```json { "success": true, "message": "Hello there", "errors": [] } ``` ### POST /api/v1/on-boarding/fiscal-device 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. Full URL: `https://fature.al/api/v1/on-boarding/fiscal-device` API version: `v1`. Authentication: required (bearer token). #### Body parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `branchId` | integer | yes | ID e njesise se biznesit ku ndodhet pajisja, ashtu sic ju ktheu `POST /on-boarding/branch`. Cdo TCR i perket nje njesie te vetme. | | `name` | string, maxLength 255 | yes | Emri i pajisjes fiskale, ai qe e dallon nga te tjerat ne te njejten njesi. | | `fromDate` | string | yes | Data nga e cila pajisja fillon te leshoje fatura, ne formatin `YYYY-MM-DD`. | | `toDate` | string, nullable | no | Data deri kur pajisja eshte aktive. Pa te, pajisja mbetet aktive pa afat. | #### Example request ```bash curl -X POST 'https://fature.al/api/v1/on-boarding/fiscal-device' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "branchId": 12, "name": "Arka 1", "fromDate": "2026-01-01", "toDate": "2026-12-31" }' ``` #### Responses **200** — Kur regjistrimi i pajisjes ne fiskalizim deshton, pergjigja kthehet me HTTP 200 dhe `status: false`. **201** — Created | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.device` | object | | | `data.device.fiscalTcrCode` | string | | ```json { "status": true, "data": { "device": { "fiscalTcrCode": "fiscalTcrCode" } } } ``` **422** — Te dhenat nuk kaluan validimin. Kjo pergjigje perdor fushen `success`, jo `status`. | Field | Type | Description | | --- | --- | --- | | `success` | boolean | Always false | | `message` | string | A single summary line, the same for every validation failure | | `errors` | object | The failing fields, each with the messages for it. Dotted keys point into nested objects and array items, e.g. `lines.0.quantity` | ```json { "success": true, "message": "Hello there", "errors": [] } ``` ### POST /api/v1/on-boarding/branch 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. Full URL: `https://fature.al/api/v1/on-boarding/branch` API version: `v1`. Authentication: required (bearer token). #### Body parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `name` | string, maxLength 255 | yes | Emri i njesise se biznesit, ai qe del ne fature. | | `type` | string | yes | Lloji i njesise: `main` per seline qendrore, `secondary` per nje seli dytesore. | | `administrator` | string, maxLength 255 | yes | Emri i personit pergjegjes per njesine. | | `address` | string, maxLength 255 | yes | Adresa e njesise, e cila shkon ne sistemin fiskal. | | `businessUnitCode` | string, maxLength 50, nullable | no | Kodi i njesise se biznesit nga tatimet. Pa te, njesia merr nje kod te ri. | #### Example request ```bash curl -X POST 'https://fature.al/api/v1/on-boarding/branch' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "name": "Dega Tirane", "type": "main", "administrator": "Festim Peposhi", "address": "Rruga e Kavajes 12, Tirane", "businessUnitCode": "bb123bb123" }' ``` #### Responses **200** — Kur krijimi deshton per nje arsye tjeter, pergjigja kthehet me HTTP 200 dhe `status: false`. **201** — Created | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.branch` | object | | | `data.branch.id` | integer | | | `data.branch.name` | string | | | `data.branch.type` | string | | | `data.branch.administrator` | string | | | `data.branch.address` | string | | | `data.branch.businessUnitCode` | string | | ```json { "status": true, "data": { "branch": { "id": 1, "name": "Jane Doe", "type": "type", "administrator": "administrator", "address": "1 Example Street", "businessUnitCode": "businessUnitCode" } } } ``` **403** — Abonimi nuk lejon me njesi biznesi. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **409** — Kompania ka tashme nje seli qendrore. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **422** — Te dhenat nuk kaluan validimin. Kjo pergjigje perdor fushen `success`, jo `status`. | Field | Type | Description | | --- | --- | --- | | `success` | boolean | Always false | | `message` | string | A single summary line, the same for every validation failure | | `errors` | object | The failing fields, each with the messages for it. Dotted keys point into nested objects and array items, e.g. `lines.0.quantity` | ```json { "success": true, "message": "Hello there", "errors": [] } ``` ### POST /api/v1/on-boarding/user Krijo perdorues te ri Krijoni nje perdorues te ri per kompanine me kodin e operatorit dhe pajisjen fiskale. Kthen token API per kete perdorues. Full URL: `https://fature.al/api/v1/on-boarding/user` API version: `v1`. Authentication: required (bearer token). #### Example request ```bash curl -X POST 'https://fature.al/api/v1/on-boarding/user' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: 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`. **201** — Created | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.user` | object | | | `data.user.id` | integer | | | `data.user.name` | string | | | `data.user.operatorCode` | string | | | `data.user.token` | string | | ```json { "status": true, "data": { "user": { "id": 1, "name": "Jane Doe", "operatorCode": "operatorCode", "token": "a1b2c3d4e5f6" } } } ``` ## Faturat (v1) Leshimi i faturave dhe gjithcka qe vjen pas tij: cash, jo-cash, e-fature, porosi, permbledhese dhe bllok jo-cash, si dhe anulimi, detajet dhe PDF-ja. Trupi i kerkeses ndryshon nga njeri lloj tek tjetri me shume nga sa duket, prandaj e njejta fature e derguar tek dy endpoint-e refuzohet nga njeri prej tyre. Cili endpoint leshon cilin dokument shpjegohet ne faqen Llojet e faturave. ### GET /api/v1/invoice Lista e faturave Merrni listen e faturave me filtrim dhe faqosje. Full URL: `https://fature.al/api/v1/invoice` API version: `v1`. Authentication: required (bearer token). #### Query parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `limit` | integer | no | Numri i faturave per faqe. Defaults to `20`. | | `offset` | integer | no | Nga cila fature te fillohet. Defaults to `0`. | | `type` | string | 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` | string | no | Data e fillimit (YYYY-MM-DD). | | `toDate` | string | no | Data e perfundimit (YYYY-MM-DD). | | `query` | string | no | Kerko sipas numrit te fatures, emrit te bleresit ose NIPT-it. | #### Example request ```bash curl -X GET 'https://fature.al/api/v1/invoice' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — OK | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.items` | array | | | `data.items[].id` | integer | Fatureal invoice id | | `data.items[].number` | string, nullable | Fiscal invoice number | | `data.items[].type` | string | Invoice type, e.g. NONCASH | | `data.items[].issue_date` | string | Issue date (YYYY-MM-DD) | | `data.items[].due_date` | string | Payment due date (YYYY-MM-DD) | | `data.items[].delivery_date` | string | Delivery/supply-end date (YYYY-MM-DD) | | `data.items[].created_at` | string, nullable | Creation timestamp (YYYY-MM-DD HH:MM:SS) | | `data.items[].supply_start_date` | string, nullable | Supply period start (YYYY-MM-DD) | | `data.items[].supply_end_date` | string, nullable | Supply period end (YYYY-MM-DD) | | `data.items[].client` | object | | | `data.items[].client.name` | string | Full name (or company name) | | `data.items[].client.id` | object | | | `data.items[].client.id.type` | any | Identifier type, e.g. NUIS, ID, PASSPORT | | `data.items[].client.id.id` | any | The identifier value | | `data.items[].client.address` | object | | | `data.items[].client.address.street` | any | | | `data.items[].client.address.city` | any | | | `data.items[].client.address.country` | any | ISO 3166-1 alpha-3 country code, defaults to ALB | | `data.items[].amount` | object | | | `data.items[].amount.currency` | string | ISO 4217 currency code | | `data.items[].amount.exchange_rate` | number, nullable | Rate to the local currency, null when the invoice is already in ALL | | `data.items[].amount.gross` | number | Gross total, already reduced by the invoice discount | | `data.items[].amount.net` | number | Net total, already reduced by the invoice discount | | `data.items[].amount.vat` | number | | | `data.items[].amount.discount` | number | The invoice-level discount, net-denominated: how much net came off the whole invoice. Line discounts are not in here; those are per line, on `lines[].discount`. Zero when the invoice carries no invoice discount | | `data.items[].amount.net_all` | number | Net converted to the local currency (ALL) | | `data.items[].amount.gross_all` | number | Gross converted to the local currency (ALL) | | `data.items[].amount.vat_all` | number | VAT converted to the local currency (ALL) | | `data.items[].amount.discount_all` | number | Invoice-level discount converted to the local currency (ALL) | | `data.items[].amount.local_currency` | object, nullable | Present only on a foreign-currency invoice | | `data.items[].payment_method` | string, nullable | | | `data.items[].payment` | object | | | `data.items[].payment.state` | string | PAID, PARTIALLY_PAID or UNPAID | | `data.items[].payment.amount_paid` | number | Amount received so far, in the invoice currency | | `data.items[].payment.amount_left` | number | Gross total minus what has been received, in the invoice currency | | `data.items[].bank_account` | object, nullable | Bank account printed on the invoice, or null | | `data.items[].bank_account.id` | integer | | | `data.items[].bank_account.bank_name` | any | | | `data.items[].bank_account.iban` | any | | | `data.items[].bank_account.swift` | any | | | `data.items[].bank_account.currency` | any | ISO 4217 currency code | | `data.items[].bank_account.notes` | any | | | `data.items[].notes` | string, nullable | | | `data.items[].iic` | string, nullable | IIC / NSLF | | `data.items[].fic` | string, nullable | FIC / NIVF | | `data.items[].eic` | string, nullable | EIC, for e-invoices | | `data.items[].doc_type` | string, nullable | UBL document type: 380 invoice, 381 credit note, 383 debit note. Null on a plain fiscal invoice | | `data.items[].process` | string, nullable | UBL ProfileID: P1 for a sale, P9 for a correction. Set on e-invoices | | `data.items[].self_issue_type` | string, nullable | Self-issuance type, when the invoice is self-issued | | `data.items[].reversed_at` | string, nullable | When the invoice was reversed (YYYY-MM-DD HH:MM:SS), or null | | `data.items[].reversed_by` | integer, nullable | Id of the invoice this one reverses, or null | | `data.items[].pdf_url` | string | Direct download URL for the invoice PDF | | `data.items[].reverse_charge` | boolean | | | `data.items[].periodic_invoice` | boolean | | | `data.pagination` | object | | | `data.pagination.records` | integer | | | `data.pagination.limit` | integer | | | `data.pagination.offset` | integer | | | `data.pagination.type` | string, nullable | | | `data.pagination.query` | string, nullable | | ```json { "status": true, "data": { "items": [ { "id": 1, "number": "number", "type": "type", "issue_date": "issue date", "due_date": "due date", "delivery_date": "delivery date", "created_at": "created at", "supply_start_date": "supply start date", "supply_end_date": "supply end date", "client": { "name": "Jane Doe", "id": { "type": "type", "id": 1 }, "address": { "street": "street", "city": "Berlin", "country": "US" } }, "amount": { "currency": "USD", "exchange_rate": 19.99, "gross": 19.99, "net": 19.99, "vat": 19.99, "discount": 3, "net_all": 19.99, "gross_all": 19.99, "vat_all": 19.99, "discount_all": 3, "local_currency": [] }, "payment_method": "payment method", "payment": { "state": "state", "amount_paid": 4200, "amount_left": 4200 }, "bank_account": { "id": 1, "bank_name": "Jane Doe", "iban": "iban", "swift": "swift", "currency": "USD", "notes": "notes" }, "notes": "notes", "iic": "iic", "fic": "fic", "eic": "eic", "doc_type": "doc type", "process": "process", "self_issue_type": "self issue type", "reversed_at": "reversed at", "reversed_by": 1, "pdf_url": "https://example.com", "reverse_charge": true, "periodic_invoice": true } ], "pagination": { "records": 1, "limit": 25, "offset": 0, "type": "type", "query": "query" } } } ``` **422** — Formati i datave nuk eshte YYYY-MM-DD. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **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`. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **500** — Gabim i papritur ne server. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` ### POST /api/v1/invoice/bulk-noncash Krijo fatura pa para ne dore ne bllok (Bulk NonCash) Leshon shume fatura jo-cash me nje kerkese te vetme, e menduar per faturim periodik. Pergjigja eshte nje objekt me nje hyrje per cdo `internalId`, dhe statusi mbetet `200` edhe kur ndonje fature brenda bllokut deshton. Prandaj: - mos u mbeshtetni tek kodi HTTP per te ditur nese gjithcka shkoi mire; - kontrolloni `status` brenda cdo hyrjeje me vete; - riprovoni vetem `internalId` qe deshtuan, jo te gjithe bllokun. Full URL: `https://fature.al/api/v1/invoice/bulk-noncash` API version: `v1`. Authentication: required (bearer token). #### Body parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `invoices` | array | yes | Faturat qe do te leshohen, secila me te njejtat fusha si trupi i `POST /invoice/noncash`, `internalId` perfshire. Nuk ka kufi ne numrin e tyre, por endpoint-i lejon vetem 3 kerkesa ne minute, prandaj dergoni blloqe te medha ne vend te shume blloqeve te vogla. | #### Example request ```bash curl -X POST 'https://fature.al/api/v1/invoice/bulk-noncash' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "invoices": [ "invoices" ] }' ``` #### 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. **201** — Created ```json [] ``` ### POST /api/v1/invoice/cancel-by-internal-id/{internalId} Anulo fature sipas Internal ID Anulon faturen duke perdorur ID-ne tuaj interne qe keni derguar kur keni krijuar faturen. Sillet njesoj si anulimi sipas ID, vetem se e gjen faturen me numrin tuaj: - pa trup anulohet e gjithe fatura; - me `lines` anulohet vetem nje pjese, e mundur **vetem per faturat Cash**; - rreshtat duhet te perputhen ne `product_code` dhe `product_name`, dhe sasia vetem ulet; - nje fature me zbritje mbi te gjithe faturen anulohet vetem e plote. Perdoreni kur nuk doni te mbani `id` e fature.al prane shitjes tuaj. Full URL: `https://fature.al/api/v1/invoice/cancel-by-internal-id/{internalId}` API version: `v1`. Authentication: required (bearer token). #### Path parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `internalId` | string | yes | ID juaj interne, e derguar kur u krijua fatura. | #### Body parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `lines` | array | no | Rreshtat qe anulohen. Pa te anulohet e gjithe fatura; me te anulohet vetem pjesa e derguar, e mundur vetem per faturat Cash. Cdo rresht duhet te ekzistoje ne faturen origjinale me te njejtin `product_code` dhe `product_name`, dhe sasia mund vetem te ulet. Nje fature qe u leshua me zbritje mbi te gjithe faturen nuk pranon anulim te pjesshem: dergojeni kerkesen pa `lines` qe te anulohet e plote. | | `lines[].product_name` | string | yes | | | `lines[].product_code` | string | yes | | | `lines[].quantity` | number | yes | | | `lines[].price` | number, nullable | no | | #### Example request ```bash curl -X POST 'https://fature.al/api/v1/invoice/cancel-by-internal-id/CASH-001' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "lines": [ { "product_name": "Jane Doe", "product_code": "product code", "quantity": 2, "price": 1999 } ] }' ``` #### Responses **201** — Created | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.invoice` | object | | | `data.invoice.id` | integer | Fatureal invoice id. Store it next to your own internalId | | `data.invoice.number` | string, nullable | Fiscal invoice number | | `data.invoice.iic` | string, nullable | IIC / NSLF | | `data.invoice.fic` | string, nullable | FIC / NIVF. Null while the invoice waits for a deferred fiscalisation | | `data.invoice.tcrCode` | string, nullable | TCR code of the fiscal device that issued it | | `data.invoice.businessCode` | string, nullable | Business unit code the invoice was issued under | | `data.invoice.operatorCode` | string, nullable | Operator code the invoice was issued under | | `data.invoice.fiscalizedAt` | string | Creation timestamp (YYYY-MM-DD HH:MM:SS) | | `data.invoice.verifyURL` | string, nullable | Government verification URL, the one behind the QR code | | `data.invoice.pdf` | string | Direct download URL for the document. On an e-invoice that already has an EIC this points at the official e-invoice PDF instead of ours | | `data.invoice.eic` | string, nullable | EIC. The key is present only on an e-invoice that already has one, so treat it as absent rather than null on every other invoice | ```json { "status": true, "data": { "invoice": { "id": 1, "number": "number", "iic": "iic", "fic": "fic", "tcrCode": "tcrCode", "businessCode": "businessCode", "operatorCode": "operatorCode", "fiscalizedAt": "fiscalizedAt", "verifyURL": "https://example.com", "pdf": "pdf", "eic": "eic" } } } ``` **404** — Fatura nuk u gjet, ose nuk i perket kompanise suaj. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **422** — Fatura nuk mund te anulohet ne gjendjen e saj aktuale. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **429** — Kufiri i anulimeve u arrit. Pergjigja kthen vetem `message` bashke me header-in `Retry-After`. | Field | Type | Description | | --- | --- | --- | | `message` | string | | ```json { "message": "Hello there" } ``` **500** — Gabim i papritur ne server. Perfshin rastin kur anulimi nuk u regjistrua ne fiskalizim. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` ### POST /api/v1/invoice/cancel/{id} Anulo fature sipas ID Anulon faturen dhe krijon regjistrim fiskal anulimi ne sistemin e tatimeve. ## I plote ose i pjesshem | Trupi | Cfare ndodh | | --- | --- | | bosh | Anulohet e gjithe fatura | | me `lines` | Anulohet vetem pjesa e derguar, **vetem per faturat Cash** | ## Rregullat e anulimit te pjesshem - cdo rresht duhet te ekzistoje ne faturen origjinale me te njejtin `product_code` dhe `product_name`; - 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; - nje fature me zbritje mbi te gjithe faturen (`invoice_discount_type`) nuk anulohet dot pjeserisht. Zbritja eshte shperndare mbi te gjitha normat e TVSH-se se dokumentit, keshtu qe nje pjese e rreshtave nuk e mban dot pjesen e vet pa e gabuar TVSH-ne. Dergoni kerkesen pa `lines` qe te anulohet e plote. Fatura origjinale mbetet e hapur per anulime te metejshme derisa ato ta mbulojne te gjithen, dhe vetem atehere shenohet si e anuluar. Full URL: `https://fature.al/api/v1/invoice/cancel/{id}` API version: `v1`. Authentication: required (bearer token). #### Path parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `id` | integer | yes | ID e fatures ne fature.al. | #### Body parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `lines` | array | no | Rreshtat qe anulohen. Pa te anulohet e gjithe fatura; me te anulohet vetem pjesa e derguar, e mundur vetem per faturat Cash. Cdo rresht duhet te ekzistoje ne faturen origjinale me te njejtin `product_code` dhe `product_name`, dhe sasia mund vetem te ulet. Nje fature qe u leshua me zbritje mbi te gjithe faturen nuk pranon anulim te pjesshem: dergojeni kerkesen pa `lines` qe te anulohet e plote. | | `lines[].product_name` | string | yes | | | `lines[].product_code` | string | yes | | | `lines[].quantity` | number | yes | | | `lines[].price` | number, nullable | no | | #### Example request ```bash curl -X POST 'https://fature.al/api/v1/invoice/cancel/403' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "lines": [ { "product_name": "Jane Doe", "product_code": "product code", "quantity": 2, "price": 1999 } ] }' ``` #### Responses **201** — Created | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.invoice` | object | | | `data.invoice.id` | integer | Fatureal invoice id. Store it next to your own internalId | | `data.invoice.number` | string, nullable | Fiscal invoice number | | `data.invoice.iic` | string, nullable | IIC / NSLF | | `data.invoice.fic` | string, nullable | FIC / NIVF. Null while the invoice waits for a deferred fiscalisation | | `data.invoice.tcrCode` | string, nullable | TCR code of the fiscal device that issued it | | `data.invoice.businessCode` | string, nullable | Business unit code the invoice was issued under | | `data.invoice.operatorCode` | string, nullable | Operator code the invoice was issued under | | `data.invoice.fiscalizedAt` | string | Creation timestamp (YYYY-MM-DD HH:MM:SS) | | `data.invoice.verifyURL` | string, nullable | Government verification URL, the one behind the QR code | | `data.invoice.pdf` | string | Direct download URL for the document. On an e-invoice that already has an EIC this points at the official e-invoice PDF instead of ours | | `data.invoice.eic` | string, nullable | EIC. The key is present only on an e-invoice that already has one, so treat it as absent rather than null on every other invoice | ```json { "status": true, "data": { "invoice": { "id": 1, "number": "number", "iic": "iic", "fic": "fic", "tcrCode": "tcrCode", "businessCode": "businessCode", "operatorCode": "operatorCode", "fiscalizedAt": "fiscalizedAt", "verifyURL": "https://example.com", "pdf": "pdf", "eic": "eic" } } } ``` **404** — Fatura nuk u gjet, ose nuk i perket kompanise suaj. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **422** — Fatura nuk mund te anulohet ne gjendjen e saj aktuale. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **429** — Kufiri i anulimeve u arrit. Pergjigja kthen vetem `message` bashke me header-in `Retry-After`. | Field | Type | Description | | --- | --- | --- | | `message` | string | | ```json { "message": "Hello there" } ``` **500** — Gabim i papritur ne server. Perfshin rastin kur anulimi nuk u regjistrua ne fiskalizim. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` ### POST /api/v1/invoice/cash Krijo fature me para ne dore (Cash) ## Bleresi eshte opsional Pa `client` fatura leshohet per klientin e rastit, qe eshte rasti normal i nje arke. Sapo dergoni qofte edhe nje te dhene te klientit, behen te nevojshme `client.name`, `client.address` dhe `client.city`, sepse adresa dhe qyteti 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 njera, kerkesa refuzohet me `400` dhe fusha `errors` thote sakte cfare duhet plotesuar. ## Fusha qe varen nga menyra e pageses Dy fusha kerkohen vetem per nje menyre pagese, dhe ndalohen per cdo tjeter: | `payment_method` | Fusha e detyrueshme | Kufiri | | --- | --- | --- | | `COMPANY` | `company_card` | deri ne 50 karaktere | | `SVOUCHER` | `vouchers` | deri ne 20, ne formen numer-vit-NIPT, pa perseritje | Dergimi i `company_card` me `BANKNOTE`, ose i `vouchers` me `CARD`, refuzohet. Nuk ka vend ku ato te shkojne ne dokumentin fiskal, prandaj nuk pranohen ne heshtje. ## Zbritja mbi faturen `invoice_discount_type` me `invoice_discount_value` dergohen gjithmone bashke, dhe zbresin te gjithe faturen. Nje rresht i vetem zbritet me `lines[].discount`, dhe te dyja mund te jene ne te njejten fature. | `invoice_discount_type` | Si lexohet `invoice_discount_value` | Kufiri | | --- | --- | --- | | `percent` | perqindje mbi totalin me TVSH | 100 | | `amount` | vlere me TVSH, ne monedhen e fatures | totali i fatures | Zbritja shperndahet mbi grupet e TVSH-se sipas peshes se secilit ne total, dhe TVSH-ja rillogaritet mbi vleren e ulur, keshtu qe nje fature me disa norma TVSH-je mbetet e sakte. `lines[].discount` eshte perqindje mbi cmimin e njesise se atij rreshti. `price` mbetet cmimi i plote dhe `total` vjen tashme i ulur: `price` here `quantity`, me zbritjen e hequr. Full URL: `https://fature.al/api/v1/invoice/cash` API version: `v1`. Authentication: required (bearer token). #### Body parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `internalId` | string | yes | ID unike e fatures ne sistemin tuaj. Sherben edhe si celes idempotence. | | `client` | object, nullable | no | Pa te, ose me vlere bosh, fatura leshohet per klientin e rastit. | | `client.internal_id` | integer, nullable | no | ID e nje klienti te ruajtur ne fature.al. Kur e dergoni, klienti gjendet me te dhe fushat me poshte nuk lexohen. | | `client.name` | string, nullable | no | I detyrueshem sapo dergoni cilendo fushe tjeter te klientit. | | `client.id` | object, nullable | no | Dokumenti i identifikimit te bleresit, si objekt me `type` dhe `id`. | | `client.id.id` | string, nullable | no | Numri i dokumentit te identifikimit. | | `client.address` | string, nullable | no | Adresa e bleresit qe shkon ne fiskalizim. Nje klient i emeruar e kerkon, ose ne kete kerkese ose e ruajtur me pare ne fature.al. | | `client.city` | string, nullable | no | Qyteti i bleresit qe shkon ne fiskalizim. Nje klient i emeruar e kerkon, ose ne kete kerkese ose e ruajtur me pare ne fature.al. | | `client.country` | string, nullable | no | ISO 3166-1 alpha-3 country code (e.g. RKS, ALB, USA). ALB when absent. | | `lines` | array | yes | Rreshtat e fatures. | | `lines[].product_name` | string | yes | Emri i produktit. | | `lines[].product_code` | string | yes | Kodi i produktit. | | `lines[].unit` | string | yes | Njesia matese. | | `lines[].quantity` | number | yes | Sasia. | | `lines[].price` | number | yes | Cmimi per njesi, me TVSH. | | `lines[].total` | number | yes | Totali i rreshtit, me TVSH. | | `lines[].discount` | number, min 0, max 100, nullable | no | Zbritja e ketij rreshti, ne perqindje mbi cmimin e njesise. Eshte opsionale: pa te, ose me vlere bosh, rreshti kalon pikerisht si me pare dhe mungesa e saj nuk kthen kurre gabim. `price` mbetet cmimi i plote i njesise, ndersa `total` vjen tashme i ulur: `price` here `quantity`, me zbritjen e hequr. Nje `total` qe nuk perputhet me ate shifer e refuzon kerkesen me `400`, dhe `errors` tregon cili eshte rreshti dhe cila vlere pritej. | | `lines[].vat` | integer, one of 0, 6, 10, 20 | yes | Norma e TVSH-se ne perqindje: `0`, `6`, `10` ose `20`. Kur biznesi juaj nuk eshte ne skemen e TVSH-se, rreshti regjistrohet me TVSH `0` dhe me perjashtim `TAX_FREE` sido qe ta dergoni kete fushe. Kerkesa nuk refuzohet. | | `lines[].vat_exempt_type` | string, one of TYPE_1, TYPE_2, EXPORT_OF_GOODS, TAX_FREE, nullable | no | Arsyeja e perjashtimit nga TVSH, kur rreshti eshte i perjashtuar. | | `invoice_discount_type` | string, one of percent, amount, nullable | no | Si lexohet `invoice_discount_value`: `percent` si perqindje, `amount` si vlere fikse me TVSH. Zbritja zbatohet mbi te gjithe faturen, kurre mbi nje rresht te vetem: rreshtat ruhen ashtu si i dergoni dhe ulet vetem totali. Punon vetem ne cift me `invoice_discount_value`. Njera pa tjetren injorohet ne heshtje, dhe fatura del pa zbritje. | | `invoice_discount_value` | number, min 0, nullable | no | Vlera e zbritjes, e lexuar sipas `invoice_discount_type`: perqindje kur tipi eshte `percent`, e kufizuar ne 100; vlere me TVSH ne monedhen e fatures kur tipi eshte `amount`, e kufizuar ne totalin e fatures. Zeroja e le faturen pa zbritje. Zbritja shperndahet mbi grupet e TVSH-se sipas peshes se secilit ne total, dhe TVSH-ja rillogaritet mbi vleren e ulur. Detajet dhe shembujt: faqja Zbritjet ne fature. | | `currency` | string, nullable | no | Monedha e fatures. Pa te merret ALL. | | `exchange_rate` | number, nullable | no | Sa leke vlen nje njesi e monedhes se fatures. Pa te, ose me nje vlere jo pozitive, merret 1. Per monedha qe vlejne me pak se nje lek, si JPY ose HUF, dergoni vlere nen 1. | | `due_date` | string, nullable | no | Afati i pageses, ne formatin `YYYY-MM-DD`. | | `supply_start_date` | string, nullable | no | Fillimi i periudhes se furnizimit, per fatura qe mbulojne nje interval. | | `supply_end_date` | string, nullable | no | Fundi i periudhes se furnizimit. | | `reverse_charge` | boolean, nullable | no | Ngarkesa e kundert: TVSH-ja deklarohet nga bleresi, jo nga shitesi. | | `notes` | string, nullable | no | Shenime qe shfaqen ne fature. | | `periodic_invoice` | boolean, nullable | no | Shenon nje fature qe i perket nje cikli te perseritur faturimi. | | `self_issue_type` | string, one of DOMESTIC, ABROAD, OTHER, nullable | no | Vetefaturim. Kur e dergoni, `client` eshte shitesi dhe i duhet numri i identifikimit (NUIS ose dokument) bashke me shtetin. Kur nuk e dergoni, fatura eshte e zakonshme. | #### Example request ```bash curl -X POST 'https://fature.al/api/v1/invoice/cash' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "internalId": "CASH-001", "client": { "internal_id": 1, "name": "Klient i rastit", "id": { "id": "L62221018T" }, "address": "1 Example Street", "city": "Berlin", "country": "US" }, "lines": [ { "product_name": "Kafe", "product_code": "KAF-001", "unit": "cope", "quantity": 2, "price": 150, "total": 300, "discount": 10, "vat": 20, "vat_exempt_type": "TYPE_1" } ], "invoice_discount_type": "percent", "invoice_discount_value": 10, "currency": "ALL", "exchange_rate": 100.5, "due_date": "2026-10-04", "supply_start_date": "2026-09-01", "supply_end_date": "2026-09-30", "reverse_charge": false, "notes": "Faleminderit per blerjen", "periodic_invoice": false, "self_issue_type": "DOMESTIC" }' ``` #### Responses **201** — Created | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.invoice` | object | | | `data.invoice.id` | integer | Fatureal invoice id. Store it next to your own internalId | | `data.invoice.number` | string, nullable | Fiscal invoice number | | `data.invoice.iic` | string, nullable | IIC / NSLF | | `data.invoice.fic` | string, nullable | FIC / NIVF. Null while the invoice waits for a deferred fiscalisation | | `data.invoice.tcrCode` | string, nullable | TCR code of the fiscal device that issued it | | `data.invoice.businessCode` | string, nullable | Business unit code the invoice was issued under | | `data.invoice.operatorCode` | string, nullable | Operator code the invoice was issued under | | `data.invoice.fiscalizedAt` | string | Creation timestamp (YYYY-MM-DD HH:MM:SS) | | `data.invoice.verifyURL` | string, nullable | Government verification URL, the one behind the QR code | | `data.invoice.pdf` | string | Direct download URL for the document. On an e-invoice that already has an EIC this points at the official e-invoice PDF instead of ours | | `data.invoice.eic` | string, nullable | EIC. The key is present only on an e-invoice that already has one, so treat it as absent rather than null on every other invoice | ```json { "status": true, "data": { "invoice": { "id": 1, "number": "number", "iic": "iic", "fic": "fic", "tcrCode": "tcrCode", "businessCode": "businessCode", "operatorCode": "operatorCode", "fiscalizedAt": "fiscalizedAt", "verifyURL": "https://example.com", "pdf": "pdf", "eic": "eic" } } } ``` **400** — Te dhena te paplota ose te pavlefshme. `errors` thote sakte cfare duhet plotesuar. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **403** — Abonimi ka mbaruar, ose veprimi nuk lejohet per kete llogari. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **409** — Nje fature me kete `internalId` po procesohet ose ekziston tashme per kete vit. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **422** — Te dhenat nuk kaluan validimin. Kjo pergjigje perdor fushen `success`, jo `status`. `internalId` qe mungon kthehet me zarfin standard te gabimit. | Field | Type | Description | | --- | --- | --- | | `success` | boolean | Always false | | `message` | string | A single summary line, the same for every validation failure | | `errors` | object | The failing fields, each with the messages for it. Dotted keys point into nested objects and array items, e.g. `lines.0.quantity` | ```json { "success": true, "message": "Hello there", "errors": [] } ``` **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`. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **500** — Gabim i papritur ne server. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **503** — Sherbimi i fiskalizimit eshte i paarritshem. Fatura ruhet dhe fiskalizohet automatikisht me vone. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` ### POST /api/v1/invoice/details/{internalId} Detajet e fatures sipas Internal ID Merr detajet e nje fature duke perdorur ID-ne tuaj interne. Full URL: `https://fature.al/api/v1/invoice/details/{internalId}` API version: `v1`. Authentication: required (bearer token). #### Path parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `internalId` | string | yes | ID juaj interne, e derguar kur u krijua fatura. | #### Example request ```bash curl -X POST 'https://fature.al/api/v1/invoice/details/CASH-001' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **201** — Created | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.invoice` | object | | | `data.invoice.id` | integer | Fatureal invoice id. Store it next to your own internalId | | `data.invoice.number` | string, nullable | Fiscal invoice number | | `data.invoice.iic` | string, nullable | IIC / NSLF | | `data.invoice.fic` | string, nullable | FIC / NIVF. Null while the invoice waits for a deferred fiscalisation | | `data.invoice.tcrCode` | string, nullable | TCR code of the fiscal device that issued it | | `data.invoice.businessCode` | string, nullable | Business unit code the invoice was issued under | | `data.invoice.operatorCode` | string, nullable | Operator code the invoice was issued under | | `data.invoice.fiscalizedAt` | string | Creation timestamp (YYYY-MM-DD HH:MM:SS) | | `data.invoice.verifyURL` | string, nullable | Government verification URL, the one behind the QR code | | `data.invoice.pdf` | string | Direct download URL for the document. On an e-invoice that already has an EIC this points at the official e-invoice PDF instead of ours | | `data.invoice.eic` | string, nullable | EIC. The key is present only on an e-invoice that already has one, so treat it as absent rather than null on every other invoice | ```json { "status": true, "data": { "invoice": { "id": 1, "number": "number", "iic": "iic", "fic": "fic", "tcrCode": "tcrCode", "businessCode": "businessCode", "operatorCode": "operatorCode", "fiscalizedAt": "fiscalizedAt", "verifyURL": "https://example.com", "pdf": "pdf", "eic": "eic" } } } ``` **404** — Nuk u gjet asnje fature me kete `internalId`. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **422** — `internalId` eshte bosh. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **500** — Gabim i papritur ne server. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` ### POST /api/v1/invoice/e-invoice 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 `client.address` dhe `client.city` duhen ose ne kerkese, ose te ruajtura me pare tek klienti ne fature.al. Kur mungon nje e dhene e nevojshme, kerkesa refuzohet me `400` dhe fusha `errors` thote sakte cfare duhet plotesuar. ## Lloji i dokumentit `process` shkon si ProfileID ne dokumentin UBL, `doc_type` si lloji i dokumentit. Te dyja jane te detyrueshme: | Dokumenti | `doc_type` | `process` | Kerkon `original_invoice_iic` | | --- | --- | --- | --- | | Fature shitjeje | `380` | `P1` | jo | | Note krediti | `381` | `P9` | **po** | | Note debiti | `383` | `P9` | **po** | Nje note krediti dhe nje note debiti korrigjojne nje fature tjeter, prandaj kerkojne `original_invoice_iic`, IIC-ne qe ju ktheu ajo fature: - shkon si BillingReference ne dokumentin UBL; - shkon si reference korrigjimi ne regjistrimin e CIS; - pa te, kerkesa refuzohet me `422`. Per te kthyer nje fature te plote perdorni endpoint-in e anulimit, jo nje note krediti: ai e shenon origjinalin si te kthyer. ## Zbritja mbi faturen `invoice_discount_type` me `invoice_discount_value` dergohen gjithmone bashke, dhe zbresin te gjithe faturen. Nje rresht i vetem zbritet me `lines[].discount`, dhe te dyja mund te jene ne te njejten fature. | `invoice_discount_type` | Si lexohet `invoice_discount_value` | Kufiri | | --- | --- | --- | | `percent` | perqindje mbi totalin me TVSH | 100 | | `amount` | vlere me TVSH, ne monedhen e fatures | totali i fatures | Zbritja shperndahet mbi grupet e TVSH-se sipas peshes se secilit ne total, dhe TVSH-ja rillogaritet mbi vleren e ulur, keshtu qe nje fature me disa norma TVSH-je mbetet e sakte. `lines[].discount` eshte perqindje mbi cmimin e njesise se atij rreshti. `price` mbetet cmimi i plote dhe `total` vjen tashme i ulur: `price` here `quantity`, me zbritjen e hequr. Ne dokumentin UBL zbritja del si AllowanceCharge, me nje ze per cdo norme TVSH-je. Full URL: `https://fature.al/api/v1/invoice/e-invoice` API version: `v1`. Authentication: required (bearer token). #### Body parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `internalId` | string | yes | ID unike e fatures ne sistemin tuaj. Sherben edhe si celes idempotence: i njejti `internalId` brenda te njejtit vit kthen `409` ne vend qe te leshoje nje fature te dyte, prandaj nje riprovim pas nje lidhjeje qe u nderpre eshte i sigurt. | | `client` | object | yes | Bleresi. I detyrueshem per nje e-fature, sepse dokumenti shkon i plote ne sistemin qendror. Dergoni `client.internal_id` per nje klient te ruajtur, ose NIPT-in me emrin dhe shtetin per nje te ri. | | `client.internal_id` | integer, nullable | no | ID e nje klienti te ruajtur ne fature.al. Kur e dergoni, klienti gjendet me te dhe fushat e tjera nuk lexohen. | | `client.nuis` | string | no | NIPT-i i bleresit. I detyrueshem kur nuk dergoni `client.internal_id`. | | `client.name` | string | no | Emri i bleresit. I detyrueshem kur nuk dergoni `client.internal_id`. | | `client.address` | string, nullable | no | Adresa e bleresit qe shkon ne sistemin e e-faturave. Duhet ose ne kete kerkese ose e ruajtur me pare ne fature.al. | | `client.city` | string, nullable | no | Qyteti i bleresit qe shkon ne sistemin e e-faturave. Duhet ose ne kete kerkese ose i ruajtur me pare ne fature.al. | | `client.country` | string | no | Kodi i shtetit ISO 3166-1 alpha-3. | | `lines` | array | yes | Rreshtat e fatures, te pakten nje. | | `lines[].product_name` | string | yes | Emri i produktit ose i sherbimit. | | `lines[].product_code` | string | yes | Kodi i produktit ne katalogun tuaj. | | `lines[].unit` | string | yes | Njesia matese si tekst, ajo qe lexon njeriu. | | `lines[].quantity` | number | yes | Sasia. | | `lines[].price` | number | yes | Cmimi per njesi, me TVSH. | | `lines[].total` | number | yes | Totali i rreshtit, me TVSH. | | `lines[].discount` | number, min 0, max 100, nullable | no | Zbritja e ketij rreshti, ne perqindje mbi cmimin e njesise. Eshte opsionale: pa te, ose me vlere bosh, rreshti kalon pikerisht si me pare dhe mungesa e saj nuk kthen kurre gabim. `price` mbetet cmimi i plote i njesise, ndersa `total` vjen tashme i ulur: `price` here `quantity`, me zbritjen e hequr. Nje `total` qe nuk perputhet me ate shifer e refuzon kerkesen me `400`, dhe `errors` tregon cili eshte rreshti dhe cila vlere pritej. | | `lines[].vat` | integer, one of 0, 6, 10, 20, nullable | no | Norma e TVSH-se ne perqindje: `0`, `6`, `10` ose `20`. Kur biznesi juaj nuk eshte ne skemen e TVSH-se, rreshti regjistrohet me TVSH `0` dhe me perjashtim `TAX_FREE` sido qe ta dergoni kete fushe. Kerkesa nuk refuzohet. | | `lines[].vat_exempt_type` | string, one of TYPE_1, TYPE_2, EXPORT_OF_GOODS, TAX_FREE, nullable | no | Arsyeja e perjashtimit nga TVSH, kur rreshti eshte i perjashtuar. | | `invoice_discount_type` | string, one of percent, amount, nullable | no | Si lexohet `invoice_discount_value`: `percent` si perqindje, `amount` si vlere fikse me TVSH. Zbritja zbatohet mbi te gjithe faturen, kurre mbi nje rresht te vetem: rreshtat ruhen ashtu si i dergoni dhe ulet vetem totali. Punon vetem ne cift me `invoice_discount_value`. Njera pa tjetren injorohet ne heshtje, dhe fatura del pa zbritje. | | `invoice_discount_value` | number, min 0, nullable | no | Vlera e zbritjes, e lexuar sipas `invoice_discount_type`: perqindje kur tipi eshte `percent`, e kufizuar ne 100; vlere me TVSH ne monedhen e fatures kur tipi eshte `amount`, e kufizuar ne totalin e fatures. Zeroja e le faturen pa zbritje. Ne dokumentin UBL del si AllowanceCharge me nje ze per cdo norme TVSH-je, sepse zbritja shperndahet mbi grupet e TVSH-se sipas peshes se secilit ne total. Detajet dhe shembujt: faqja Zbritjet ne fature. | | `bank_account` | integer, nullable | no | ID e nje llogarie bankare te ruajtur ne fature.al. | | `bank_account_iban` | string, nullable | no | IBAN-i i llogarise. Alternative ndaj `bank_account`, kur mbani IBAN-in dhe jo ID-ne. | | `bankAccount` | object, nullable | no | Llogaria bankare e shkruar e plote, kur nuk e keni ende ne fature.al. Ruhet si llogari e kompanise suaj, dhe nje IBAN qe ekziston tashme riperdoret ne vend qe te dyfishohet. | | `bankAccount.name` | string, nullable | no | Emri i bankes. | | `bankAccount.iban` | string, nullable | no | IBAN-i i llogarise. | | `bankAccount.currency` | string, nullable | no | Monedha e llogarise. | | `bankAccount.swift` | string, nullable | no | Kodi SWIFT/BIC i bankes. | | `bankAccount.notes` | string, nullable | no | Shenime qe shoqerojne llogarine ne fature. | | `bankAccount.holder` | string, nullable | no | Mbajtesi i llogarise. | | `currency` | string, nullable | no | Monedha e fatures. Pa te merret ALL. | | `exchange_rate` | number, nullable | no | Sa leke vlen nje njesi e monedhes se fatures. Pa te, ose me nje vlere jo pozitive, merret 1. Per monedha qe vlejne me pak se nje lek, si JPY ose HUF, dergoni vlere nen 1. | | `due_date` | string, nullable | no | Afati i pageses, ne formatin `YYYY-MM-DD`. | | `supply_start_date` | string, nullable | no | Fillimi i periudhes se furnizimit, per fatura qe mbulojne nje interval. | | `supply_end_date` | string, nullable | no | Fundi i periudhes se furnizimit. | | `reverse_charge` | boolean, nullable | no | Ngarkesa e kundert: TVSH-ja deklarohet nga bleresi, jo nga shitesi. | | `notes` | string, nullable | no | Shenime qe shfaqen ne fature. | | `periodic_invoice` | boolean, nullable | no | Shenon nje fature qe i perket nje cikli te perseritur faturimi. | | `original_invoice_iic` | string, nullable | yes | IIC-ja e fatures qe ky dokument korrigjon, ajo qe ju ktheu fatura origjinale. E detyrueshme per nje note krediti (`doc_type=381`) dhe per nje note debiti (`doc_type=383`), sepse te dyja korrigjojne nje fature tjeter. Nuk pranohet per llojet e tjera te dokumentit. Required depending on doc_type. | #### Example request ```bash curl -X POST 'https://fature.al/api/v1/invoice/e-invoice' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "internalId": "EINV-2026-000412", "client": { "internal_id": 8812, "nuis": "L62221018T", "name": "Ei3 Software Solution shpk", "address": "1 Example Street", "city": "Berlin", "country": "ALB" }, "lines": [ { "product_name": "Kafe", "product_code": "KAF-001", "unit": "cope", "quantity": 2, "price": 150, "total": 300, "discount": 10, "vat": 20, "vat_exempt_type": "EXPORT_OF_GOODS" } ], "invoice_discount_type": "percent", "invoice_discount_value": 10, "bank_account": 42, "bank_account_iban": "AL35202111090000000001234567", "bankAccount": { "name": "BKT", "iban": "AL35202111090000000001234567", "currency": "ALL", "swift": "NCBAALTX", "notes": "notes", "holder": "Ei3 Software Solution shpk" }, "currency": "ALL", "exchange_rate": 100.5, "due_date": "2026-10-04", "supply_start_date": "2026-09-01", "supply_end_date": "2026-09-30", "reverse_charge": false, "notes": "Faleminderit per blerjen", "periodic_invoice": false, "original_invoice_iic": "8FE72E2ACD1C500A83F8C89B4E2E3E1D" }' ``` #### Responses **201** — Created | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.invoice` | object | | | `data.invoice.id` | integer | Fatureal invoice id. Store it next to your own internalId | | `data.invoice.number` | string, nullable | Fiscal invoice number | | `data.invoice.iic` | string, nullable | IIC / NSLF | | `data.invoice.fic` | string, nullable | FIC / NIVF. Null while the invoice waits for a deferred fiscalisation | | `data.invoice.tcrCode` | string, nullable | TCR code of the fiscal device that issued it | | `data.invoice.businessCode` | string, nullable | Business unit code the invoice was issued under | | `data.invoice.operatorCode` | string, nullable | Operator code the invoice was issued under | | `data.invoice.fiscalizedAt` | string | Creation timestamp (YYYY-MM-DD HH:MM:SS) | | `data.invoice.verifyURL` | string, nullable | Government verification URL, the one behind the QR code | | `data.invoice.pdf` | string | Direct download URL for the document. On an e-invoice that already has an EIC this points at the official e-invoice PDF instead of ours | | `data.invoice.eic` | string, nullable | EIC. The key is present only on an e-invoice that already has one, so treat it as absent rather than null on every other invoice | ```json { "status": true, "data": { "invoice": { "id": 1, "number": "number", "iic": "iic", "fic": "fic", "tcrCode": "tcrCode", "businessCode": "businessCode", "operatorCode": "operatorCode", "fiscalizedAt": "fiscalizedAt", "verifyURL": "https://example.com", "pdf": "pdf", "eic": "eic" } } } ``` **400** — Te dhena te paplota ose te pavlefshme. `errors` thote sakte cfare duhet plotesuar. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **403** — Abonimi ka mbaruar, ose veprimi nuk lejohet per kete llogari. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **409** — Nje fature me kete `internalId` po procesohet ose ekziston tashme per kete vit. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **422** — Te dhenat nuk kaluan validimin. Kjo pergjigje perdor fushen `success`, jo `status`. `internalId` qe mungon kthehet me zarfin standard te gabimit. | Field | Type | Description | | --- | --- | --- | | `success` | boolean | Always false | | `message` | string | A single summary line, the same for every validation failure | | `errors` | object | The failing fields, each with the messages for it. Dotted keys point into nested objects and array items, e.g. `lines.0.quantity` | ```json { "success": true, "message": "Hello there", "errors": [] } ``` **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`. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **500** — Gabim i papritur ne server. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **503** — Sherbimi i fiskalizimit eshte i paarritshem. Fatura ruhet dhe fiskalizohet automatikisht me vone. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` ### POST /api/v1/invoice/noncash Krijo fature pa para ne dore (NonCash) Perdoret per transaksione me transferte bankare, cek dhe cdo pagese qe nuk kryhet ne arke. ## Bleresi Klienti identifikohet me `client.name` dhe, kur e dergoni, me `client.id`. Adresa dhe qyteti shkojne ne sistemin fiskal, prandaj duhen njera nga dy rruget: - `client.address` dhe `client.city` ne vete kerkesen; - ose te ruajtura me pare tek klienti ne fature.al. Kur mungon nje e dhene e nevojshme, kerkesa refuzohet me `400` dhe fusha `errors` thote sakte cfare duhet plotesuar. ## Llogaria bankare Shkruhet ne fature ne tri menyra, sipas asaj qe keni ne dore: | Fusha | Kuptimi | | --- | --- | | `bank_account` | ID e nje llogarie te ruajtur ne fature.al | | `bank_account_iban` | Gjendet me IBAN | | `bankAccount` | Shkruhet e plote dhe ruhet si llogari e kompanise; nje IBAN ekzistues riperdoret | ## Zbritja mbi faturen `invoice_discount_type` me `invoice_discount_value` dergohen gjithmone bashke, dhe zbresin te gjithe faturen. Nje rresht i vetem zbritet me `lines[].discount`, dhe te dyja mund te jene ne te njejten fature. | `invoice_discount_type` | Si lexohet `invoice_discount_value` | Kufiri | | --- | --- | --- | | `percent` | perqindje mbi totalin me TVSH | 100 | | `amount` | vlere me TVSH, ne monedhen e fatures | totali i fatures | Zbritja shperndahet mbi grupet e TVSH-se sipas peshes se secilit ne total, dhe TVSH-ja rillogaritet mbi vleren e ulur, keshtu qe nje fature me disa norma TVSH-je mbetet e sakte. `lines[].discount` eshte perqindje mbi cmimin e njesise se atij rreshti. `price` mbetet cmimi i plote dhe `total` vjen tashme i ulur: `price` here `quantity`, me zbritjen e hequr. Tarifa `fee` mbetet jashte bazes se zbritjes: zbritet shuma e rreshtave, dhe tarifa i shtohet totalit te ulur. ## Note krediti dhe note debiti Nje fature jo-cash korrigjohet nga nje fature tjeter jo-cash. Dergoni `doc_type` bashke me `original_invoice_iic`, IIC-ne qe ju ktheu fatura origjinale: | `doc_type` | Dokumenti | Efekti | | --- | --- | --- | | mungon ose `380` | Fature e zakonshme | asnje | | `381` | Note krediti | ul vleren qe bleresi ju detyrohet | | `383` | Note debiti | rrit vleren qe bleresi ju detyrohet | Origjinali duhet te jete fature jo-cash e fiskalizuar, e paanuluar dhe ende e korrigjueshme. Rreshtat qe dergoni jane rreshtat e korrigjimit, me vlerat pozitive: drejtimin e percakton `doc_type`, jo shenja e numrave. Kur korrigjimet e mbulojne te gjithe faturen, origjinali shenohet si i kthyer. Per te kthyer nje fature te plote perdorni endpoint-in e anulimit, jo nje note krediti. Full URL: `https://fature.al/api/v1/invoice/noncash` API version: `v1`. Authentication: required (bearer token). #### Body parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `internalId` | string | yes | ID unike e fatures ne sistemin tuaj. Sherben edhe si celes idempotence: i njejti `internalId` brenda te njejtit vit kthen `409` ne vend qe te leshoje nje fature te dyte, prandaj nje riprovim pas nje lidhjeje qe u nderpre eshte i sigurt. | | `client` | object, nullable | no | Pa te, ose me vlere bosh, fatura leshohet per klientin e rastit. | | `client.internal_id` | integer, nullable | no | ID e nje klienti te ruajtur ne fature.al. Kur e dergoni, klienti gjendet me te dhe fushat me poshte nuk lexohen. | | `client.name` | string | no | Emri i bleresit. | | `client.id` | object, nullable | no | Dokumenti i identifikimit te bleresit, si objekt me `type` dhe `id`. | | `client.id.id` | string, nullable | no | Numri i dokumentit te identifikimit. | | `client.address` | string, nullable | no | Adresa e bleresit qe shkon ne fiskalizim. Nje klient i emeruar e kerkon, ose ne kete kerkese ose e ruajtur me pare ne fature.al. | | `client.city` | string, nullable | no | Qyteti i bleresit qe shkon ne fiskalizim. Nje klient i emeruar e kerkon, ose ne kete kerkese ose e ruajtur me pare ne fature.al. | | `client.country` | string | no | ISO 3166-1 alpha-3 country code (e.g. RKS, ALB, USA). ALB when absent. | | `lines` | array | yes | Rreshtat e fatures, te pakten nje. | | `lines[].product_name` | string | yes | Emri i produktit ose i sherbimit. | | `lines[].product_code` | string | yes | Kodi i produktit ne katalogun tuaj. | | `lines[].unit` | string | yes | Njesia matese si tekst, ajo qe lexon njeriu. | | `lines[].quantity` | number | yes | Sasia. | | `lines[].price` | number | yes | Cmimi per njesi, me TVSH. | | `lines[].total` | number | yes | Totali i rreshtit, me TVSH. | | `lines[].discount` | number, min 0, max 100, nullable | no | Zbritja e ketij rreshti, ne perqindje mbi cmimin e njesise. Eshte opsionale: pa te, ose me vlere bosh, rreshti kalon pikerisht si me pare dhe mungesa e saj nuk kthen kurre gabim. `price` mbetet cmimi i plote i njesise, ndersa `total` vjen tashme i ulur: `price` here `quantity`, me zbritjen e hequr. Nje `total` qe nuk perputhet me ate shifer e refuzon kerkesen me `400`, dhe `errors` tregon cili eshte rreshti dhe cila vlere pritej. | | `lines[].vat` | integer, one of 0, 6, 10, 20, nullable | no | Norma e TVSH-se ne perqindje: `0`, `6`, `10` ose `20`. Kur biznesi juaj nuk eshte ne skemen e TVSH-se, rreshti regjistrohet me TVSH `0` dhe me perjashtim `TAX_FREE` sido qe ta dergoni kete fushe. Kerkesa nuk refuzohet. | | `lines[].vat_exempt_type` | string, one of TYPE_1, TYPE_2, EXPORT_OF_GOODS, TAX_FREE, nullable | no | Arsyeja e perjashtimit nga TVSH, kur rreshti eshte i perjashtuar. | | `invoice_discount_type` | string, one of percent, amount, nullable | no | Si lexohet `invoice_discount_value`: `percent` si perqindje, `amount` si vlere fikse me TVSH. Zbritja zbatohet mbi te gjithe faturen, kurre mbi nje rresht te vetem: rreshtat ruhen ashtu si i dergoni dhe ulet vetem totali. Punon vetem ne cift me `invoice_discount_value`. Njera pa tjetren injorohet ne heshtje, dhe fatura del pa zbritje. | | `invoice_discount_value` | number, min 0, nullable | no | Vlera e zbritjes, e lexuar sipas `invoice_discount_type`: perqindje kur tipi eshte `percent`, e kufizuar ne 100; vlere me TVSH ne monedhen e fatures kur tipi eshte `amount`, e kufizuar ne totalin e fatures. Zeroja e le faturen pa zbritje. Baza e zbritjes eshte shuma e rreshtave. Tarifa `fee` mbetet jashte saj dhe nuk zbritet. Detajet dhe shembujt: faqja Zbritjet ne fature. | | `bank_account` | integer, nullable | no | ID e nje llogarie bankare te ruajtur ne fature.al. | | `bank_account_iban` | string, nullable | no | IBAN-i i llogarise. Alternative ndaj `bank_account`, kur mbani IBAN-in dhe jo ID-ne. | | `bankAccount` | object, nullable | no | Llogaria bankare e shkruar e plote, kur nuk e keni ende ne fature.al. Ruhet si llogari e kompanise suaj, dhe nje IBAN qe ekziston tashme riperdoret ne vend qe te dyfishohet. | | `bankAccount.name` | string, nullable | no | Emri i bankes. | | `bankAccount.iban` | string, nullable | no | IBAN-i i llogarise. | | `bankAccount.currency` | string, nullable | no | Monedha e llogarise. | | `bankAccount.swift` | string, nullable | no | Kodi SWIFT/BIC i bankes. | | `bankAccount.notes` | string, nullable | no | Shenime qe shoqerojne llogarine ne fature. | | `bankAccount.holder` | string, nullable | no | Mbajtesi i llogarise. | | `fee` | object, nullable | no | Tarife shtese qe shkon vecmas nga rreshtat e fatures. | | `fee.fee_type` | string, nullable | no | Lloji i tarifes: OTHER, COMMISSION, PACK ose BOTTLE. | | `fee.fee_amount` | number, nullable | no | Vlera e tarifes. | | `currency` | string, nullable | no | Monedha e fatures. Pa te merret ALL. | | `exchange_rate` | number, nullable | no | Sa leke vlen nje njesi e monedhes se fatures. Pa te, ose me nje vlere jo pozitive, merret 1. Per monedha qe vlejne me pak se nje lek, si JPY ose HUF, dergoni vlere nen 1. | | `due_date` | string, nullable | no | Afati i pageses, ne formatin `YYYY-MM-DD`. | | `supply_start_date` | string, nullable | no | Fillimi i periudhes se furnizimit, per fatura qe mbulojne nje interval. | | `supply_end_date` | string, nullable | no | Fundi i periudhes se furnizimit. | | `reverse_charge` | boolean, nullable | no | Ngarkesa e kundert: TVSH-ja deklarohet nga bleresi, jo nga shitesi. | | `notes` | string, nullable | no | Shenime qe shfaqen ne fature. | | `periodic_invoice` | boolean, nullable | no | Shenon nje fature qe i perket nje cikli te perseritur faturimi. | | `self_issue_type` | string, one of DOMESTIC, ABROAD, OTHER, nullable | no | Vetefaturim. Kur e dergoni, `client` eshte shitesi. | | `doc_type` | string, nullable | no | E ben faturen dokument korrigjues mbi nje fature tjeter jo-cash: `381` note krediti, `383` note debiti. Pa te, ose me `380`, fatura eshte e zakonshme. Nje note kerkon `original_invoice_iic`, dhe rreshtat qe dergoni jane rreshtat e korrigjimit, jo ata te fatures origjinale. Vlerat shkojne pozitive: eshte `doc_type` qe percakton drejtimin, jo shenja e numrave. | | `original_invoice_iic` | string, nullable | no | IIC-ja e fatures jo-cash qe ky dokument korrigjon, ajo qe ju ktheu fatura origjinale. E detyrueshme kur `doc_type` eshte `381` ose `383`, dhe e papranueshme ne cdo rast tjeter. Origjinali duhet te jete fature jo-cash e fiskalizuar, e paanuluar dhe ende e korrigjueshme. Per te kthyer nje fature te plote perdorni endpoint-in e anulimit, jo nje note krediti. | #### Example request ```bash curl -X POST 'https://fature.al/api/v1/invoice/noncash' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "internalId": "NONCASH-2026-000412", "client": { "internal_id": 1, "name": "Alpha SHPK", "id": { "id": "L62221018T" }, "address": "1 Example Street", "city": "Berlin", "country": "US" }, "lines": [ { "product_name": "Kafe", "product_code": "KAF-001", "unit": "cope", "quantity": 2, "price": 150, "total": 300, "discount": 10, "vat": 20, "vat_exempt_type": "EXPORT_OF_GOODS" } ], "invoice_discount_type": "percent", "invoice_discount_value": 10, "bank_account": 42, "bank_account_iban": "AL35202111090000000001234567", "bankAccount": { "name": "BKT", "iban": "AL35202111090000000001234567", "currency": "ALL", "swift": "NCBAALTX", "notes": "notes", "holder": "Ei3 Software Solution shpk" }, "fee": { "fee_type": "PACK", "fee_amount": 50 }, "currency": "ALL", "exchange_rate": 100.5, "due_date": "2026-10-04", "supply_start_date": "2026-09-01", "supply_end_date": "2026-09-30", "reverse_charge": false, "notes": "Faleminderit per blerjen", "periodic_invoice": false, "self_issue_type": "DOMESTIC", "doc_type": 381, "original_invoice_iic": "8FE72E2ACD1C500A83F8C89B4E2E3E1D" }' ``` #### Responses **201** — Created | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.invoice` | object | | | `data.invoice.id` | integer | Fatureal invoice id. Store it next to your own internalId | | `data.invoice.number` | string, nullable | Fiscal invoice number | | `data.invoice.iic` | string, nullable | IIC / NSLF | | `data.invoice.fic` | string, nullable | FIC / NIVF. Null while the invoice waits for a deferred fiscalisation | | `data.invoice.tcrCode` | string, nullable | TCR code of the fiscal device that issued it | | `data.invoice.businessCode` | string, nullable | Business unit code the invoice was issued under | | `data.invoice.operatorCode` | string, nullable | Operator code the invoice was issued under | | `data.invoice.fiscalizedAt` | string | Creation timestamp (YYYY-MM-DD HH:MM:SS) | | `data.invoice.verifyURL` | string, nullable | Government verification URL, the one behind the QR code | | `data.invoice.pdf` | string | Direct download URL for the document. On an e-invoice that already has an EIC this points at the official e-invoice PDF instead of ours | | `data.invoice.eic` | string, nullable | EIC. The key is present only on an e-invoice that already has one, so treat it as absent rather than null on every other invoice | ```json { "status": true, "data": { "invoice": { "id": 1, "number": "number", "iic": "iic", "fic": "fic", "tcrCode": "tcrCode", "businessCode": "businessCode", "operatorCode": "operatorCode", "fiscalizedAt": "fiscalizedAt", "verifyURL": "https://example.com", "pdf": "pdf", "eic": "eic" } } } ``` **400** — Te dhena te paplota ose te pavlefshme. `errors` thote sakte cfare duhet plotesuar. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **403** — Abonimi ka mbaruar, ose veprimi nuk lejohet per kete llogari. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **409** — Nje fature me kete `internalId` po procesohet ose ekziston tashme per kete vit. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **422** — Te dhenat nuk kaluan validimin. Kjo pergjigje perdor fushen `success`, jo `status`. `internalId` qe mungon kthehet me zarfin standard te gabimit. | Field | Type | Description | | --- | --- | --- | | `success` | boolean | Always false | | `message` | string | A single summary line, the same for every validation failure | | `errors` | object | The failing fields, each with the messages for it. Dotted keys point into nested objects and array items, e.g. `lines.0.quantity` | ```json { "success": true, "message": "Hello there", "errors": [] } ``` **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`. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **500** — Gabim i papritur ne server. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **503** — Sherbimi i fiskalizimit eshte i paarritshem. Fatura ruhet dhe fiskalizohet automatikisht me vone. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` ### POST /api/v1/invoice/order Krijo fature porosi (Order) Regjistron konsumin qe ka nisur pa e mbyllur pagesen. Perdoret ne cift me faturen permbledhese: porosia hap tavolinen, permbledhesja e paguan. - **Mos dergoni `payment_method`**: ai vendoset vete ne `ORDER`. - Ruani `iic` qe ju kthehet. Ai eshte celesi me te cilin porosia mbyllet me vone. - Nje tavoline mund te kete disa porosi te hapura njeheresh. **Zbritja mbi te gjithe faturen i perket permbledheses, jo porosise.** Porosia nuk pranon `invoice_discount_type` dhe `invoice_discount_value`, sepse permbledhesja i kopjon rreshtat nga porosite dhe nje zbritje mbi te gjithe porosine nuk kalon dot tek ajo. Zbritja per rresht kalon: `lines[].discount` ruhet mbi rreshtin e porosise dhe permbledhesja e merr bashke me te, keshtu qe tavolina paguan pikerisht sa tregoi porosia. Full URL: `https://fature.al/api/v1/invoice/order` API version: `v1`. Authentication: required (bearer token). #### Body parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `internalId` | string | yes | ID unike e fatures ne sistemin tuaj. Sherben edhe si celes idempotence. | | `client` | object, nullable | no | Bleresi. Opsional si tek fatura cash: pa te porosia i leshohet klientit te rastit. Me `client.internal_id` merret nje klient i ruajtur, ndryshe `client.name` behet i detyrueshem sapo dergoni cdo fushe tjeter te tij. | | `client.internal_id` | integer, nullable | no | ID e nje klienti te ruajtur ne fature.al. Kur e dergoni, fushat e tjera nuk lexohen. | | `client.name` | string, nullable | no | Emri i bleresit. | | `client.id` | object, nullable | no | Dokumenti i identifikimit te bleresit, si objekt me `type` dhe `id`. | | `client.id.type` | string, nullable | no | NUIS, VAT ose TAX per kompani; ID, PASS ose SOC per person. | | `client.id.id` | string, nullable | no | Numri i dokumentit te identifikimit. | | `client.address` | string, nullable | no | Adresa e bleresit, kur klienti eshte i emeruar. | | `client.city` | string, nullable | no | Qyteti i bleresit, kur klienti eshte i emeruar. | | `client.country` | string, nullable | no | Kodi i shtetit ISO 3166-1 alpha-3. ALB kur mungon. | | `lines` | array | yes | Rreshtat e fatures, me te njejtat fusha si tek Cash. | | `lines[].product_name` | string | yes | Emri i produktit. | | `lines[].product_code` | string | yes | Kodi i produktit. | | `lines[].unit` | string | yes | Njesia matese. | | `lines[].quantity` | number | yes | | | `lines[].price` | number | yes | | | `lines[].total` | number | yes | Totali i rreshtit, me TVSH. | | `lines[].discount` | number, min 0, max 100, nullable | no | Zbritja e ketij rreshti, ne perqindje mbi cmimin e njesise. Eshte opsionale: pa te, ose me vlere bosh, rreshti kalon pikerisht si me pare dhe mungesa e saj nuk kthen kurre gabim. `price` mbetet cmimi i plote i njesise, ndersa `total` vjen tashme i ulur: `price` here `quantity`, me zbritjen e hequr. Nje `total` qe nuk perputhet me ate shifer e refuzon kerkesen me `400`, dhe `errors` tregon cili eshte rreshti dhe cila vlere pritej. | | `lines[].vat` | integer | yes | Shkalla e TVSH. Kur biznesi juaj nuk eshte ne skemen e TVSH-se, rreshti regjistrohet me TVSH `0` dhe me perjashtim `TAX_FREE` sido qe ta dergoni kete fushe. Kerkesa nuk refuzohet. | | `lines[].vat_exempt_type` | string, nullable | no | Arsyeja e perjashtimit nga TVSH, kur rreshti eshte i perjashtuar. | | `currency` | string, nullable | no | Monedha e porosise. Pa te merret ALL. | | `exchange_rate` | number, nullable | no | Sa leke vlen nje njesi e monedhes se porosise. Pa te merret 1. | | `supply_start_date` | string, nullable | no | Fillimi i periudhes se furnizimit. | | `supply_end_date` | string, nullable | no | Fundi i periudhes se furnizimit. | | `notes` | string, nullable | no | Shenime qe shfaqen ne porosi. | #### Example request ```bash curl -X POST 'https://fature.al/api/v1/invoice/order' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "internalId": "ORD-001", "client": { "internal_id": 1, "name": "Klient i rastit", "id": { "type": "type", "id": "L62221018T" }, "address": "1 Example Street", "city": "Berlin", "country": "US" }, "lines": [ { "product_name": "Kafe", "product_code": "KAF-001", "unit": "cope", "quantity": 2, "price": 1999, "total": 4200, "discount": 10, "vat": 20, "vat_exempt_type": "vat exempt type" } ], "currency": "ALL", "exchange_rate": 100.5, "supply_start_date": "2026-09-01", "supply_end_date": "2026-09-30", "notes": "Tavolina 4" }' ``` #### Responses **201** — Created | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.invoice` | object | | | `data.invoice.isOrderInvoice` | boolean | Always true. The key marks the invoice as an Order | | `data.invoice.summaryInvoiceId` | integer, nullable | Id of the Summary invoice that settled this Order. The key appears only once it has been settled, so a freshly issued Order does not carry it | ```json { "status": true, "data": { "invoice": { "isOrderInvoice": true, "summaryInvoiceId": 1 } } } ``` **400** — Te dhena te paplota ose te pavlefshme. `errors` thote sakte cfare duhet plotesuar. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **403** — Abonimi ka mbaruar, ose veprimi nuk lejohet per kete llogari. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **409** — Nje fature me kete `internalId` po procesohet ose ekziston tashme per kete vit. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **422** — Te dhenat nuk kaluan validimin. Kjo pergjigje perdor fushen `success`, jo `status`. `internalId` qe mungon kthehet me zarfin standard te gabimit. | Field | Type | Description | | --- | --- | --- | | `success` | boolean | Always false | | `message` | string | A single summary line, the same for every validation failure | | `errors` | object | The failing fields, each with the messages for it. Dotted keys point into nested objects and array items, e.g. `lines.0.quantity` | ```json { "success": true, "message": "Hello there", "errors": [] } ``` **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`. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **500** — Gabim i papritur ne server. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **503** — Sherbimi i fiskalizimit eshte i paarritshem. Fatura ruhet dhe fiskalizohet automatikisht me vone. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` ### GET /api/v1/invoice/print-eic/{eic} Shkarko PDF te fatures sipas EIC Kthen skedarin PDF te fatures duke perdorur kodin EIC (UUID). Full URL: `https://fature.al/api/v1/invoice/print-eic/{eic}` API version: `v1`. Authentication: required (bearer token). #### Path parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `eic` | string | yes | Kodi EIC i fatures elektronike. | #### Example request ```bash curl -X GET 'https://fature.al/api/v1/invoice/print-eic/2e9b6f31-d712-4c45-8cc0-9faf24c805a3' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — Skedari PDF i fatures. Kontrolloni Content-Type para se ta ruani si PDF: nje EIC qe nuk gjendet kthehet po me statusin 200, por si text/html. ```json example ``` ### GET /api/v1/invoice/print/{id} 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. Full URL: `https://fature.al/api/v1/invoice/print/{id}` API version: `v1`. Authentication: required (bearer token). #### Path parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `id` | integer | yes | ID e fatures ne fature.al. | #### Query parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `format` | string | no | Versioni i dokumentit sipas tabeles me siper: a4, thermal, v2, receipt, local, local-thermal, html, json. | | `lang` | string | no | Gjuha e dokumentit A4: en, it, de. Pa te dokumenti kthehet shqip. | | `copy_only` | integer | no | Vetem per faturat Cash: kthen kopjen e kuponit ne vend te origjinalit. | #### Example request ```bash curl -X GET 'https://fature.al/api/v1/invoice/print/403' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### 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. | Field | Type | Description | | --- | --- | --- | | `logo` | string, nullable | The company logo as base64, or null when none is set | | `title` | string | Document title in the account language, e.g. "Faturë Tatimore" | | `company` | object | | | `company.name` | string | | | `company.nuis` | string, nullable | Seller NUIS | | `company.address` | string, nullable | Address of the business unit that issued the invoice | | `client` | object | | | `client.name` | string | | | `client.id` | object | | | `client.id.type` | string, nullable | Identifier type, e.g. NUIS, ID, PASSPORT | | `client.id.id` | string, nullable | The identifier value | | `client.addres` | string, nullable | Buyer street address | | `client.city` | string, nullable | | | `client.country` | string | ISO 3166-1 alpha-3 country code. ALB when the buyer has none | | `transporter` | object | | | `transporter.name` | string, nullable | | | `transporter.plate` | string, nullable | Vehicle plate | | `transporter.address` | string, nullable | | | `transporter.city` | string, nullable | | | `invoice` | object | | | `invoice.type` | string | Invoice type, e.g. CASH, NONCASH, EINVOICE | | `invoice.payment_method` | string, nullable | | | `invoice.payment_method_label` | string, nullable | The payment method spelled out in the account language, ready to print | | `invoice.bank_account` | object, nullable | Bank account to print as payment instructions, or null | | `invoice.bank_account.id` | integer | | | `invoice.bank_account.bank_name` | string, nullable | | | `invoice.bank_account.iban` | string, nullable | | | `invoice.bank_account.swift` | string, nullable | | | `invoice.bank_account.currency` | string, nullable | ISO 4217 currency code | | `invoice.bank_account.notes` | string, nullable | | | `invoice.issueDate` | string, nullable | Issue date (YYYY-MM-DD HH:MM:SS) | | `invoice.businessCode` | string, nullable | | | `invoice.operatorCode` | string, nullable | | | `invoice.operatorName` | string, nullable | The operator resolved to a name and shortened to "Ana H.", when we know one | | `invoice.deviceCode` | string, nullable | TCR code of the fiscal device | | `invoice.currency` | string, nullable | Invoice currency, null when it is ALL | | `invoice.exchangeRate` | number, nullable | Rate to ALL, null when the invoice is already in ALL | | `invoice.number` | string, nullable | | | `invoice.lines` | array | | | `invoice.lines[].name` | string | | | `invoice.lines[].unit` | string, nullable | | | `invoice.lines[].quantity` | number | | | `invoice.lines[].unitPrice` | number | Unit price before any line discount | | `invoice.lines[].total` | number | Gross line total | | `invoice.amounts` | object | | | `invoice.amounts.net` | number | | | `invoice.amounts.gross` | number | | | `invoice.amounts.vat` | number | | | `invoice.amounts.discount` | number | | | `invoice.amounts.net_all` | number | | | `invoice.amounts.gross_all` | number | | | `invoice.amounts.vat_all` | number | | | `invoice.amounts.discount_all` | number | | | `invoice.iic` | string, nullable | IIC / NSLF | | `invoice.fic` | string, nullable | FIC / NIVF | | `invoice.eic` | string, nullable | EIC, for e-invoices | | `invoice.process` | string, nullable | | | `invoice.doc_type` | string, nullable | | | `invoice.notes` | string, nullable | | | `invoice.verifyUrl` | string, nullable | Government verification URL, the one to render as a QR code | | `invoice.footer` | array | Lines to print under the total, already ordered | ```json { "logo": "logo", "title": "Quarterly report", "company": { "name": "Jane Doe", "nuis": "nuis", "address": "1 Example Street" }, "client": { "name": "Jane Doe", "id": { "type": "type", "id": "id" }, "addres": "addres", "city": "Berlin", "country": "US" }, "transporter": { "name": "Jane Doe", "plate": "plate", "address": "1 Example Street", "city": "Berlin" }, "invoice": { "type": "type", "payment_method": "payment method", "payment_method_label": "payment method label", "bank_account": { "id": 1, "bank_name": "Jane Doe", "iban": "iban", "swift": "swift", "currency": "USD", "notes": "notes" }, "issueDate": "issueDate", "businessCode": "businessCode", "operatorCode": "operatorCode", "operatorName": "Jane Doe", "deviceCode": "deviceCode", "currency": "USD", "exchangeRate": 19.99, "number": "number", "lines": [ { "name": "Jane Doe", "unit": "unit", "quantity": 2, "unitPrice": 1999, "total": 4200 } ], "amounts": { "net": 19.99, "gross": 19.99, "vat": 19.99, "discount": 3, "net_all": 19.99, "gross_all": 19.99, "vat_all": 19.99, "discount_all": 3 }, "iic": "iic", "fic": "fic", "eic": "eic", "process": "process", "doc_type": "doc type", "notes": "notes", "verifyUrl": "https://example.com", "footer": [ "footer" ] } } ``` **404** — Fatura nuk u gjet, ose nuk i perket kompanise suaj. | Field | Type | Description | | --- | --- | --- | | `message` | string | | ```json { "message": "Hello there" } ``` ### POST /api/v1/invoice/summary Krijo fature permbledhese (Summary) Mbyll pagesen e nje ose me shume faturave porosi me nje dokument te vetem. - `order_invoices` mban IIC-te e porosive qe po mbyllen, te pakten nje. - **Rreshtat nuk dergohen**: merren nga vete porosite. - `payment_method` pranon vetem `BANKNOTE` ose `CARD`. - Zbritja e tavolines vendoset ketu, me `invoice_discount_type` dhe `invoice_discount_value`. Pergjigja i liston porosite e mbyllura ne `settledOrderInvoices`. Full URL: `https://fature.al/api/v1/invoice/summary` API version: `v1`. Authentication: required (bearer token). #### Body parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `internalId` | string | yes | ID unike e fatures ne sistemin tuaj. Sherben edhe si celes idempotence: i njejti `internalId` brenda te njejtit vit kthen `409` ne vend qe te leshoje nje fature te dyte, prandaj nje riprovim pas nje lidhjeje qe u nderpre eshte i sigurt. | | `order_invoices` | array | yes | IIC-te e faturave porosi qe po mbyllen, te pakten nje. Rreshtat e permbledhëses merren nga keto porosi, prandaj nuk dergohen ne kerkese. | | `currency` | string, nullable | no | Monedha e fatures. Pa te merret ALL. | | `exchange_rate` | number, nullable | no | Sa leke vlen nje njesi e monedhes se fatures. Pa te merret 1. | | `supply_start_date` | string, nullable | no | Fillimi i periudhes se furnizimit, per fatura qe mbulojne nje interval. | | `supply_end_date` | string, nullable | no | Fundi i periudhes se furnizimit. | | `invoice_discount_type` | string, one of percent, amount, nullable | no | Si lexohet `invoice_discount_value`: `percent` si perqindje, `amount` si vlere fikse me TVSH. Zbritja mbi te gjithe faturen i perket permbledhëses, jo porosive, sepse porosia nuk e pranon fare. Zbritjet per rresht vijne bashke me rreshtat qe kopjohen nga porosite. Punon vetem ne cift me `invoice_discount_value`. | | `invoice_discount_value` | number, min 0, nullable | no | Vlera e zbritjes, e lexuar sipas `invoice_discount_type`: perqindje kur tipi eshte `percent`, e kufizuar ne 100; vlere me TVSH ne monedhen e fatures kur tipi eshte `amount`, e kufizuar ne totalin e permbledhëses. | #### Example request ```bash curl -X POST 'https://fature.al/api/v1/invoice/summary' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "internalId": "SUMMARY-2026-000021", "order_invoices": [ "8FE72E2ACD1C500A83F8C89B4E2E3E1D" ], "currency": "ALL", "exchange_rate": 100.5, "supply_start_date": "2026-09-01", "supply_end_date": "2026-09-30", "invoice_discount_type": "percent", "invoice_discount_value": 10 }' ``` #### Responses **201** — Created | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.invoice` | object | | | `data.invoice.isSummaryInvoice` | boolean | Always true. The key marks the invoice as a Summary | | `data.invoice.settledOrderInvoices` | array | | | `data.invoice.settledOrderInvoices[].id` | integer | | | `data.invoice.settledOrderInvoices[].number` | string, nullable | | | `data.invoice.settledOrderInvoices[].date` | string | When the order was issued (YYYY-MM-DD HH:MM:SS) | | `data.invoice.settledOrderInvoices[].amountGross` | number | | | `data.invoice.settledOrderInvoices[].currency` | string, nullable | | ```json { "status": true, "data": { "invoice": { "isSummaryInvoice": true, "settledOrderInvoices": [ { "id": 1, "number": "number", "date": "date", "amountGross": 4200, "currency": "USD" } ] } } } ``` **400** — Te dhena te paplota ose te pavlefshme. `errors` thote sakte cfare duhet plotesuar. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **403** — Abonimi ka mbaruar, ose veprimi nuk lejohet per kete llogari. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **409** — Nje fature me kete `internalId` po procesohet ose ekziston tashme per kete vit. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **422** — Te dhenat nuk kaluan validimin. Kjo pergjigje perdor fushen `success`, jo `status`. `internalId` qe mungon kthehet me zarfin standard te gabimit. | Field | Type | Description | | --- | --- | --- | | `success` | boolean | Always false | | `message` | string | A single summary line, the same for every validation failure | | `errors` | object | The failing fields, each with the messages for it. Dotted keys point into nested objects and array items, e.g. `lines.0.quantity` | ```json { "success": true, "message": "Hello there", "errors": [] } ``` **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`. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **500** — Gabim i papritur ne server. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **503** — Sherbimi i fiskalizimit eshte i paarritshem. Fatura ruhet dhe fiskalizohet automatikisht me vone. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` ### GET /api/v1/invoice/{id}/details Detajet e fatures sipas ID Merrni detajet e plota te nje fature sipas ID-se ne sistem. Full URL: `https://fature.al/api/v1/invoice/{id}/details` API version: `v1`. Authentication: required (bearer token). #### Path parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `id` | integer | yes | ID e fatures ne fature.al. | #### Example request ```bash curl -X GET 'https://fature.al/api/v1/invoice/403/details' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — OK | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.invoice` | object, nullable | | | `data.invoice.lines` | array | | | `data.invoice.lines[].name` | string | | | `data.invoice.lines[].product_code` | string, nullable | Internal product code, when the line is a mapped product | | `data.invoice.lines[].unit` | string, nullable | | | `data.invoice.lines[].unit_code` | string, nullable | | | `data.invoice.lines[].quantity` | number | | | `data.invoice.lines[].unitPrice` | number | Unit price with the line discount already taken off, major units | | `data.invoice.lines[].vat_rate` | number, nullable | VAT rate percent | | `data.invoice.lines[].vat_exempt_type` | string, nullable | VAT exemption type, when the line is exempt | | `data.invoice.lines[].discount_rate` | number, nullable | Line discount percent, as sent in `lines[].discount` when the line was discounted | | `data.invoice.lines[].discount` | number, nullable | Line discount amount, net-denominated, major units | | `data.invoice.lines[].amount_net` | number | | | `data.invoice.lines[].amount_vat` | number | | | `data.invoice.lines[].total` | number | Gross line total, major units | ```json { "status": true, "data": { "invoice": { "lines": [ { "name": "Jane Doe", "product_code": "product code", "unit": "unit", "unit_code": "unit code", "quantity": 2, "unitPrice": 1999, "vat_rate": 19.99, "vat_exempt_type": "vat exempt type", "discount_rate": 3, "discount": 3, "amount_net": 4200, "amount_vat": 4200, "total": 4200 } ] } } } ``` **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`. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **500** — Gabim i papritur ne server. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` ## Arka Fiskale (v1) Dita ne arken fiskale: hapja e balances para fatures se pare cash, hyrjet dhe daljet e parave, mbyllja ne fund dhe gjendja ne cdo moment. Veprimet regjistrohen ne pajisjen fiskale (TCR) te lidhur me perdoruesin qe ben kerkesen, prandaj pa nje TCR nuk kane ku te shkojne. ### GET /api/v1/cash-register/actions Lista e veprimeve me arken Historiku i arkes: hyrjet, daljet dhe hapjet me mbylljet e dites, me filtrim dhe faqosje. | `type` | Veprimi | | --- | --- | | `MONEY_IN` | Hyrje parash | | `MONEY_OUT` | Dalje parash | | `OPEN_DAY` | Hapje e dites | | `CLOSE_DAY` | Mbyllje e dites | Disa tipe ndahen me presje, pra `type=MONEY_IN,MONEY_OUT` kthen vetem levizjet e parave. Faqezohet me `limit` dhe `offset`. Full URL: `https://fature.al/api/v1/cash-register/actions` API version: `v1`. Authentication: required (bearer token). #### Query parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `limit` | integer | no | Numri i veprimeve per faqe. Defaults to `20`. | | `offset` | integer | no | Nga cili veprim te fillohet. Defaults to `0`. | | `type` | string | no | Filtro sipas tipit: MONEY_IN, MONEY_OUT, OPEN_DAY, CLOSE_DAY. Disa tipe ndahen me presje. | | `fromDate` | string | no | Data e fillimit (YYYY-MM-DD). | | `toDate` | string | no | Data e perfundimit (YYYY-MM-DD). | #### Example request ```bash curl -X GET 'https://fature.al/api/v1/cash-register/actions' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — OK | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.items` | array | | | `data.items[].id` | integer | | | `data.items[].action_type` | string | | | `data.items[].amount` | number | | | `data.items[].currency` | string | | | `data.items[].transaction_date` | string | | | `data.items[].transaction_no` | integer | | | `data.items[].cash_action_no` | string | | | `data.items[].fiscal_status` | string, nullable | | | `data.items[].fiscal_uuid` | string, nullable | | | `data.items[].fiscal_fic` | string, nullable | | | `data.items[].fiscal_tcr_code` | string, nullable | | | `data.items[].description` | string, nullable | | | `data.items[].third_party` | string, nullable | | | `data.items[].id_client` | integer, nullable | | | `data.items[].created_at` | string | | | `data.pagination` | object | | | `data.pagination.records` | integer | | | `data.pagination.limit` | integer | | | `data.pagination.offset` | integer | | | `data.pagination.type` | string, nullable | | ```json { "status": true, "data": { "items": [ { "id": 1, "action_type": "action type", "amount": 4200, "currency": "USD", "transaction_date": "transaction date", "transaction_no": 1, "cash_action_no": "cash action no", "fiscal_status": "fiscal status", "fiscal_uuid": "9f8c7b6a-5d4e-3f2a-1b0c-9d8e7f6a5b4c", "fiscal_fic": "fiscal fic", "fiscal_tcr_code": "fiscal tcr code", "description": "A short description.", "third_party": "third party", "id_client": 1, "created_at": "created at" } ], "pagination": { "records": 1, "limit": 25, "offset": 0, "type": "type" } } } ``` **500** — Gabim i papritur ne server. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` ### GET /api/v1/cash-register/balance Balanca e arkes fiskale Kthen gjendjen e arkes fiskale (TCR) te perdoruesit, ne ALL. Pa `toDate` kthehet balanca e fundit. Me `toDate` llogaritet gjendja sic ka qene ne fund te asaj dite, cka e ben te dobishme per rakordim me nje dite te shkuar. Full URL: `https://fature.al/api/v1/cash-register/balance` API version: `v1`. Authentication: required (bearer token). #### Query parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `toDate` | string, nullable | no | Data deri te cila llogaritet balanca. Pa te kthehet balanca e fundit. | #### Example request ```bash curl -X GET 'https://fature.al/api/v1/cash-register/balance' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — Kur perdoruesi nuk ka pajisje fiskale, pergjigja kthehet me HTTP 200 dhe `status: false`. **422** — Te dhenat nuk kaluan validimin. Kjo pergjigje perdor fushen `success`, jo `status`. | Field | Type | Description | | --- | --- | --- | | `success` | boolean | Always false | | `message` | string | A single summary line, the same for every validation failure | | `errors` | object | The failing fields, each with the messages for it. Dotted keys point into nested objects and array items, e.g. `lines.0.quantity` | ```json { "success": true, "message": "Hello there", "errors": [] } ``` **500** — Gabim i papritur ne server. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` ### POST /api/v1/cash-register/close-balance Mbyll balancen e arkes Mbyll diten ne arken fiskale dhe regjistron veprimin `CLOSE_DAY`. **Nese arka nuk eshte e hapur, hapet vete me balance `0` dhe mbyllet menjehere.** Kjo do te thote se thirrja nuk deshton kurre sepse dita nuk u hap, prandaj mund ta thirrni ne fund te turnit pa kontrolluar me pare gjendjen. Per shifrat e turnit qe sapo u mbyll perdorni raportin e mbylljes se arkes. Full URL: `https://fature.al/api/v1/cash-register/close-balance` API version: `v1`. Authentication: required (bearer token). #### Example request ```bash curl -X POST 'https://fature.al/api/v1/cash-register/close-balance' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — Kur perdoruesi nuk ka pajisje fiskale ose mbyllja deshton, pergjigja kthehet me HTTP 200 dhe `status: false`. **201** — Created | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.balance` | number | | ```json { "status": true, "data": { "balance": 19.99 } } ``` ### POST /api/v1/cash-register/deposit Hyrje ne arke (Deposit) Regjistron para qe hyjne ne arke pa qene shitje, si nje arketim nga klienti ose nje fond fillestar. Veprimi ruhet si `MONEY_IN`. - `amount` duhet te jete gjithmone me e madhe se `0`. Per para qe dalin perdorni endpoint-in e daljes, jo nje vlere negative ketu. - `description` dhe pala e trete jane opsionale por ndihmojne ne rakordim. - Kerkon nje pajisje fiskale (TCR) te lidhur. Full URL: `https://fature.al/api/v1/cash-register/deposit` API version: `v1`. Authentication: required (bearer token). #### Body parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `amount` | number | yes | Vlera e veprimit, gjithmone me e madhe se 0. | | `description` | string, maxLength 255, nullable | no | Pershkrimi i veprimit. | | `third_party` | string, maxLength 255, nullable | no | Pala e trete per veprimin. | | `id_client` | integer, nullable | no | ID e nje klienti tuaj, per ta lidhur veprimin me te. Kthehet me pas ne listen e veprimeve. Nje ID qe nuk i perket kompanise suaj refuzohet. | #### Example request ```bash curl -X POST 'https://fature.al/api/v1/cash-register/deposit' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "amount": 1500, "description": "Arketim nga klienti", "third_party": "Klienti XYZ", "id_client": 42 }' ``` #### Responses **200** — Kur perdoruesi nuk ka pajisje fiskale ose arka nuk ka fonde te mjaftueshme, pergjigja kthehet me HTTP 200 dhe `status: false`. **201** — Created | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.id` | integer | | | `data.action_type` | string | | | `data.amount` | number | | | `data.currency` | string | | | `data.transaction_date` | string | | | `data.transaction_no` | integer | | | `data.cash_action_no` | string | | | `data.fiscal_status` | string, nullable | | | `data.fiscal_uuid` | string, nullable | | | `data.fiscal_fic` | string, nullable | | | `data.description` | string | | ```json { "status": true, "data": { "id": 1, "action_type": "action type", "amount": 4200, "currency": "USD", "transaction_date": "transaction date", "transaction_no": 1, "cash_action_no": "cash action no", "fiscal_status": "fiscal status", "fiscal_uuid": "9f8c7b6a-5d4e-3f2a-1b0c-9d8e7f6a5b4c", "fiscal_fic": "fiscal fic", "description": "A short description." } } ``` **422** — Te dhenat nuk kaluan validimin. Kjo pergjigje perdor fushen `success`, jo `status`. | Field | Type | Description | | --- | --- | --- | | `success` | boolean | Always false | | `message` | string | A single summary line, the same for every validation failure | | `errors` | object | The failing fields, each with the messages for it. Dotted keys point into nested objects and array items, e.g. `lines.0.quantity` | ```json { "success": true, "message": "Hello there", "errors": [] } ``` ### POST /api/v1/cash-register/open-balance Hap balancen e arkes Hap diten ne arken fiskale, hapi qe duhet para se te leshohet fatura e pare cash. - `balance` eshte gjendja me te cilen nis dita. Pa te merret `0`. - Perdoruesi duhet te kete nje pajisje fiskale (TCR) te lidhur, perndryshe veprimi nuk ka ku te regjistrohet. Hapja regjistrohet si veprim `OPEN_DAY` dhe del ne listen e veprimeve. Full URL: `https://fature.al/api/v1/cash-register/open-balance` API version: `v1`. Authentication: required (bearer token). #### Example request ```bash curl -X POST 'https://fature.al/api/v1/cash-register/open-balance' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: 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`. **201** — Created | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.balance` | number | | ```json { "status": true, "data": { "balance": 19.99 } } ``` ### POST /api/v1/cash-register/withdraw Dalje nga arka (Withdraw) Regjistron para qe dalin nga arka, si nje pagese furnitori ose terheqje ne fund te dites. Veprimi ruhet si `MONEY_OUT`. - `amount` duhet te jete gjithmone me e madhe se `0`. Shenja vjen nga endpoint-i qe thirret, jo nga numri. - Kerkon nje pajisje fiskale (TCR) te lidhur. Full URL: `https://fature.al/api/v1/cash-register/withdraw` API version: `v1`. Authentication: required (bearer token). #### Body parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `amount` | number | yes | Vlera e veprimit, gjithmone me e madhe se 0. | | `description` | string, maxLength 255, nullable | no | Pershkrimi i veprimit. | | `third_party` | string, maxLength 255, nullable | no | Pala e trete per veprimin. | | `id_client` | integer, nullable | no | ID e nje klienti tuaj, per ta lidhur veprimin me te. Kthehet me pas ne listen e veprimeve. Nje ID qe nuk i perket kompanise suaj refuzohet. | #### Example request ```bash curl -X POST 'https://fature.al/api/v1/cash-register/withdraw' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "amount": 1500, "description": "Arketim nga klienti", "third_party": "Klienti XYZ", "id_client": 42 }' ``` #### Responses **200** — Kur perdoruesi nuk ka pajisje fiskale ose arka nuk ka fonde te mjaftueshme, pergjigja kthehet me HTTP 200 dhe `status: false`. **201** — Created | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.id` | integer | | | `data.action_type` | string | | | `data.amount` | number | | | `data.currency` | string | | | `data.transaction_date` | string | | | `data.transaction_no` | integer | | | `data.cash_action_no` | string | | | `data.fiscal_status` | string, nullable | | | `data.fiscal_uuid` | string, nullable | | | `data.fiscal_fic` | string, nullable | | | `data.description` | string | | ```json { "status": true, "data": { "id": 1, "action_type": "action type", "amount": 4200, "currency": "USD", "transaction_date": "transaction date", "transaction_no": 1, "cash_action_no": "cash action no", "fiscal_status": "fiscal status", "fiscal_uuid": "9f8c7b6a-5d4e-3f2a-1b0c-9d8e7f6a5b4c", "fiscal_fic": "fiscal fic", "description": "A short description." } } ``` **422** — Te dhenat nuk kaluan validimin. Kjo pergjigje perdor fushen `success`, jo `status`. | Field | Type | Description | | --- | --- | --- | | `success` | boolean | Always false | | `message` | string | A single summary line, the same for every validation failure | | `errors` | object | The failing fields, each with the messages for it. Dotted keys point into nested objects and array items, e.g. `lines.0.quantity` | ```json { "success": true, "message": "Hello there", "errors": [] } ``` ## Klienti (v1) Klientet e kompanise: lista, detajet, krijimi dhe perditesimi, si dhe nje kerkim sipas NIPT-it qe e gjen subjektin qe te mos e krijoni dy here. ### GET /api/v1/client/search Kerko klient sipas NIPT Kerkon nje kompani ne **regjistrin fiskal** me NIPT/NUIS dhe kthen te dhenat e saj. Perdoreni per te mbushur vete formularin e nje klienti te ri: kerkoni nje fushe te vetme nga perdoruesi dhe merrni emrin, adresen dhe qytetin nga regjistri. Nje NIPT i gabuar kapet ketu, para se te dale ne nje fature. Fusha `verified` thote nese kompania u gjet e konfirmuar ne regjister. Dalloni dy pergjigjet qe duken te ngjashme: - `404`, NIPT-i nuk ekziston ne regjister; - `503`, regjistri nuk u arrit, pra NIPT-i mbeti i pakontrolluar. Provoni perseri. Full URL: `https://fature.al/api/v1/client/search` API version: `v1`. Authentication: required (bearer token). #### Query parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `nuis` | string | yes | NIPT/NUIS i kompanise per te kerkuar, ne formatin X00000000X. | #### Example request ```bash curl -X GET 'https://fature.al/api/v1/client/search?nuis=L91806031A' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — OK | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.client` | object | | | `data.client.nuis` | string | | | `data.client.name` | string | | | `data.client.address` | string | | | `data.client.city` | string | | | `data.client.country` | integer | | | `data.client.country_code` | string | | | `data.client.verified` | boolean | | ```json { "status": true, "data": { "client": { "nuis": "nuis", "name": "Jane Doe", "address": "1 Example Street", "city": "Berlin", "country": 1, "country_code": "US", "verified": true } } } ``` **404** — NIPT-i nuk gjendet ne regjistrin fiskal. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **422** — NIPT-i mungon ose nuk eshte ne formatin X00000000X. Kjo pergjigje perdor fushen `success`, jo `status`. | Field | Type | Description | | --- | --- | --- | | `success` | boolean | Always false | | `message` | string | A single summary line, the same for every validation failure | | `errors` | object | The failing fields, each with the messages for it. Dotted keys point into nested objects and array items, e.g. `lines.0.quantity` | ```json { "success": true, "message": "Hello there", "errors": [] } ``` **503** — Regjistri fiskal nuk u arrit, keshtu qe NIPT-i mbeti i pakontrolluar. Provoni perseri. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` ### GET /api/v1/clients Lista e klienteve Merr listen e klienteve te kompanise me faqosje dhe filtrim me tekst. Faqezohet me `limit` dhe `offset`. `limit` kufizohet ne **100** dhe `pagination` kthen edhe `total`, prandaj e dini qe ne faqen e pare sa faqe ju presin: vazhdoni me `offset += limit` derisa `offset` te kaloje `total`. Full URL: `https://fature.al/api/v1/clients` API version: `v1`. Authentication: required (bearer token). #### Query parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `limit` | integer | no | Numri i klienteve per faqe (max 100). Defaults to `20`. | | `offset` | integer | no | Nga cili klient te fillohet. Defaults to `0`. | | `query` | string | no | Kerkim ne emer, mbiemer, NIPT, dokument, email ose telefon. | #### Example request ```bash curl -X GET 'https://fature.al/api/v1/clients' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — OK | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.items` | array | | | `data.items[].id` | integer | | | `data.items[].name` | string | | | `data.items[].client_type` | string, nullable | | | `data.items[].company_name` | string, nullable | | | `data.items[].company_type` | string, nullable | | | `data.items[].nipt` | string, nullable | | | `data.items[].first_name` | string, nullable | | | `data.items[].surname` | string, nullable | | | `data.items[].birthday` | string, nullable | | | `data.items[].id_type` | string, nullable | | | `data.items[].id_num` | string, nullable | | | `data.items[].nationality_code` | string, nullable | | | `data.items[].nationality_id` | integer, nullable | | | `data.items[].telephone` | string, nullable | | | `data.items[].email` | string, nullable | | | `data.items[].address` | string, nullable | | | `data.items[].city` | string, nullable | | | `data.items[].customer_number` | string, nullable | | | `data.items[].created_at` | string, nullable | | | `data.pagination` | object | | | `data.pagination.records` | integer | | | `data.pagination.total` | integer | | | `data.pagination.limit` | integer | | | `data.pagination.offset` | integer | | ```json { "status": true, "data": { "items": [ { "id": 1, "name": "Jane Doe", "client_type": "client type", "company_name": "Jane Doe", "company_type": "company type", "nipt": "nipt", "first_name": "Jane", "surname": "Jane Doe", "birthday": "birthday", "id_type": "id type", "id_num": "id num", "nationality_code": "nationality code", "nationality_id": 1, "telephone": "+15551234567", "email": "jane@example.com", "address": "1 Example Street", "city": "Berlin", "customer_number": "customer number", "created_at": "created at" } ], "pagination": { "records": 1, "total": 4200, "limit": 25, "offset": 0 } } } ``` **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`. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **500** — Gabim i papritur ne server. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` ### POST /api/v1/clients Krijo klient Trupi ndryshon sipas `client_type`, i cili pranon `COMPANY` ose `PERSON`. | `client_type` | Fushat e detyrueshme | | --- | --- | | `COMPANY` | `company_name`, `nipt`, `address`, `city` | | `PERSON` | vetem emri | `company_type` eshte opsional dhe pranon `BUSINESS`, `BANK` ose `EXCHANGE`. Per nje kompani shqiptare, thirrni me pare `GET /client/search` me NIPT-in: ju kthen emrin, adresen dhe qytetin gati per ketu. Full URL: `https://fature.al/api/v1/clients` API version: `v1`. Authentication: required (bearer token). #### Body parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `nationality_code` | string, minLength 3, maxLength 3, nullable | no | Kodi ISO 3166-1 alpha-3 i kombesise. Pa te merret ALB. | | `nationality_id` | integer, nullable | no | ID e nacionalitetit ne fature.al. Plotesohet vete nga nationality_code. | | `telephone` | string, maxLength 255, nullable | no | Telefoni. | | `email` | string, maxLength 255, nullable | no | Email. | | `customer_number` | string, maxLength 30, nullable | no | Numri unik i klientit ne sistemin tuaj. | | `gender` | string, maxLength 10, nullable | no | Gjinia, vetem per PERSON. | | `birthday` | string, nullable | no | Data e lindjes (YYYY-MM-DD). | #### Example request ```bash curl -X POST 'https://fature.al/api/v1/clients' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "nationality_code": "ALB", "nationality_id": 1, "telephone": "+355691234567", "email": "klient@example.com", "customer_number": "CLI-001", "gender": "M", "birthday": "1990-01-15" }' ``` #### Responses **201** — Created | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.client` | object | | | `data.client.id` | integer | | | `data.client.name` | string | | | `data.client.client_type` | string, nullable | | | `data.client.company_name` | string, nullable | | | `data.client.company_type` | string, nullable | | | `data.client.nipt` | string, nullable | | | `data.client.first_name` | string, nullable | | | `data.client.surname` | string, nullable | | | `data.client.birthday` | string, nullable | | | `data.client.id_type` | string, nullable | | | `data.client.id_num` | string, nullable | | | `data.client.nationality_code` | string, nullable | | | `data.client.nationality_id` | integer, nullable | | | `data.client.telephone` | string, nullable | | | `data.client.email` | string, nullable | | | `data.client.address` | string, nullable | | | `data.client.city` | string, nullable | | | `data.client.customer_number` | string, nullable | | | `data.client.created_at` | string, nullable | | ```json { "status": true, "data": { "client": { "id": 1, "name": "Jane Doe", "client_type": "client type", "company_name": "Jane Doe", "company_type": "company type", "nipt": "nipt", "first_name": "Jane", "surname": "Jane Doe", "birthday": "birthday", "id_type": "id type", "id_num": "id num", "nationality_code": "nationality code", "nationality_id": 1, "telephone": "+15551234567", "email": "jane@example.com", "address": "1 Example Street", "city": "Berlin", "customer_number": "customer number", "created_at": "created at" } } } ``` **403** — Abonimi ka mbaruar, ose veprimi nuk lejohet per kete llogari. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **409** — Ekziston tashme nje regjistrim me te njejtat te dhena. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **422** — Te dhenat nuk kaluan validimin. Kjo pergjigje perdor fushen `success`, jo `status`. | Field | Type | Description | | --- | --- | --- | | `success` | boolean | Always false | | `message` | string | A single summary line, the same for every validation failure | | `errors` | object | The failing fields, each with the messages for it. Dotted keys point into nested objects and array items, e.g. `lines.0.quantity` | ```json { "success": true, "message": "Hello there", "errors": [] } ``` **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`. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **500** — Gabim i papritur ne server. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` ### PUT /api/v1/clients/{id} Perditeso klient Perditeson nje klient ekzistues. Trupi ka te njejtin format si `POST /clients`, prandaj vlejne te njejtat fusha te detyrueshme sipas `client_type`. Full URL: `https://fature.al/api/v1/clients/{id}` API version: `v1`. Authentication: required (bearer token). #### Path parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `id` | integer | yes | ID e klientit. | #### Body parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `nationality_code` | string, minLength 3, maxLength 3, nullable | no | Kodi ISO 3166-1 alpha-3 i kombesise. Pa te merret ALB. | | `nationality_id` | integer, nullable | no | ID e nacionalitetit ne fature.al. Plotesohet vete nga nationality_code. | | `telephone` | string, maxLength 255, nullable | no | Telefoni. | | `email` | string, maxLength 255, nullable | no | Email. | | `customer_number` | string, maxLength 30, nullable | no | Numri unik i klientit ne sistemin tuaj. | | `gender` | string, maxLength 10, nullable | no | Gjinia, vetem per PERSON. | | `birthday` | string, nullable | no | Data e lindjes (YYYY-MM-DD). | #### Example request ```bash curl -X PUT 'https://fature.al/api/v1/clients/42' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "nationality_code": "ALB", "nationality_id": 1, "telephone": "+355691234567", "email": "klient@example.com", "customer_number": "CLI-001", "gender": "M", "birthday": "1990-01-15" }' ``` #### Responses **200** — OK | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.client` | object | | | `data.client.id` | integer | | | `data.client.name` | string | | | `data.client.client_type` | string, nullable | | | `data.client.company_name` | string, nullable | | | `data.client.company_type` | string, nullable | | | `data.client.nipt` | string, nullable | | | `data.client.first_name` | string, nullable | | | `data.client.surname` | string, nullable | | | `data.client.birthday` | string, nullable | | | `data.client.id_type` | string, nullable | | | `data.client.id_num` | string, nullable | | | `data.client.nationality_code` | string, nullable | | | `data.client.nationality_id` | integer, nullable | | | `data.client.telephone` | string, nullable | | | `data.client.email` | string, nullable | | | `data.client.address` | string, nullable | | | `data.client.city` | string, nullable | | | `data.client.customer_number` | string, nullable | | | `data.client.created_at` | string, nullable | | ```json { "status": true, "data": { "client": { "id": 1, "name": "Jane Doe", "client_type": "client type", "company_name": "Jane Doe", "company_type": "company type", "nipt": "nipt", "first_name": "Jane", "surname": "Jane Doe", "birthday": "birthday", "id_type": "id type", "id_num": "id num", "nationality_code": "nationality code", "nationality_id": 1, "telephone": "+15551234567", "email": "jane@example.com", "address": "1 Example Street", "city": "Berlin", "customer_number": "customer number", "created_at": "created at" } } } ``` **403** — Abonimi ka mbaruar, ose veprimi nuk lejohet per kete llogari. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **404** — Klienti nuk u gjet, ose nuk i perket kompanise suaj. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **409** — Ekziston tashme nje klient me te njejtat te dhena. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **422** — Te dhenat nuk kaluan validimin. Kjo pergjigje perdor fushen `success`, jo `status`. | Field | Type | Description | | --- | --- | --- | | `success` | boolean | Always false | | `message` | string | A single summary line, the same for every validation failure | | `errors` | object | The failing fields, each with the messages for it. Dotted keys point into nested objects and array items, e.g. `lines.0.quantity` | ```json { "success": true, "message": "Hello there", "errors": [] } ``` **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`. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **500** — Gabim i papritur ne server. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` ### GET /api/v1/clients/{id}/details Detajet e klientit sipas ID Kthen nje klient te vetem me te gjitha fushat, si per kompani ashtu edhe per person. Fushat qe nuk i perkasin llojit te klientit kthehen `null`. Full URL: `https://fature.al/api/v1/clients/{id}/details` API version: `v1`. Authentication: required (bearer token). #### Path parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `id` | integer | yes | ID e klientit. | #### Example request ```bash curl -X GET 'https://fature.al/api/v1/clients/42/details' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — OK | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.client` | object | | | `data.client.id` | integer | | | `data.client.name` | string | | | `data.client.client_type` | string, nullable | | | `data.client.company_name` | string, nullable | | | `data.client.company_type` | string, nullable | | | `data.client.nipt` | string, nullable | | | `data.client.first_name` | string, nullable | | | `data.client.surname` | string, nullable | | | `data.client.birthday` | string, nullable | | | `data.client.id_type` | string, nullable | | | `data.client.id_num` | string, nullable | | | `data.client.nationality_code` | string, nullable | | | `data.client.nationality_id` | integer, nullable | | | `data.client.telephone` | string, nullable | | | `data.client.email` | string, nullable | | | `data.client.address` | string, nullable | | | `data.client.city` | string, nullable | | | `data.client.customer_number` | string, nullable | | | `data.client.created_at` | string, nullable | | ```json { "status": true, "data": { "client": { "id": 1, "name": "Jane Doe", "client_type": "client type", "company_name": "Jane Doe", "company_type": "company type", "nipt": "nipt", "first_name": "Jane", "surname": "Jane Doe", "birthday": "birthday", "id_type": "id type", "id_num": "id num", "nationality_code": "nationality code", "nationality_id": 1, "telephone": "+15551234567", "email": "jane@example.com", "address": "1 Example Street", "city": "Berlin", "customer_number": "customer number", "created_at": "created at" } } } ``` **404** — Klienti nuk u gjet, ose nuk i perket kompanise suaj. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **500** — Gabim i papritur ne server. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` ## Produkte (v1) Katalogu i produkteve dhe kategorite e tyre: lista, detajet, krijimi dhe perditesimi. Keta jane artikujt qe dalin si rreshta ne fature. ### GET /api/v1/product/categories Lista e kategorive Merrni listen e kategorive te produkteve per kompanine tuaj. Kthehen te gjitha ne nje pergjigje te vetme, pa faqosje. Kur limiti i kerkesave arrihet ose ndodh nje gabim i papritur, pergjigja kthehet me HTTP 200 dhe `status: false`, prandaj lexoni `status` dhe jo vetem kodin HTTP. Full URL: `https://fature.al/api/v1/product/categories` API version: `v1`. Authentication: required (bearer token). #### Example request ```bash curl -X GET 'https://fature.al/api/v1/product/categories' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — OK | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | array | | | `data[].id` | integer | | | `data[].name` | string | | | `data[].color` | string, nullable | Hex colour used by the POS grid | ```json { "status": true, "data": [ { "id": 1, "name": "Jane Doe", "color": "color" } ] } ``` ### GET /api/v1/products 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 ``` Kur limiti i kerkesave arrihet ose ndodh nje gabim i papritur, pergjigja kthehet me HTTP 200 dhe `status: false`, prandaj lexoni `status` dhe jo vetem kodin HTTP. Full URL: `https://fature.al/api/v1/products` API version: `v1`. Authentication: required (bearer token). #### Query parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `query` | string | no | Kerkim ne emer, kod ose pershkrim te produktit. | | `id_category` | integer | no | Vetem produktet e kesaj kategorie, nga GET /product/categories. | | `service` | boolean | no | true kthen vetem sherbimet, false vetem artikujt e inventarit. Pa te kthehen te dyja. | | `limit` | integer | no | Sa produkte te kthehen, deri ne 500. Pa te kthehet i gjithe katalogu. | | `offset` | integer | no | Nga cili produkt te fillohet. Zbatohet vetem bashke me `limit`. Defaults to `0`. | #### Example request ```bash curl -X GET 'https://fature.al/api/v1/products' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — OK | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | array | | | `data[].id` | integer | | | `data[].code` | string, nullable | Unique product code | | `data[].name` | string | | | `data[].description` | string, nullable | | | `data[].unit` | string, nullable | Unit of measure, derived from unit_code | | `data[].unit_code` | string, nullable | Unit of measure code, e.g. C62, XPP, LTR | | `data[].last_price` | number | Sale price | | `data[].cost_price` | number, nullable | Purchase price, when one is recorded | | `data[].vat_rate` | number | VAT rate percent: 0, 6, 10 or 20 | | `data[].vat_exempt_type` | string, nullable | VAT exemption type, when the product is exempt | | `data[].vat_exempt_description` | string, nullable | The exemption type spelled out in the account language | | `data[].currency` | string, nullable | | | `data[].id_category` | integer, nullable | | | `pagination` | object | | | `pagination.records` | integer | | | `pagination.total` | integer | | | `pagination.limit` | integer, nullable | | | `pagination.offset` | integer | | ```json { "status": true, "data": [ { "id": 1, "code": "code", "name": "Jane Doe", "description": "A short description.", "unit": "unit", "unit_code": "unit code", "last_price": 1999, "cost_price": 1999, "vat_rate": 19.99, "vat_exempt_type": "vat exempt type", "vat_exempt_description": "A short description.", "currency": "USD", "id_category": 1 } ], "pagination": { "records": 1, "total": 4200, "limit": 25, "offset": 0 } } ``` ### POST /api/v1/products Krijo produkt Krijon nje produkt te ri per kompanine tuaj. - **`code` gjenerohet vete** nese nuk e dergoni, prandaj mund ta lini bosh dhe ta ruani ate qe ju kthehet. - **`unit` nuk dergohet**: njesia matese derivohet nga `unit_code`, i cili eshte kodi qe mban dokumenti fiskal. - `vat_rate` pranon `0`, `6`, `10` ose `20`. Per nje produkt te perjashtuar shtoni `vat_exempt_type`. Produkti i krijuar ketu del menjehere ne `GET /products` dhe mund te perdoret ne rreshtat e nje fature. Full URL: `https://fature.al/api/v1/products` API version: `v1`. Authentication: required (bearer token). #### Body parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `code` | string, maxLength 255, nullable | no | Kodi unik i produktit. Gjenerohet vete nese mungon. | | `name` | string, maxLength 255 | yes | Emri i produktit. | | `description` | string, maxLength 255, nullable | no | Pershkrimi. Pa te merret emri. | | `last_price` | number, min 0 | yes | Cmimi i shitjes. | | `cost_price` | number, min 0, nullable | no | Cmimi i blerjes. | | `vat_rate` | string, one of 0, 6, 10, 20 | yes | Shkalla e TVSH. | | `currency` | string, maxLength 10, nullable | no | Monedha. Pa te merret ALL. | | `service` | boolean | no | Sherbim (true) apo artikull inventarizues (false). Pa te merret true. | | `id_category` | integer, nullable | no | ID e kategorise, nga GET /product/categories. | #### Example request ```bash curl -X POST 'https://fature.al/api/v1/products' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "code": "P001", "name": "Kafe Espresso", "description": "Kafe espresso e peshuar 18g", "last_price": 150, "cost_price": 80, "vat_rate": 20, "currency": "ALL", "service": true, "id_category": 3 }' ``` #### Responses **201** — Created | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.product` | object | | | `data.product.service` | boolean | True for a service, false for an article that is tracked in stock | | `data.product.category` | object, nullable | The category resolved, or null when the product has none | | `data.product.category.id` | integer | | | `data.product.category.name` | string | | | `data.product.category.color` | string, nullable | Hex colour used by the POS grid | | `data.product.created_at` | string, nullable | Creation timestamp, ISO 8601 | ```json { "status": true, "data": { "product": { "service": true, "category": { "id": 1, "name": "Jane Doe", "color": "color" }, "created_at": "created at" } } } ``` **403** — Abonimi ka mbaruar, ose veprimi nuk lejohet per kete llogari. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **409** — Ekziston tashme nje regjistrim me te njejtat te dhena. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **422** — Te dhenat nuk kaluan validimin. Kjo pergjigje perdor fushen `success`, jo `status`. | Field | Type | Description | | --- | --- | --- | | `success` | boolean | Always false | | `message` | string | A single summary line, the same for every validation failure | | `errors` | object | The failing fields, each with the messages for it. Dotted keys point into nested objects and array items, e.g. `lines.0.quantity` | ```json { "success": true, "message": "Hello there", "errors": [] } ``` **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`. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **500** — Gabim i papritur ne server. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` ### PUT /api/v1/products/{id} Perditeso produkt Perditeson nje produkt ekzistues. Trupi ka te njejtin format si `POST /products`, prandaj `unit_code` dhe `vat_rate` vlejne me te njejtat rregulla. Ndryshimi i cmimit nuk prek faturat e leshuara: ato mbajne cmimin me te cilin u shiten. Full URL: `https://fature.al/api/v1/products/{id}` API version: `v1`. Authentication: required (bearer token). #### Path parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `id` | integer | yes | ID e produktit. | #### Body parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `code` | string, maxLength 255, nullable | no | Kodi unik i produktit. Gjenerohet vete nese mungon. | | `name` | string, maxLength 255 | yes | Emri i produktit. | | `description` | string, maxLength 255, nullable | no | Pershkrimi. Pa te merret emri. | | `last_price` | number, min 0 | yes | Cmimi i shitjes. | | `cost_price` | number, min 0, nullable | no | Cmimi i blerjes. | | `vat_rate` | string, one of 0, 6, 10, 20 | yes | Shkalla e TVSH. | | `currency` | string, maxLength 10, nullable | no | Monedha. Pa te merret ALL. | | `service` | boolean | no | Sherbim (true) apo artikull inventarizues (false). Pa te merret true. | | `id_category` | integer, nullable | no | ID e kategorise, nga GET /product/categories. | #### Example request ```bash curl -X PUT 'https://fature.al/api/v1/products/42' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "code": "P001", "name": "Kafe Espresso", "description": "Kafe espresso e peshuar 18g", "last_price": 150, "cost_price": 80, "vat_rate": 20, "currency": "ALL", "service": true, "id_category": 3 }' ``` #### Responses **200** — OK | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.product` | object | | | `data.product.service` | boolean | True for a service, false for an article that is tracked in stock | | `data.product.category` | object, nullable | The category resolved, or null when the product has none | | `data.product.category.id` | integer | | | `data.product.category.name` | string | | | `data.product.category.color` | string, nullable | Hex colour used by the POS grid | | `data.product.created_at` | string, nullable | Creation timestamp, ISO 8601 | ```json { "status": true, "data": { "product": { "service": true, "category": { "id": 1, "name": "Jane Doe", "color": "color" }, "created_at": "created at" } } } ``` **403** — Abonimi ka mbaruar, ose veprimi nuk lejohet per kete llogari. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **404** — Produkti nuk u gjet, ose nuk i perket kompanise suaj. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **409** — Ekziston tashme nje produkt me kete kod. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **422** — Te dhenat nuk kaluan validimin. Kjo pergjigje perdor fushen `success`, jo `status`. | Field | Type | Description | | --- | --- | --- | | `success` | boolean | Always false | | `message` | string | A single summary line, the same for every validation failure | | `errors` | object | The failing fields, each with the messages for it. Dotted keys point into nested objects and array items, e.g. `lines.0.quantity` | ```json { "success": true, "message": "Hello there", "errors": [] } ``` **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`. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **500** — Gabim i papritur ne server. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` ### GET /api/v1/products/{id}/details Detajet e produktit sipas ID Merrni detajet e nje produkti sipas id-se per kompanine tuaj. Kthen me shume se lista: pervec emrit dhe cmimit, edhe kodin fiskal te njesise, normen e TVSH-se dhe kategorine. Full URL: `https://fature.al/api/v1/products/{id}/details` API version: `v1`. Authentication: required (bearer token). #### Path parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `id` | integer | yes | ID e produktit. | #### Example request ```bash curl -X GET 'https://fature.al/api/v1/products/42/details' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — OK | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.product` | object | | | `data.product.service` | boolean | True for a service, false for an article that is tracked in stock | | `data.product.category` | object, nullable | The category resolved, or null when the product has none | | `data.product.category.id` | integer | | | `data.product.category.name` | string | | | `data.product.category.color` | string, nullable | Hex colour used by the POS grid | | `data.product.created_at` | string, nullable | Creation timestamp, ISO 8601 | ```json { "status": true, "data": { "product": { "service": true, "category": { "id": 1, "name": "Jane Doe", "color": "color" }, "created_at": "created at" } } } ``` **404** — Produkti nuk u gjet, ose nuk i perket kompanise suaj. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **500** — Gabim i papritur ne server. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` ## Llogaritë bankare (v1) Llogarite bankare te kompanise, ashtu sic dalin si informacion pagese ne faturat jo-cash dhe elektronike. Vetem lexim: nje llogari e re shtohet gjate regjistrimit ose nga paneli. ### GET /api/v1/bank-accounts Lista e llogarive bankare Merr listen e llogarive bankare aktive te kompanise me faqosje dhe filtrim me tekst. Full URL: `https://fature.al/api/v1/bank-accounts` API version: `v1`. Authentication: required (bearer token). #### Query parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `limit` | integer | no | Numri i llogarive per faqe (max 100). Defaults to `20`. | | `offset` | integer | no | Nga cila llogari te fillohet. Defaults to `0`. | | `query` | string | no | Kerkim ne emer te bankes, IBAN, SWIFT, mbajtes ose shenime. | #### Example request ```bash curl -X GET 'https://fature.al/api/v1/bank-accounts' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — OK | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.items` | array | | | `data.items[].id` | integer | | | `data.items[].bank_name` | string, nullable | | | `data.items[].iban` | string, nullable | | | `data.items[].swift` | string, nullable | | | `data.items[].holder` | string, nullable | | | `data.items[].currency_code` | string, nullable | | | `data.items[].is_default` | boolean | | | `data.items[].notes` | string, nullable | | | `data.items[].valid_from` | string, nullable | | | `data.items[].valid_to` | string, nullable | | | `data.items[].created_at` | string, nullable | | | `data.pagination` | object | | | `data.pagination.records` | integer | | | `data.pagination.total` | integer | | | `data.pagination.limit` | integer | | | `data.pagination.offset` | integer | | ```json { "status": true, "data": { "items": [ { "id": 1, "bank_name": "Jane Doe", "iban": "iban", "swift": "swift", "holder": "holder", "currency_code": "USD", "is_default": true, "notes": "notes", "valid_from": "valid from", "valid_to": "valid to", "created_at": "created at" } ], "pagination": { "records": 1, "total": 4200, "limit": 25, "offset": 0 } } } ``` **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`. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **500** — Gabim i papritur ne server. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` ## Monedhat (v1) Monedhat e konfiguruara per kompanine dhe kursi i kembimit i dites, i marre nga kursi.al. ### GET /api/v1/currencies Lista e monedhave Kthen monedhat e konfiguruara per kompanine, me ALL gjithmone ne fillim. Full URL: `https://fature.al/api/v1/currencies` API version: `v1`. Authentication: required (bearer token). #### Example request ```bash curl -X GET 'https://fature.al/api/v1/currencies' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — OK | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.currencies` | array | | | `data.currencies[].id` | integer | | | `data.currencies[].code` | string | | | `data.currencies[].name` | string | | ```json { "status": true, "data": { "currencies": [ { "id": 1, "code": "code", "name": "Jane Doe" } ] } } ``` ### GET /api/v1/exchange-rates Kursi i kembimit Kthen kursin e shitjes se dites per cdo monedhe, sipas burimit te zgjedhur. Te dhenat vijne nga `https://api.kursi.al/api/rates` dhe ruhen ne cache per nje ore ne server, prandaj klienti mund ta mbaje snapshot-in e fundit lokalisht dhe te punoje edhe pa internet. Burimet e mbeshtetura (vlera `source` ne kerkese): - `BOA` -> Banka e Shqiperise (kursi zyrtar) - `BKT` -> Banka Kombetare Tregtare - `Iliria98` -> Kembim Valutor "Iliria '98" - `ADON` -> Kembim Valutor "Adon" Nje burim i papercaktuar kthehet automatikisht ne `BOA`. Fusha `source` ne pergjigje eshte gjithmone vlera e normalizuar. Full URL: `https://fature.al/api/v1/exchange-rates` API version: `v1`. Authentication: required (bearer token). #### Query parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `source` | string | no | Burimi i kursit: BOA, BKT, Iliria98 ose ADON. Defaults to `BOA`. | #### Example request ```bash curl -X GET 'https://fature.al/api/v1/exchange-rates' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — OK | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.rates` | object | | | `data.source` | string | | | `data.fetchedAt` | string | | ```json { "status": true, "data": { "rates": [], "source": "source", "fetchedAt": "fetchedAt" } } ``` ## Fletë shoqëruese (v1) Fletet shoqeruese (WTN) per mallin qe leviz midis njesive ose drejt nje klienti pa qene shitje: krijimi, lista, detajet dhe te dhenat per printim. ### GET /api/v1/invoice/wtn Lista e faturave shoqeruese (WTN) Merr listen e faturave shoqeruese me faqosje dhe filtrim sipas datave. Faqezohet me `limit` dhe `offset`. `pagination` kthen vetem numeruesit e faqes, pa nje total, prandaj ndaloni kur nje faqe vjen me e shkurter se `limit`. Full URL: `https://fature.al/api/v1/invoice/wtn` API version: `v1`. Authentication: required (bearer token). #### Query parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `limit` | integer | no | Numri i faturave per faqe. Defaults to `20`. | | `offset` | integer | no | Nga cila fature te fillohet. Defaults to `0`. | | `fromDate` | string | no | Data e fillimit (YYYY-MM-DD). | | `toDate` | string | no | Data e perfundimit (YYYY-MM-DD). | #### Example request ```bash curl -X GET 'https://fature.al/api/v1/invoice/wtn' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — OK | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `message` | any | | ```json { "status": false, "message": "Hello there" } ``` ### POST /api/v1/invoice/wtn Krijo fature shoqeruese (WTN) Fleta shoqeruese nuk eshte shitje: shoqeron mall qe leviz nga nje pike ne tjetren, dhe kerkohet nga ligji edhe kur asgje nuk shitet. Rreshtat quhen `invoice_lines`, jo `lines` si tek faturat. ## Fushat e detyrueshme - `vehPlates`, targa e automjetit; - `valueOfGoods`, vlera e mallit qe udheton; - `invoice_lines`, te pakten nje rresht. ## Vlerat e lejuara | Fusha | Vlerat | | --- | --- | | `type` | `WTN`, `SALE` | | `transaction` | `TRANSFER`, `EXAMINATION`, `SALES`, `DOOR` | | `vehOwnership` | `OWNER`, `THIRDPARTY` | | `startPoint`, `destinPoint` | `ANOTHER`, `CUSTOMS`, `EXHIBITION`, `OTHER`, `SALE`, `STORE`, `WAREHOUSE` | | `carrier_id_type` | `NUIS`, `ID` | Full URL: `https://fature.al/api/v1/invoice/wtn` API version: `v1`. Authentication: required (bearer token). #### Body parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `vehPlates` | string | yes | Targa e automjetit. | | `valueOfGoods` | number | yes | Vlera e mallrave, ne ALL. | | `invoice_lines` | array | yes | Rreshtat e mallit, minimumi nje rresht. | | `invoice_lines[].product_name` | string, maxLength 255 | yes | Emri ose pershkrimi i mallit. | | `invoice_lines[].product_code` | string, maxLength 50 | yes | Kodi i mallit. | | `invoice_lines[].unit` | string, maxLength 50 | yes | Njesia matese. | | `invoice_lines[].quantity` | number | yes | Sasia, gjithmone me e madhe se 0. | | `startCity` | string, nullable | no | Qyteti i nisjes. | | `startAddr` | string, nullable | no | Adresa e nisjes. | | `destinCity` | string, nullable | no | Qyteti i destinacionit. | | `destinAddr` | string, nullable | no | Adresa e destinacionit. | | `carrier_id_num` | string, nullable | no | ID ose NIPT i transportuesit. | | `carrier_name` | string, nullable | no | Emri i transportuesit. | | `carrier_town` | string, nullable | no | Qyteti i transportuesit. | | `carrier_address` | string, nullable | no | Adresa e transportuesit. | #### Example request ```bash curl -X POST 'https://fature.al/api/v1/invoice/wtn' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "vehPlates": "AA123BB", "valueOfGoods": 10000, "invoice_lines": [ { "product_name": "Kafe", "product_code": "K1", "unit": "cope", "quantity": 5 } ], "startCity": "Tirane", "startAddr": "Rruga X", "destinCity": "Durres", "destinAddr": "Rruga Y", "carrier_id_num": "L01234567A", "carrier_name": "Transport SHPK", "carrier_town": "Tirane", "carrier_address": "Rruga Z" }' ``` #### Responses **201** — Created | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `message` | any | | ```json { "status": false, "message": "Hello there" } ``` ### GET /api/v1/invoice/wtn/print/{id} Te dhenat e fatures shoqeruese ne format printimi (JSON) Kthen te dhenat e fletes si JSON, jo nje PDF, qe ta formatoni vete dokumentin. Perdoreni kur printoni me nje sistem tuajin. Per dokumentin e gatshem perdorni PDF-ne e fletes. Full URL: `https://fature.al/api/v1/invoice/wtn/print/{id}` API version: `v1`. Authentication: required (bearer token). #### Path parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `id` | integer | yes | ID e fatures shoqeruese ne fature.al. | #### Example request ```bash curl -X GET 'https://fature.al/api/v1/invoice/wtn/print/403' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — OK | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | any | | ```json { "status": true, "data": "data" } ``` ### GET /api/v1/invoice/wtn/{id}/details Detajet e fatures shoqeruese sipas ID Kthen fleten e plote: automjetin, piket e nisjes dhe te mberritjes, transportuesin dhe rreshtat e mallit. Full URL: `https://fature.al/api/v1/invoice/wtn/{id}/details` API version: `v1`. Authentication: required (bearer token). #### Path parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `id` | integer | yes | ID e fatures shoqeruese ne fature.al. | #### Example request ```bash curl -X GET 'https://fature.al/api/v1/invoice/wtn/403/details' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — OK | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `message` | any | | ```json { "status": false, "message": "Hello there" } ``` ## Faturat e blerjes (v1) Faturat qe kompania ka marre nga furnitoret, ashtu sic vijne nga sistemi i e-faturave. Vetem lexim: keto dokumente nuk leshohen ketu. ### GET /api/v1/purchase-invoices Lista e faturave te blerjes Merrni faturat qe furnitoret ju kane leshuar juve, ashtu sic i ka regjistruar sistemi fiskal. Furnitori nuk ju dergon gje: dokumentet vijne nga tatimet. Per cdo fature terhiqen te dhenat e plota: artikujt, shitesi, bleresi, TVSH-ja dhe menyrat e pageses. Kjo e ben rakordimin e blerjeve dhe te TVSH-se te mundur pa asnje hap manual. ## Faqezimi Ky endpoint lexon nga fiskalizimi, jo nga baza jone, prandaj faqezohet me `page` qe fillon nga `1` dhe jo me `limit` me `offset`. Perseritni me `page + 1` derisa `items` te kthehet bosh. Pa `fromDate` dhe `toDate` merret dita e sotme, jo e gjithe historia. Full URL: `https://fature.al/api/v1/purchase-invoices` API version: `v1`. Authentication: required (bearer token). #### Query parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `fromDate` | string | no | Data e fillimit (YYYY-MM-DD). Pa te merret sot. | | `toDate` | string | no | Data e perfundimit (YYYY-MM-DD). Pa te merret sot. | | `fic` | string | no | Filtro sipas FIC per nje fature te vetme. | | `page` | integer | no | Faqja e listes nga fiskalizimi. Perserit me page+1 derisa items te kthehet bosh. Defaults to `1`. | #### Example request ```bash curl -X GET 'https://fature.al/api/v1/purchase-invoices' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — OK | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.items` | array | | | `data.items[].iic` | string | | | `data.items[].fic` | string | | | `data.items[].invoiceNumber` | string | | | `data.items[].invoiceOrderNumber` | integer | | | `data.items[].dateTimeCreated` | string | | | `data.items[].payDeadline` | string, nullable | | | `data.items[].invoiceType` | string | | | `data.items[].issuerTaxNumber` | string | | | `data.items[].seller` | object | | | `data.items[].seller.idType` | string | | | `data.items[].seller.idNum` | string | | | `data.items[].seller.name` | string | | | `data.items[].seller.address` | string, nullable | | | `data.items[].seller.town` | string, nullable | | | `data.items[].seller.country` | string, nullable | | | `data.items[].buyer` | object | | | `data.items[].buyer.idType` | string | | | `data.items[].buyer.idNum` | string | | | `data.items[].buyer.name` | string | | | `data.items[].buyer.address` | string, nullable | | | `data.items[].buyer.town` | string, nullable | | | `data.items[].buyer.country` | string, nullable | | | `data.items[].items` | array | | | `data.items[].items[].name` | string | | | `data.items[].items[].code` | string, nullable | | | `data.items[].items[].unit` | string, nullable | | | `data.items[].items[].quantity` | number | | | `data.items[].items[].unitPriceAfterVat` | number | | | `data.items[].items[].priceAfterVat` | number | | | `data.items[].items[].vatAmount` | number | | | `data.items[].items[].vatRate` | number, nullable | | | `data.items[].items[].exemptFromVat` | string, nullable | | | `data.items[].paymentMethod` | array | | | `data.items[].paymentMethod[].typeCode` | string | | | `data.items[].paymentMethod[].compCard` | string, nullable | | | `data.items[].currency` | object, nullable | | | `data.items[].currency.code` | string | | | `data.items[].currency.exchangeRate` | number | | | `data.items[].totalPrice` | number | | | `data.items[].totalPriceWithoutVAT` | number | | | `data.items[].reverseCharge` | boolean | | | `data.items[].businessUnit` | string, nullable | | | `data.items[].operatorCode` | string, nullable | | | `data.items[].tcrCode` | string, nullable | | | `data.items[].softwareCode` | string, nullable | | | `data.items[].iicSignature` | string, nullable | | | `data.pagination` | object | | | `data.pagination.records` | integer | | | `data.pagination.page` | integer | | ```json { "status": true, "data": { "items": [ { "iic": "iic", "fic": "fic", "invoiceNumber": "invoiceNumber", "invoiceOrderNumber": 1, "dateTimeCreated": "dateTimeCreated", "payDeadline": "payDeadline", "invoiceType": "invoiceType", "issuerTaxNumber": "issuerTaxNumber", "seller": { "idType": "idType", "idNum": "idNum", "name": "Jane Doe", "address": "1 Example Street", "town": "town", "country": "US" }, "buyer": { "idType": "idType", "idNum": "idNum", "name": "Jane Doe", "address": "1 Example Street", "town": "town", "country": "US" }, "items": [ { "name": "Jane Doe", "code": "code", "unit": "unit", "quantity": 2, "unitPriceAfterVat": 1999, "priceAfterVat": 1999, "vatAmount": 4200, "vatRate": 19.99, "exemptFromVat": "exemptFromVat" } ], "paymentMethod": [ { "typeCode": "typeCode", "compCard": "compCard" } ], "currency": { "code": "code", "exchangeRate": 19.99 }, "totalPrice": 4200, "totalPriceWithoutVAT": 4200, "reverseCharge": true, "businessUnit": "businessUnit", "operatorCode": "operatorCode", "tcrCode": "tcrCode", "softwareCode": "softwareCode", "iicSignature": "iicSignature" } ], "pagination": { "records": 1, "page": 1 } } } ``` **422** — Formati i datave nuk eshte YYYY-MM-DD. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **500** — Gabim i papritur ne server. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **502** — Fiskalizimi u pergjigj me nje gabim. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **503** — Sherbimi i fiskalizimit eshte i paarritshem. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` ## Llogaria (v1) Kush eshte perdoruesi qe mban token-in: emri, kompania, NIPT-i, njesia e biznesit, kodi fiskal dhe te drejtat. Eshte thirrja e pare e dobishme kur nis nje integrim, sepse tregon me cfare konteksti do te leshohen faturat. ### GET /api/v1/account Te dhenat e llogarise Kthen te dhenat e perdoruesit te autentifikuar: emri, email, kodi fiskal dhe kompania. Full URL: `https://fature.al/api/v1/account` API version: `v1`. Authentication: required (bearer token). #### Example request ```bash curl -X GET 'https://fature.al/api/v1/account' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — OK | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.name` | string | | | `data.email` | string | | | `data.fiscalCode` | any | | | `data.company` | any | | | `data.nipt` | any | | | `data.setupFinished` | boolean | | | `data.branch` | object | | | `data.branch.name` | string | | | `data.branch.address` | any | | | `data.branch.city` | any | | | `data.companyBranches` | any | | | `data.permissions` | object | | | `data.permissions.createArticles` | boolean | | | `data.permissions.createClients` | boolean | | | `data.configs` | object | | | `data.configs.openDayAlways0` | any | | | `data.vatConfigs` | object | | | `data.vatConfigs.issuerInVat` | any | | | `data.vatConfigs.vat_rates` | any | | | `data.vatConfigs.vat_exempts` | any | | | `data.subscription` | object | | | `data.subscription.cash` | any | | | `data.subscription.noncash` | any | | | `data.subscription.einvoice` | any | | | `data.subscription.wtn` | any | | ```json { "status": true, "data": { "name": "Jane Doe", "email": "jane@example.com", "fiscalCode": "fiscalCode", "company": "company", "nipt": "nipt", "setupFinished": true, "branch": { "name": "Jane Doe", "address": "1 Example Street", "city": "Berlin" }, "companyBranches": "companyBranches", "permissions": { "createArticles": true, "createClients": true }, "configs": { "openDayAlways0": "openDayAlways0" }, "vatConfigs": { "issuerInVat": "issuerInVat", "vat_rates": "vat rates", "vat_exempts": "vat exempts" }, "subscription": { "cash": "cash", "noncash": "noncash", "einvoice": "einvoice", "wtn": "wtn" } } } ``` ## Paneli (v1) Permbledhja e dites ne nje thirrje te vetme: turni i hapur, shitjet e sotme perballe atyre te djeshme, gjendja e arkes dhe faturat e fundit. Pergjigja ruhet ne cache per pak sekonda, prandaj eshte per ekran, jo per rakordim. ### GET /api/v1/dashboard/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. Full URL: `https://fature.al/api/v1/dashboard/summary` API version: `v1`. Authentication: required (bearer token). #### Example request ```bash curl -X GET 'https://fature.al/api/v1/dashboard/summary' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — OK | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | any | | ```json { "status": true, "data": "data" } ``` **429** — Kufiri i kerkesave u arrit: 30 kerkesa ne minute. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` ## Raportet (v1) Shifra te grumbulluara mbi nje periudhe: shitjet, TVSH-ja, ecuria ditore, klientet dhe produktet kryesore, shitjet sipas operatorit dhe sipas pajisjes, arka dhe fletet shoqeruese. Llogaritja behet ne bazen e te dhenave, prandaj nje raport i pergjigjet pyetjes me shpejt dhe me sakte se marrja e faturave nje nga nje. ### GET /api/v1/reports/by-operator Shitjet sipas operatorit Sa fatura leshoi dhe sa vlere beri secili operator ne periudhe. Perdoret per krahasim mes turneve dhe per shperblime sipas shitjes. * `from` dhe `to` jane te detyrueshme, ne formatin `YYYY-MM-DD`, dhe periudha kthehet e konfirmuar ne `period` te pergjigjes. Full URL: `https://fature.al/api/v1/reports/by-operator` API version: `v1`. Authentication: required (bearer token). #### Query parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `from` | string | yes | Data e fillimit, e perfshire. | | `to` | string | yes | Data e perfundimit, e perfshire. | #### Example request ```bash curl -X GET 'https://fature.al/api/v1/reports/by-operator?from=2026-01-01&to=2026-01-31' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — OK | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.period` | object | | | `data.period.from` | string | Start date (YYYY-MM-DD), inclusive | | `data.period.to` | string | End date (YYYY-MM-DD), inclusive | | `data.items` | array | | | `data.items[].id_user` | integer, nullable | | | `data.items[].name` | string | | | `data.items[].operator_code` | string, nullable | | | `data.items[].invoices` | integer | | | `data.items[].gross` | number | | ```json { "status": true, "data": { "period": { "from": "from", "to": "to" }, "items": [ { "id_user": 1, "name": "Jane Doe", "operator_code": "operator code", "invoices": 1, "gross": 19.99 } ] } } ``` **422** — Datat mungojne ose nuk jane ne formatin YYYY-MM-DD. | Field | Type | Description | | --- | --- | --- | | `success` | boolean | Always false | | `message` | string | A single summary line, the same for every validation failure | | `errors` | object | The failing fields, each with the messages for it. Dotted keys point into nested objects and array items, e.g. `lines.0.quantity` | ```json { "success": true, "message": "Hello there", "errors": [] } ``` **429** — Kufiri i kerkesave u arrit: 30 raporte ne minute. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` ### GET /api/v1/reports/by-tcr Shitjet sipas pajisjes fiskale Sa fatura leshoi dhe sa vlere beri secila pajisje fiskale (TCR) ne periudhe. Nje biznes me disa njesi e perdor kete per te ndare shitjet sipas pikes se shitjes, sepse cdo TCR i perket nje njesie te vetme. * `from` dhe `to` jane te detyrueshme, ne formatin `YYYY-MM-DD`, dhe periudha kthehet e konfirmuar ne `period` te pergjigjes. Full URL: `https://fature.al/api/v1/reports/by-tcr` API version: `v1`. Authentication: required (bearer token). #### Query parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `from` | string | yes | Data e fillimit, e perfshire. | | `to` | string | yes | Data e perfundimit, e perfshire. | #### Example request ```bash curl -X GET 'https://fature.al/api/v1/reports/by-tcr?from=2026-01-01&to=2026-01-31' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — OK | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.period` | object | | | `data.period.from` | string | Start date (YYYY-MM-DD), inclusive | | `data.period.to` | string | End date (YYYY-MM-DD), inclusive | | `data.items` | array | | | `data.items[].tcr_code` | string, nullable | | | `data.items[].invoices` | integer | | | `data.items[].gross` | number | | ```json { "status": true, "data": { "period": { "from": "from", "to": "to" }, "items": [ { "tcr_code": "tcr code", "invoices": 1, "gross": 19.99 } ] } } ``` **422** — Datat mungojne ose nuk jane ne formatin YYYY-MM-DD. | Field | Type | Description | | --- | --- | --- | | `success` | boolean | Always false | | `message` | string | A single summary line, the same for every validation failure | | `errors` | object | The failing fields, each with the messages for it. Dotted keys point into nested objects and array items, e.g. `lines.0.quantity` | ```json { "success": true, "message": "Hello there", "errors": [] } ``` **429** — Kufiri i kerkesave u arrit: 30 raporte ne minute. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` ### GET /api/v1/reports/cash-register Gjendja e arkes per nje dite Gjendja e arkes fiskale per nje dite te vetme: hapja, mbyllja dhe **mbyllja e pritur**, bashke me shitjet sipas menyres se pageses dhe levizjet e parave. Mbyllja e pritur eshte ajo qe duhet te kete arka po te jete regjistruar gjithcka. Diferenca me mbylljen reale eshte pikerisht ajo qe kerkohet ne rakordim. Pa `date` merret dita e sotme. Formati eshte `YYYY-MM-DD`. Full URL: `https://fature.al/api/v1/reports/cash-register` API version: `v1`. Authentication: required (bearer token). #### Query parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `date` | string, nullable | no | Dita e raportit. Pa te merret sot. | #### Example request ```bash curl -X GET 'https://fature.al/api/v1/reports/cash-register' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — OK | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.date` | string | | | `data.currency` | string | | | `data.opening` | number | | | `data.closing` | number | | | `data.expected_closing` | number | | | `data.tcr` | string, nullable | | | `data.operator` | string | | | `data.sales_by_method` | array | | | `data.sales_by_method[].method` | string | | | `data.sales_by_method[].label` | string | | | `data.sales_by_method[].count` | integer | | | `data.sales_by_method[].gross` | number | | | `data.sales_by_method[].net` | number | | | `data.sales_by_method[].vat` | number | | | `data.movements` | object | | | `data.movements.deposits_count` | integer | | | `data.movements.deposits_total` | number | | | `data.movements.withdrawals_count` | integer | | | `data.movements.withdrawals_total` | number | | ```json { "status": true, "data": { "date": "date", "currency": "USD", "opening": 19.99, "closing": 19.99, "expected_closing": 19.99, "tcr": "tcr", "operator": "operator", "sales_by_method": [ { "method": "method", "label": "label", "count": 3, "gross": 19.99, "net": 19.99, "vat": 19.99 } ], "movements": { "deposits_count": 3, "deposits_total": 4200, "withdrawals_count": 3, "withdrawals_total": 4200 } } } ``` **422** — Datat mungojne ose nuk jane ne formatin YYYY-MM-DD. | Field | Type | Description | | --- | --- | --- | | `success` | boolean | Always false | | `message` | string | A single summary line, the same for every validation failure | | `errors` | object | The failing fields, each with the messages for it. Dotted keys point into nested objects and array items, e.g. `lines.0.quantity` | ```json { "success": true, "message": "Hello there", "errors": [] } ``` **429** — Kufiri i kerkesave u arrit: 30 raporte ne minute. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **500** — Gabim i papritur ne server. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` ### GET /api/v1/reports/cash-register/closing Raporti i mbylljes se arkes Raporti i fundit i dites, ai qe printohet kur mbyllet turni: totalet e shitjeve, produktet e shitura dhe levizjet e parave. Ndryshimi nga gjendja e arkes eshte fokusi: ky raport i perket **turnit qe u mbyll**, jo dites si periudhe. Pa `date` merret dita e sotme. Formati eshte `YYYY-MM-DD`. Full URL: `https://fature.al/api/v1/reports/cash-register/closing` API version: `v1`. Authentication: required (bearer token). #### Query parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `date` | string, nullable | no | Dita e raportit. Pa te merret sot. | #### Example request ```bash curl -X GET 'https://fature.al/api/v1/reports/cash-register/closing' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — OK | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.date` | string | | | `data.currency` | string | | | `data.opening` | number | | | `data.closing` | number | | | `data.closing_total` | number | | | `data.expected_closing` | number | | | `data.opened_at` | string, nullable | | | `data.closed_at` | string, nullable | | | `data.tcr` | string, nullable | | | `data.operator` | string | | | `data.sales` | object | | | `data.sales.invoice_count` | integer | | | `data.sales.gross_total` | number | | | `data.sales.net_total` | number | | | `data.sales.vat_total` | number | | | `data.sales_by_method` | array | | | `data.sales_by_method[].method` | string | | | `data.sales_by_method[].label` | string | | | `data.sales_by_method[].count` | integer | | | `data.sales_by_method[].gross` | number | | | `data.sales_by_method[].net` | number | | | `data.sales_by_method[].vat` | number | | | `data.products_sold` | array | | | `data.products_sold[].product_name` | string | | | `data.products_sold[].product_code` | string, nullable | | | `data.products_sold[].quantity` | number | | | `data.products_sold[].unit` | string, nullable | | | `data.products_sold[].unit_price` | number | | | `data.products_sold[].gross` | number | | | `data.movements` | object | | | `data.movements.deposits_count` | integer | | | `data.movements.deposits_total` | number | | | `data.movements.withdrawals_count` | integer | | | `data.movements.withdrawals_total` | number | | ```json { "status": true, "data": { "date": "date", "currency": "USD", "opening": 19.99, "closing": 19.99, "closing_total": 4200, "expected_closing": 19.99, "opened_at": "opened at", "closed_at": "closed at", "tcr": "tcr", "operator": "operator", "sales": { "invoice_count": 3, "gross_total": 4200, "net_total": 4200, "vat_total": 4200 }, "sales_by_method": [ { "method": "method", "label": "label", "count": 3, "gross": 19.99, "net": 19.99, "vat": 19.99 } ], "products_sold": [ { "product_name": "Jane Doe", "product_code": "product code", "quantity": 2, "unit": "unit", "unit_price": 1999, "gross": 19.99 } ], "movements": { "deposits_count": 3, "deposits_total": 4200, "withdrawals_count": 3, "withdrawals_total": 4200 } } } ``` **422** — Datat mungojne ose nuk jane ne formatin YYYY-MM-DD. | Field | Type | Description | | --- | --- | --- | | `success` | boolean | Always false | | `message` | string | A single summary line, the same for every validation failure | | `errors` | object | The failing fields, each with the messages for it. Dotted keys point into nested objects and array items, e.g. `lines.0.quantity` | ```json { "success": true, "message": "Hello there", "errors": [] } ``` **429** — Kufiri i kerkesave u arrit: 30 raporte ne minute. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` **500** — Gabim i papritur ne server. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` ### GET /api/v1/reports/daily-trend Ecuria ditore Nje pike per cdo dite te periudhes, gati per nje grafik. | `metric` | Cfare mat pika | | --- | --- | | `gross` | Vlera bruto e shitjeve | | `count` | Numri i faturave | Ditet pa shitje kthehen me vlere `0` dhe nuk hiqen nga seria, keshtu qe grafiku nuk shtrembrohet. `from` dhe `to` jane te detyrueshme, ne formatin `YYYY-MM-DD`, dhe periudha kthehet e konfirmuar ne `period` te pergjigjes. Full URL: `https://fature.al/api/v1/reports/daily-trend` API version: `v1`. Authentication: required (bearer token). #### Example request ```bash curl -X GET 'https://fature.al/api/v1/reports/daily-trend' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — OK | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.period` | object | | | `data.period.from` | string | Start date (YYYY-MM-DD), inclusive | | `data.period.to` | string | End date (YYYY-MM-DD), inclusive | | `data.metric` | string | | | `data.series` | array | | | `data.series[].date` | string | | | `data.series[].count` | integer | | | `data.series[].gross` | number | | ```json { "status": true, "data": { "period": { "from": "from", "to": "to" }, "metric": "metric", "series": [ { "date": "date", "count": 3, "gross": 19.99 } ] } } ``` **422** — Datat mungojne ose nuk jane ne formatin YYYY-MM-DD. | Field | Type | Description | | --- | --- | --- | | `success` | boolean | Always false | | `message` | string | A single summary line, the same for every validation failure | | `errors` | object | The failing fields, each with the messages for it. Dotted keys point into nested objects and array items, e.g. `lines.0.quantity` | ```json { "success": true, "message": "Hello there", "errors": [] } ``` **429** — Kufiri i kerkesave u arrit: 30 raporte ne minute. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` ### GET /api/v1/reports/reversals Faturat e anulluara Faturat e anulluara ne periudhe, secila e lidhur me faturen origjinale qe korrigjon. `limit` pranon nga `1` deri ne `500`. Perdoreni per te kontrolluar sa dhe pse anulohet, sepse nje numer i larte anulimesh eshte zakonisht shenje e nje problemi ne procesin e shitjes. * `from` dhe `to` jane te detyrueshme, ne formatin `YYYY-MM-DD`, dhe periudha kthehet e konfirmuar ne `period` te pergjigjes. Full URL: `https://fature.al/api/v1/reports/reversals` API version: `v1`. Authentication: required (bearer token). #### Example request ```bash curl -X GET 'https://fature.al/api/v1/reports/reversals' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — OK | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.period` | object | | | `data.period.from` | string | Start date (YYYY-MM-DD), inclusive | | `data.period.to` | string | End date (YYYY-MM-DD), inclusive | | `data.totals` | object | | | `data.totals.count` | integer | | | `data.totals.gross` | number | | | `data.items` | array | | | `data.items[].id` | integer | | | `data.items[].number` | string | | | `data.items[].type` | string | | | `data.items[].reversed_at` | string, nullable | | | `data.items[].original_invoice_id` | integer, nullable | | | `data.items[].gross` | number | | | `data.items[].operator` | string, nullable | | ```json { "status": true, "data": { "period": { "from": "from", "to": "to" }, "totals": { "count": 3, "gross": 19.99 }, "items": [ { "id": 1, "number": "number", "type": "type", "reversed_at": "reversed at", "original_invoice_id": 1, "gross": 19.99, "operator": "operator" } ] } } ``` **422** — Datat mungojne ose nuk jane ne formatin YYYY-MM-DD. | Field | Type | Description | | --- | --- | --- | | `success` | boolean | Always false | | `message` | string | A single summary line, the same for every validation failure | | `errors` | object | The failing fields, each with the messages for it. Dotted keys point into nested objects and array items, e.g. `lines.0.quantity` | ```json { "success": true, "message": "Hello there", "errors": [] } ``` **429** — Kufiri i kerkesave u arrit: 30 raporte ne minute. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` ### GET /api/v1/reports/sales-summary Permbledhje e shitjeve Totalet e shitjeve per nje periudhe, te llogaritura ne baze te te dhenave. Vlerat jane ne ALL. Ndarjet qe kthehen njeheresh: - sipas menyres se pageses; - sipas tipit te fatures; - sipas shkalles se TVSH; - sipas dites. Perfshin edhe sa fatura u anulluan, keshtu qe nuk ju duhet nje thirrje e dyte per t'i zbritur. * `from` dhe `to` jane te detyrueshme, ne formatin `YYYY-MM-DD`, dhe periudha kthehet e konfirmuar ne `period` te pergjigjes. Full URL: `https://fature.al/api/v1/reports/sales-summary` API version: `v1`. Authentication: required (bearer token). #### Query parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `from` | string | yes | Data e fillimit, e perfshire. | | `to` | string | yes | Data e perfundimit, e perfshire. | #### Example request ```bash curl -X GET 'https://fature.al/api/v1/reports/sales-summary?from=2026-01-01&to=2026-01-31' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — OK | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.period` | object | | | `data.period.from` | string | Start date (YYYY-MM-DD), inclusive | | `data.period.to` | string | End date (YYYY-MM-DD), inclusive | | `data.totals` | object | | | `data.totals.invoices` | integer | | | `data.totals.gross` | number | | | `data.totals.net` | number | | | `data.totals.vat` | number | | | `data.totals.avg_invoice` | number | | | `data.totals.currency` | string | | | `data.by_payment_method` | array | | | `data.by_payment_method[].method` | string | | | `data.by_payment_method[].count` | integer | | | `data.by_payment_method[].gross` | number | | | `data.by_payment_method[].net` | number | | | `data.by_payment_method[].vat` | number | | | `data.by_type` | array | | | `data.by_type[].type` | string | | | `data.by_type[].count` | integer | | | `data.by_type[].gross` | number | | | `data.by_vat_rate` | array | | | `data.by_vat_rate[].rate` | number | | | `data.by_vat_rate[].net` | number | | | `data.by_vat_rate[].vat` | number | | | `data.by_vat_rate[].gross` | number | | | `data.by_day` | array | | | `data.by_day[].date` | string | | | `data.by_day[].count` | integer | | | `data.by_day[].gross` | number | | | `data.cancelled` | object | | | `data.cancelled.count` | integer | | | `data.cancelled.gross` | number | | ```json { "status": true, "data": { "period": { "from": "from", "to": "to" }, "totals": { "invoices": 1, "gross": 19.99, "net": 19.99, "vat": 19.99, "avg_invoice": 19.99, "currency": "USD" }, "by_payment_method": [ { "method": "method", "count": 3, "gross": 19.99, "net": 19.99, "vat": 19.99 } ], "by_type": [ { "type": "type", "count": 3, "gross": 19.99 } ], "by_vat_rate": [ { "rate": 19.99, "net": 19.99, "vat": 19.99, "gross": 19.99 } ], "by_day": [ { "date": "date", "count": 3, "gross": 19.99 } ], "cancelled": { "count": 3, "gross": 19.99 } } } ``` **422** — Datat mungojne ose nuk jane ne formatin YYYY-MM-DD. | Field | Type | Description | | --- | --- | --- | | `success` | boolean | Always false | | `message` | string | A single summary line, the same for every validation failure | | `errors` | object | The failing fields, each with the messages for it. Dotted keys point into nested objects and array items, e.g. `lines.0.quantity` | ```json { "success": true, "message": "Hello there", "errors": [] } ``` **429** — Kufiri i kerkesave u arrit: 30 raporte ne minute. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` ### GET /api/v1/reports/top-clients Klientet kryesore Klientet e renditur sipas vleres se faturuar ne periudhe. `limit` pranon nga `1` deri ne `500`. Klientet e rastit, pra faturat pa klient te emeruar, nuk hyjne ne renditje. * `from` dhe `to` jane te detyrueshme, ne formatin `YYYY-MM-DD`, dhe periudha kthehet e konfirmuar ne `period` te pergjigjes. Full URL: `https://fature.al/api/v1/reports/top-clients` API version: `v1`. Authentication: required (bearer token). #### Example request ```bash curl -X GET 'https://fature.al/api/v1/reports/top-clients' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — OK | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.period` | object | | | `data.period.from` | string | Start date (YYYY-MM-DD), inclusive | | `data.period.to` | string | End date (YYYY-MM-DD), inclusive | | `data.limit` | integer | | | `data.items` | array | | | `data.items[].id_client` | integer, nullable | | | `data.items[].name` | string | | | `data.items[].nipt` | string, nullable | | | `data.items[].invoices` | integer | | | `data.items[].gross` | number | | ```json { "status": true, "data": { "period": { "from": "from", "to": "to" }, "limit": 25, "items": [ { "id_client": 1, "name": "Jane Doe", "nipt": "nipt", "invoices": 1, "gross": 19.99 } ] } } ``` **422** — Datat mungojne ose nuk jane ne formatin YYYY-MM-DD. | Field | Type | Description | | --- | --- | --- | | `success` | boolean | Always false | | `message` | string | A single summary line, the same for every validation failure | | `errors` | object | The failing fields, each with the messages for it. Dotted keys point into nested objects and array items, e.g. `lines.0.quantity` | ```json { "success": true, "message": "Hello there", "errors": [] } ``` **429** — Kufiri i kerkesave u arrit: 30 raporte ne minute. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` ### GET /api/v1/reports/top-products Produktet me te shitura Produktet e renditura sipas te ardhurave ose sipas sasise se shitur. | Parametri | Vlerat | Parazgjedhja | | --- | --- | --- | | `sort` | `revenue`, `quantity` | `revenue` | | `limit` | `1` deri ne `200` | `20` | * `from` dhe `to` jane te detyrueshme, ne formatin `YYYY-MM-DD`, dhe periudha kthehet e konfirmuar ne `period` te pergjigjes. Full URL: `https://fature.al/api/v1/reports/top-products` API version: `v1`. Authentication: required (bearer token). #### Example request ```bash curl -X GET 'https://fature.al/api/v1/reports/top-products' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — OK | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.period` | object | | | `data.period.from` | string | Start date (YYYY-MM-DD), inclusive | | `data.period.to` | string | End date (YYYY-MM-DD), inclusive | | `data.sort` | string | | | `data.limit` | integer | | | `data.items` | array | | | `data.items[].id_product` | integer, nullable | | | `data.items[].name` | string | | | `data.items[].code` | string, nullable | | | `data.items[].unit` | string, nullable | | | `data.items[].quantity` | number | | | `data.items[].revenue` | number | | ```json { "status": true, "data": { "period": { "from": "from", "to": "to" }, "sort": "sort", "limit": 25, "items": [ { "id_product": 1, "name": "Jane Doe", "code": "code", "unit": "unit", "quantity": 2, "revenue": 19.99 } ] } } ``` **422** — Datat mungojne ose nuk jane ne formatin YYYY-MM-DD. | Field | Type | Description | | --- | --- | --- | | `success` | boolean | Always false | | `message` | string | A single summary line, the same for every validation failure | | `errors` | object | The failing fields, each with the messages for it. Dotted keys point into nested objects and array items, e.g. `lines.0.quantity` | ```json { "success": true, "message": "Hello there", "errors": [] } ``` **429** — Kufiri i kerkesave u arrit: 30 raporte ne minute. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` ### GET /api/v1/reports/vat Raporti i TVSH TVSH e mbledhur nga shitjet perballe asaj te paguar ne blerje, me diferencen qe rezulton. Rreshtat ndahen ne dy grupe: - **te tatueshem**, sipas shkalles: `0`, `6`, `10`, `20`; - **te perjashtuar**, sipas llojit te perjashtimit. Blerjet vijne nga faturat qe ka regjistruar sistemi fiskal, prandaj raporti mbulon te dyja anet pa ju kerkuar te importoni gje. * `from` dhe `to` jane te detyrueshme, ne formatin `YYYY-MM-DD`, dhe periudha kthehet e konfirmuar ne `period` te pergjigjes. Full URL: `https://fature.al/api/v1/reports/vat` API version: `v1`. Authentication: required (bearer token). #### Query parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `from` | string | yes | Data e fillimit, e perfshire. | | `to` | string | yes | Data e perfundimit, e perfshire. | #### Example request ```bash curl -X GET 'https://fature.al/api/v1/reports/vat?from=2026-01-01&to=2026-01-31' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — OK | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.period` | object | | | `data.period.from` | string | Start date (YYYY-MM-DD), inclusive | | `data.period.to` | string | End date (YYYY-MM-DD), inclusive | | `data.totals` | object | | | `data.totals.net` | number | | | `data.totals.vat` | number | | | `data.totals.gross` | number | | | `data.totals.currency` | string | | | `data.taxable` | array | | | `data.taxable[].rate` | number | | | `data.taxable[].net` | number | | | `data.taxable[].vat` | number | | | `data.taxable[].gross` | number | | | `data.exempt` | array | | | `data.exempt[].exempt_type` | string | | | `data.exempt[].rate` | number | | | `data.exempt[].net` | number | | | `data.exempt[].vat` | number | | | `data.exempt[].gross` | number | | | `data.purchases` | object | | | `data.purchases.taxable` | array | | | `data.purchases.taxable[].rate` | number | | | `data.purchases.taxable[].net` | number | | | `data.purchases.taxable[].vat` | number | | | `data.purchases.taxable[].gross` | number | | | `data.purchases.exempt` | array | | | `data.purchases.exempt[].exempt_type` | string | | | `data.purchases.exempt[].rate` | number | | | `data.purchases.exempt[].net` | number | | | `data.purchases.exempt[].vat` | number | | | `data.purchases.exempt[].gross` | number | | | `data.purchases.totals` | object | | | `data.purchases.totals.net` | number | | | `data.purchases.totals.vat` | number | | | `data.purchases.totals.gross` | number | | | `data.purchases.totals.currency` | string | | | `data.summary` | object | | | `data.summary.output_vat` | number | | | `data.summary.input_vat` | number | | | `data.summary.vat_due` | number | | | `data.summary.currency` | string | | ```json { "status": true, "data": { "period": { "from": "from", "to": "to" }, "totals": { "net": 19.99, "vat": 19.99, "gross": 19.99, "currency": "USD" }, "taxable": [ { "rate": 19.99, "net": 19.99, "vat": 19.99, "gross": 19.99 } ], "exempt": [ { "exempt_type": "exempt type", "rate": 19.99, "net": 19.99, "vat": 19.99, "gross": 19.99 } ], "purchases": { "taxable": [ { "rate": 19.99, "net": 19.99, "vat": 19.99, "gross": 19.99 } ], "exempt": [ { "exempt_type": "exempt type", "rate": 19.99, "net": 19.99, "vat": 19.99, "gross": 19.99 } ], "totals": { "net": 19.99, "vat": 19.99, "gross": 19.99, "currency": "USD" } }, "summary": { "output_vat": 19.99, "input_vat": 19.99, "vat_due": 19.99, "currency": "USD" } } } ``` **422** — Datat mungojne ose nuk jane ne formatin YYYY-MM-DD. | Field | Type | Description | | --- | --- | --- | | `success` | boolean | Always false | | `message` | string | A single summary line, the same for every validation failure | | `errors` | object | The failing fields, each with the messages for it. Dotted keys point into nested objects and array items, e.g. `lines.0.quantity` | ```json { "success": true, "message": "Hello there", "errors": [] } ``` **429** — Kufiri i kerkesave u arrit: 30 raporte ne minute. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` ### GET /api/v1/reports/wtn Raporti i faturave shoqeruese Fletet shoqeruese te periudhes, te grupuara sipas gjendjes fiskale, bashke me destinacionet e perdorura dhe vleren e mallit qe ka levizur. Nje flete e pafiskalizuar ketu eshte gje qe kerkon vemendje: malli ka levizur pa dokumentin qe ligji kerkon. * `from` dhe `to` jane te detyrueshme, ne formatin `YYYY-MM-DD`, dhe periudha kthehet e konfirmuar ne `period` te pergjigjes. Full URL: `https://fature.al/api/v1/reports/wtn` API version: `v1`. Authentication: required (bearer token). #### Query parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `from` | string | yes | Data e fillimit, e perfshire. | | `to` | string | yes | Data e perfundimit, e perfshire. | #### Example request ```bash curl -X GET 'https://fature.al/api/v1/reports/wtn?from=2026-01-01&to=2026-01-31' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — OK | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.period` | object | | | `data.period.from` | string | Start date (YYYY-MM-DD), inclusive | | `data.period.to` | string | End date (YYYY-MM-DD), inclusive | | `data.totals` | object | | | `data.totals.count` | integer | | | `data.totals.value_of_goods` | number | | | `data.by_status` | array | | | `data.by_status[].status` | string, nullable | | | `data.by_status[].count` | integer | | | `data.by_status[].value_of_goods` | number | | | `data.unique_destinations` | integer | | | `data.destinations` | array | | ```json { "status": true, "data": { "period": { "from": "from", "to": "to" }, "totals": { "count": 3, "value_of_goods": 19.99 }, "by_status": [ { "status": "status", "count": 3, "value_of_goods": 19.99 } ], "unique_destinations": 1, "destinations": [ "destinations" ] } } ``` **422** — Datat mungojne ose nuk jane ne formatin YYYY-MM-DD. | Field | Type | Description | | --- | --- | --- | | `success` | boolean | Always false | | `message` | string | A single summary line, the same for every validation failure | | `errors` | object | The failing fields, each with the messages for it. Dotted keys point into nested objects and array items, e.g. `lines.0.quantity` | ```json { "success": true, "message": "Hello there", "errors": [] } ``` **429** — Kufiri i kerkesave u arrit: 30 raporte ne minute. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false. A successful response carries `status: true` and a `data` object instead | | `message` | string | The exception message. Empty when the failure carries no exception of its own | | `errors` | array | Messages to show the operator or to log. Absent when the failure has nothing to add beyond `message` | ```json { "status": true, "message": "Hello there", "errors": [ "errors" ] } ``` ## Wolt Partner API The venue side of a Wolt integration: read the order feed, accept or reject what arrives, move an order through pickup and delivery, and fetch the fiscal invoice it produced. The feed is append-only and ordered, so it is what a venue's own system should follow to stay in step. The listing endpoints are for backfill and for showing a snapshot. ### GET /api/partner/v1/wolt/events Event feed The spine of the integration. Poll this endpoint with the last next_cursor you received to get the venue's order lifecycle events in order. The feed is append-only, so nothing is missed across your downtime; delivery is at-least-once, so treat (order_id, type) as idempotent. Each event carries a compact snapshot of the order at that moment in `order`. Full URL: `https://fature.al/api/partner/v1/wolt/events` Authentication: required (bearer token). #### Query parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `since` | integer | no | The cursor to resume from; pass the previous next_cursor. Defaults to 0, the start of retention. Defaults to `0`. | | `limit` | integer | no | Max events to return, 1-200. Defaults to `50`. | | `types` | string | no | Comma-separated event types to include, e.g. order.received,order.ready. | #### Example request ```bash curl -X GET 'https://fature.al/api/partner/v1/wolt/events' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — OK | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.events` | array | | | `data.events[].id` | integer | Monotonic cursor id; pass the highest one you have seen as ?since= | | `data.events[].type` | string | Event type, e.g. order.received, order.accepted, order.ready, order.delivered, order.fiscalized, order.fiscalization_failed | | `data.events[].order_id` | integer | Fatureal order id the event is about | | `data.events[].wolt_order_id` | string | Wolt's order id | | `data.events[].status` | string, nullable | Order status at the moment of the event | | `data.events[].occurred_at` | string, nullable | When the event occurred (ISO-8601) | | `data.events[].order` | object | Compact snapshot of the order at that moment | | `data.events[].order.id` | integer | Fatureal order id; use this as {id} in the order and action routes | | `data.events[].order.wolt_order_id` | string | Wolt's own order id | | `data.events[].order.display_number` | string, nullable | Human order number shown to the customer | | `data.events[].order.status` | string | Raw Wolt lifecycle status: received, acknowledged, production, ready, picked_up, courier_at_customer, delivered, rejected, refunded, ... | | `data.events[].order.fiscal_state` | string | Fiscal state derived from the invoice: pending, deferred, fiscalised or failed | | `data.events[].order.total_amount` | number | Charged total in major currency units | | `data.events[].order.currency` | string | ISO 4217 currency code | | `data.events[].order.received_at` | string, nullable | When Wolt handed the order to us (ISO-8601) | | `data.events[].order.pickup_at` | string, nullable | Committed handover time (ISO-8601), set when a pickup time was chosen on accept | | `data.events[].order.delivery_type` | string, nullable | Wolt delivery type: takeaway, eatin, homedelivery, ... | | `data.events[].order.self_delivery` | boolean | Whether the venue fulfils delivery with its own courier | | `data.events[].order.branch` | string, nullable | Branch name | | `data.events[].order.invoice` | object, nullable | Linked fiscal invoice reference, or null before fiscalisation | | `data.next_cursor` | string | | | `data.has_more` | boolean | | ```json { "status": true, "data": { "events": [ { "id": 1, "type": "type", "order_id": 1, "wolt_order_id": "wolt order id", "status": "status", "occurred_at": "occurred at", "order": { "id": 1, "wolt_order_id": "wolt order id", "display_number": "display number", "status": "status", "fiscal_state": "fiscal state", "total_amount": 4200, "currency": "USD", "received_at": "received at", "pickup_at": "pickup at", "delivery_type": "delivery type", "self_delivery": true, "branch": "branch", "invoice": [] } } ], "next_cursor": "next cursor", "has_more": true } } ``` **403** — The company has no Wolt add-on, the token has no Wolt right, or it resolves to no single active venue. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **429** — Rate limit reached: 180 reads a minute per token. Retry after the number of seconds in the Retry-After header. | Field | Type | Description | | --- | --- | --- | | `message` | string | | ```json { "message": "Hello there" } ``` ### GET /api/partner/v1/wolt/orders List orders The venue's orders, newest first. Page backwards by passing the `next_cursor` from the previous response as `?cursor=`. Stop when `has_more` is `false`. This is a snapshot for listing and backfill. For keeping in step with the venue in real time, poll the event feed instead: it is append-only and ordered, so nothing is missed. Full URL: `https://fature.al/api/partner/v1/wolt/orders` Authentication: required (bearer token). #### Query parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `cursor` | integer | no | Return orders older than this id; pass the previous next_cursor. | | `limit` | integer | no | Page size, 1-100. Defaults to `25`. | | `status` | string | no | Filter by raw Wolt status (e.g. received, acknowledged, ready, delivered). | | `from` | string | no | Only orders received on/after this date (YYYY-MM-DD). | | `to` | string | no | Only orders received on/before this date (YYYY-MM-DD). | #### Example request ```bash curl -X GET 'https://fature.al/api/partner/v1/wolt/orders' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — OK | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.orders` | array | | | `data.orders[].id` | integer | Fatureal order id; use this as {id} in the order and action routes | | `data.orders[].wolt_order_id` | string | Wolt's own order id | | `data.orders[].display_number` | string, nullable | Human order number shown to the customer | | `data.orders[].status` | string | Raw Wolt lifecycle status: received, acknowledged, production, ready, picked_up, courier_at_customer, delivered, rejected, refunded, ... | | `data.orders[].fiscal_state` | string | Fiscal state derived from the invoice: pending, deferred, fiscalised or failed | | `data.orders[].total_amount` | number | Charged total in major currency units | | `data.orders[].currency` | string | ISO 4217 currency code | | `data.orders[].received_at` | string, nullable | When Wolt handed the order to us (ISO-8601) | | `data.orders[].pickup_at` | string, nullable | Committed handover time (ISO-8601), set when a pickup time was chosen on accept | | `data.orders[].delivery_type` | string, nullable | Wolt delivery type: takeaway, eatin, homedelivery, ... | | `data.orders[].self_delivery` | boolean | Whether the venue fulfils delivery with its own courier | | `data.orders[].branch` | string, nullable | Branch name | | `data.orders[].invoice` | object, nullable | Linked fiscal invoice reference, or null before fiscalisation | | `data.orders[].invoice.id` | integer | Fatureal invoice id | | `data.orders[].invoice.number` | any | Fiscal invoice number, once assigned | | `data.orders[].invoice.state` | string | Fiscal state: pending, deferred, fiscalised or failed | | `data.orders[].invoice.fiscal_iic` | any | Fiscal IIC (NSLF), once fiscalised | | `data.orders[].invoice.fiscal_fic` | any | Fiscal FIC (NIVF), once fiscalised | | `data.next_cursor` | string | | | `data.has_more` | boolean | | ```json { "status": true, "data": { "orders": [ { "id": 1, "wolt_order_id": "wolt order id", "display_number": "display number", "status": "status", "fiscal_state": "fiscal state", "total_amount": 4200, "currency": "USD", "received_at": "received at", "pickup_at": "pickup at", "delivery_type": "delivery type", "self_delivery": true, "branch": "branch", "invoice": { "id": 1, "number": "number", "state": "state", "fiscal_iic": "fiscal iic", "fiscal_fic": "fiscal fic" } } ], "next_cursor": "next cursor", "has_more": true } } ``` **403** — The company has no Wolt add-on, the token has no Wolt right, or it resolves to no single active venue. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **429** — Rate limit reached: 180 reads a minute per token. Retry after the number of seconds in the Retry-After header. | Field | Type | Description | | --- | --- | --- | | `message` | string | | ```json { "message": "Hello there" } ``` ### GET /api/partner/v1/wolt/orders/{id} Get an order The authoritative snapshot of one order: header, parties, lines, totals and fiscal linkage. Full URL: `https://fature.al/api/partner/v1/wolt/orders/{id}` Authentication: required (bearer token). #### Path parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `id` | integer | yes | The order's Fatureal id, from the feed or the order list. | #### Example request ```bash curl -X GET 'https://fature.al/api/partner/v1/wolt/orders/8801' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — OK | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.order` | object | | | `data.order.customer` | object | | | `data.order.customer.name` | string, nullable | | | `data.order.customer.phone` | string, nullable | Shared by Wolt only for self-delivery orders | | `data.order.customer.note` | string, nullable | Customer note left with the order | | `data.order.company` | object, nullable | B2B billing company, or null for a normal consumer order | | `data.order.company.tax_id` | string | Tax id (NUIS/NIPT) the customer asked to bill | | `data.order.company.name` | string, nullable | | | `data.order.company.address` | string, nullable | | | `data.order.preorder` | object, nullable | Scheduled pre-order info, or null for an instant order | | `data.order.preorder.time` | string | Scheduled time (ISO-8601) | | `data.order.preorder.status` | string, nullable | Wolt pre-order status | | `data.order.lines` | array | | | `data.order.lines[].name` | string | Item name | | `data.order.lines[].quantity` | number | | | `data.order.lines[].unit_price` | number | Unit price in major units | | `data.order.lines[].total` | number | Line total in major units, after discount | | `data.order.lines[].discount` | number | Discount applied to the line, major units | | `data.order.lines[].product` | object, nullable | Linked internal product, or null when the Wolt item is unmapped | | `data.order.lines[].options` | array | Chosen modifiers/options for the line | | `data.order.totals` | object | | | `data.order.totals.subtotal_before_discount` | number | Basket total before any discount, major units | | `data.order.totals.discount` | number | Total discount applied, major units | | `data.order.totals.total` | number | Charged total, major units | | `data.order.totals.currency` | string | ISO 4217 currency code | | `data.order.totals.campaigns` | array | Applied promotion labels | ```json { "status": true, "data": { "order": { "customer": { "name": "Jane Doe", "phone": "+15551234567", "note": "note" }, "company": { "tax_id": "tax id", "name": "Jane Doe", "address": "1 Example Street" }, "preorder": { "time": "time", "status": "status" }, "lines": [ { "name": "Jane Doe", "quantity": 2, "unit_price": 1999, "total": 4200, "discount": 3, "product": [], "options": [ "options" ] } ], "totals": { "subtotal_before_discount": 4200, "discount": 3, "total": 4200, "currency": "USD", "campaigns": [ "campaigns" ] } } } } ``` **403** — The company has no Wolt add-on, the token has no Wolt right, or it resolves to no single active venue. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **404** — No such order for this venue. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **429** — Rate limit reached: 180 reads a minute per token. Retry after the number of seconds in the Retry-After header. | Field | Type | Description | | --- | --- | --- | | `message` | string | | ```json { "message": "Hello there" } ``` ### POST /api/partner/v1/wolt/orders/{id}/accept Accept an order Relays acceptance to Wolt. No fiscal invoice is created here: that happens when the order is marked ready. `pickup_minutes` means two different things depending on the order: | Order type | What `pickup_minutes` commits to | | --- | --- | | Marketplace | When the food will be ready, so Wolt dispatches a courier to match | | Self-delivery | The **total delivery time** promised to the customer | Getting this wrong on a marketplace order sends a courier to wait, or leaves food going cold. Full URL: `https://fature.al/api/partner/v1/wolt/orders/{id}/accept` Authentication: required (bearer token). #### Path parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `id` | integer | yes | The order's Fatureal id, from the feed or the order list. | #### Header parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `Idempotency-Key` | string | yes | Your own unique key for this action. A retry with the same key replays the first result instead of relaying a second action to Wolt, and the replay carries an Idempotent-Replayed: true header. Kept for 24 hours. | #### Body parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `pickup_minutes` | integer | no | Minutes from now until ready, 5-180. | #### Example request ```bash curl -X POST 'https://fature.al/api/partner/v1/wolt/orders/8801/accept' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -H 'Idempotency-Key: a2f1c9e4-5b60-4d7a-9c31-8e0f2b6d4a17' \ -d '{ "pickup_minutes": 20 }' ``` #### Responses **201** — Created | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.order` | object | | | `data.order.customer` | object | | | `data.order.customer.name` | string, nullable | | | `data.order.customer.phone` | string, nullable | Shared by Wolt only for self-delivery orders | | `data.order.customer.note` | string, nullable | Customer note left with the order | | `data.order.company` | object, nullable | B2B billing company, or null for a normal consumer order | | `data.order.company.tax_id` | string | Tax id (NUIS/NIPT) the customer asked to bill | | `data.order.company.name` | string, nullable | | | `data.order.company.address` | string, nullable | | | `data.order.preorder` | object, nullable | Scheduled pre-order info, or null for an instant order | | `data.order.preorder.time` | string | Scheduled time (ISO-8601) | | `data.order.preorder.status` | string, nullable | Wolt pre-order status | | `data.order.lines` | array | | | `data.order.lines[].name` | string | Item name | | `data.order.lines[].quantity` | number | | | `data.order.lines[].unit_price` | number | Unit price in major units | | `data.order.lines[].total` | number | Line total in major units, after discount | | `data.order.lines[].discount` | number | Discount applied to the line, major units | | `data.order.lines[].product` | object, nullable | Linked internal product, or null when the Wolt item is unmapped | | `data.order.lines[].options` | array | Chosen modifiers/options for the line | | `data.order.totals` | object | | | `data.order.totals.subtotal_before_discount` | number | Basket total before any discount, major units | | `data.order.totals.discount` | number | Total discount applied, major units | | `data.order.totals.total` | number | Charged total, major units | | `data.order.totals.currency` | string | ISO 4217 currency code | | `data.order.totals.campaigns` | array | Applied promotion labels | ```json { "status": true, "data": { "order": { "customer": { "name": "Jane Doe", "phone": "+15551234567", "note": "note" }, "company": { "tax_id": "tax id", "name": "Jane Doe", "address": "1 Example Street" }, "preorder": { "time": "time", "status": "status" }, "lines": [ { "name": "Jane Doe", "quantity": 2, "unit_price": 1999, "total": 4200, "discount": 3, "product": [], "options": [ "options" ] } ], "totals": { "subtotal_before_discount": 4200, "discount": 3, "total": 4200, "currency": "USD", "campaigns": [ "campaigns" ] } } } } ``` **400** — The Idempotency-Key header is missing. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **403** — The company has no Wolt add-on, the token has no Wolt right, or it resolves to no single active venue. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **404** — No such order for this venue. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **409** — The order's current status does not allow this action, or a call with the same Idempotency-Key is still in flight. Nothing was relayed to Wolt. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **422** — pickup_minutes is outside 5-180, or the action failed on our side and was not completed. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **429** — Rate limit reached: 60 writes a minute per token. Retry after the number of seconds in the Retry-After header. | Field | Type | Description | | --- | --- | --- | | `message` | string | | ```json { "message": "Hello there" } ``` **502** — Wolt refused or did not answer. Safe to retry with the same Idempotency-Key. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` ### POST /api/partner/v1/wolt/orders/{id}/confirm-preorder Confirm a pre-order Confirms a customer-scheduled pre-order. It is parked until Wolt releases it into production near its due time, after which it can be marked ready. Full URL: `https://fature.al/api/partner/v1/wolt/orders/{id}/confirm-preorder` Authentication: required (bearer token). #### Path parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `id` | integer | yes | The order's Fatureal id, from the feed or the order list. | #### Header parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `Idempotency-Key` | string | yes | Your own unique key for this action. A retry with the same key replays the first result instead of relaying a second action to Wolt, and the replay carries an Idempotent-Replayed: true header. Kept for 24 hours. | #### Example request ```bash curl -X POST 'https://fature.al/api/partner/v1/wolt/orders/8801/confirm-preorder' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' \ -H 'Idempotency-Key: a2f1c9e4-5b60-4d7a-9c31-8e0f2b6d4a17' ``` #### Responses **201** — Created | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.order` | object | | | `data.order.customer` | object | | | `data.order.customer.name` | string, nullable | | | `data.order.customer.phone` | string, nullable | Shared by Wolt only for self-delivery orders | | `data.order.customer.note` | string, nullable | Customer note left with the order | | `data.order.company` | object, nullable | B2B billing company, or null for a normal consumer order | | `data.order.company.tax_id` | string | Tax id (NUIS/NIPT) the customer asked to bill | | `data.order.company.name` | string, nullable | | | `data.order.company.address` | string, nullable | | | `data.order.preorder` | object, nullable | Scheduled pre-order info, or null for an instant order | | `data.order.preorder.time` | string | Scheduled time (ISO-8601) | | `data.order.preorder.status` | string, nullable | Wolt pre-order status | | `data.order.lines` | array | | | `data.order.lines[].name` | string | Item name | | `data.order.lines[].quantity` | number | | | `data.order.lines[].unit_price` | number | Unit price in major units | | `data.order.lines[].total` | number | Line total in major units, after discount | | `data.order.lines[].discount` | number | Discount applied to the line, major units | | `data.order.lines[].product` | object, nullable | Linked internal product, or null when the Wolt item is unmapped | | `data.order.lines[].options` | array | Chosen modifiers/options for the line | | `data.order.totals` | object | | | `data.order.totals.subtotal_before_discount` | number | Basket total before any discount, major units | | `data.order.totals.discount` | number | Total discount applied, major units | | `data.order.totals.total` | number | Charged total, major units | | `data.order.totals.currency` | string | ISO 4217 currency code | | `data.order.totals.campaigns` | array | Applied promotion labels | ```json { "status": true, "data": { "order": { "customer": { "name": "Jane Doe", "phone": "+15551234567", "note": "note" }, "company": { "tax_id": "tax id", "name": "Jane Doe", "address": "1 Example Street" }, "preorder": { "time": "time", "status": "status" }, "lines": [ { "name": "Jane Doe", "quantity": 2, "unit_price": 1999, "total": 4200, "discount": 3, "product": [], "options": [ "options" ] } ], "totals": { "subtotal_before_discount": 4200, "discount": 3, "total": 4200, "currency": "USD", "campaigns": [ "campaigns" ] } } } } ``` **400** — The Idempotency-Key header is missing. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **403** — The company has no Wolt add-on, the token has no Wolt right, or it resolves to no single active venue. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **404** — No such order for this venue. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **409** — The order's current status does not allow this action, or a call with the same Idempotency-Key is still in flight. Nothing was relayed to Wolt. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **422** — The action failed on our side and was not completed. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **429** — Rate limit reached: 60 writes a minute per token. Retry after the number of seconds in the Retry-After header. | Field | Type | Description | | --- | --- | --- | | `message` | string | | ```json { "message": "Hello there" } ``` **502** — Wolt refused or did not answer. Safe to retry with the same Idempotency-Key. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` ### POST /api/partner/v1/wolt/orders/{id}/courier-at-customer Self-delivery step 2: the courier reached the customer Only for **self-delivery** orders, and only after `pickup-completed`. Wolt notifies the customer that the courier has arrived, so send it when that is actually true rather than in advance. The order moves to `courier_at_customer`. The drop-off itself is confirmed separately with `delivered`. Full URL: `https://fature.al/api/partner/v1/wolt/orders/{id}/courier-at-customer` Authentication: required (bearer token). #### Path parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `id` | integer | yes | The order's Fatureal id, from the feed or the order list. | #### Header parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `Idempotency-Key` | string | yes | Your own unique key for this action. A retry with the same key replays the first result instead of relaying a second action to Wolt, and the replay carries an Idempotent-Replayed: true header. Kept for 24 hours. | #### Example request ```bash curl -X POST 'https://fature.al/api/partner/v1/wolt/orders/8801/courier-at-customer' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' \ -H 'Idempotency-Key: a2f1c9e4-5b60-4d7a-9c31-8e0f2b6d4a17' ``` #### Responses **201** — Created | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.order` | object | | | `data.order.customer` | object | | | `data.order.customer.name` | string, nullable | | | `data.order.customer.phone` | string, nullable | Shared by Wolt only for self-delivery orders | | `data.order.customer.note` | string, nullable | Customer note left with the order | | `data.order.company` | object, nullable | B2B billing company, or null for a normal consumer order | | `data.order.company.tax_id` | string | Tax id (NUIS/NIPT) the customer asked to bill | | `data.order.company.name` | string, nullable | | | `data.order.company.address` | string, nullable | | | `data.order.preorder` | object, nullable | Scheduled pre-order info, or null for an instant order | | `data.order.preorder.time` | string | Scheduled time (ISO-8601) | | `data.order.preorder.status` | string, nullable | Wolt pre-order status | | `data.order.lines` | array | | | `data.order.lines[].name` | string | Item name | | `data.order.lines[].quantity` | number | | | `data.order.lines[].unit_price` | number | Unit price in major units | | `data.order.lines[].total` | number | Line total in major units, after discount | | `data.order.lines[].discount` | number | Discount applied to the line, major units | | `data.order.lines[].product` | object, nullable | Linked internal product, or null when the Wolt item is unmapped | | `data.order.lines[].options` | array | Chosen modifiers/options for the line | | `data.order.totals` | object | | | `data.order.totals.subtotal_before_discount` | number | Basket total before any discount, major units | | `data.order.totals.discount` | number | Total discount applied, major units | | `data.order.totals.total` | number | Charged total, major units | | `data.order.totals.currency` | string | ISO 4217 currency code | | `data.order.totals.campaigns` | array | Applied promotion labels | ```json { "status": true, "data": { "order": { "customer": { "name": "Jane Doe", "phone": "+15551234567", "note": "note" }, "company": { "tax_id": "tax id", "name": "Jane Doe", "address": "1 Example Street" }, "preorder": { "time": "time", "status": "status" }, "lines": [ { "name": "Jane Doe", "quantity": 2, "unit_price": 1999, "total": 4200, "discount": 3, "product": [], "options": [ "options" ] } ], "totals": { "subtotal_before_discount": 4200, "discount": 3, "total": 4200, "currency": "USD", "campaigns": [ "campaigns" ] } } } } ``` **400** — The Idempotency-Key header is missing. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **403** — The company has no Wolt add-on, the token has no Wolt right, or it resolves to no single active venue. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **404** — No such order for this venue. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **409** — The order's current status does not allow this action, or a call with the same Idempotency-Key is still in flight. Nothing was relayed to Wolt. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **422** — The action failed on our side and was not completed. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **429** — Rate limit reached: 60 writes a minute per token. Retry after the number of seconds in the Retry-After header. | Field | Type | Description | | --- | --- | --- | | `message` | string | | ```json { "message": "Hello there" } ``` **502** — Wolt refused or did not answer. Safe to retry with the same Idempotency-Key. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` ### POST /api/partner/v1/wolt/orders/{id}/delivered Close the order The final step, used in two situations: - **Takeaway**: the customer has collected the order after it was marked ready. - **Self-delivery**: your courier has handed it over, after `courier-at-customer`. Marketplace orders do not need this: a Wolt courier collects them and Wolt closes them. The order moves to `delivered` and leaves the active board. Full URL: `https://fature.al/api/partner/v1/wolt/orders/{id}/delivered` Authentication: required (bearer token). #### Path parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `id` | integer | yes | The order's Fatureal id, from the feed or the order list. | #### Header parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `Idempotency-Key` | string | yes | Your own unique key for this action. A retry with the same key replays the first result instead of relaying a second action to Wolt, and the replay carries an Idempotent-Replayed: true header. Kept for 24 hours. | #### Example request ```bash curl -X POST 'https://fature.al/api/partner/v1/wolt/orders/8801/delivered' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' \ -H 'Idempotency-Key: a2f1c9e4-5b60-4d7a-9c31-8e0f2b6d4a17' ``` #### Responses **201** — Created | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.order` | object | | | `data.order.customer` | object | | | `data.order.customer.name` | string, nullable | | | `data.order.customer.phone` | string, nullable | Shared by Wolt only for self-delivery orders | | `data.order.customer.note` | string, nullable | Customer note left with the order | | `data.order.company` | object, nullable | B2B billing company, or null for a normal consumer order | | `data.order.company.tax_id` | string | Tax id (NUIS/NIPT) the customer asked to bill | | `data.order.company.name` | string, nullable | | | `data.order.company.address` | string, nullable | | | `data.order.preorder` | object, nullable | Scheduled pre-order info, or null for an instant order | | `data.order.preorder.time` | string | Scheduled time (ISO-8601) | | `data.order.preorder.status` | string, nullable | Wolt pre-order status | | `data.order.lines` | array | | | `data.order.lines[].name` | string | Item name | | `data.order.lines[].quantity` | number | | | `data.order.lines[].unit_price` | number | Unit price in major units | | `data.order.lines[].total` | number | Line total in major units, after discount | | `data.order.lines[].discount` | number | Discount applied to the line, major units | | `data.order.lines[].product` | object, nullable | Linked internal product, or null when the Wolt item is unmapped | | `data.order.lines[].options` | array | Chosen modifiers/options for the line | | `data.order.totals` | object | | | `data.order.totals.subtotal_before_discount` | number | Basket total before any discount, major units | | `data.order.totals.discount` | number | Total discount applied, major units | | `data.order.totals.total` | number | Charged total, major units | | `data.order.totals.currency` | string | ISO 4217 currency code | | `data.order.totals.campaigns` | array | Applied promotion labels | ```json { "status": true, "data": { "order": { "customer": { "name": "Jane Doe", "phone": "+15551234567", "note": "note" }, "company": { "tax_id": "tax id", "name": "Jane Doe", "address": "1 Example Street" }, "preorder": { "time": "time", "status": "status" }, "lines": [ { "name": "Jane Doe", "quantity": 2, "unit_price": 1999, "total": 4200, "discount": 3, "product": [], "options": [ "options" ] } ], "totals": { "subtotal_before_discount": 4200, "discount": 3, "total": 4200, "currency": "USD", "campaigns": [ "campaigns" ] } } } } ``` **400** — The Idempotency-Key header is missing. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **403** — The company has no Wolt add-on, the token has no Wolt right, or it resolves to no single active venue. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **404** — No such order for this venue. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **409** — The order's current status does not allow this action, or a call with the same Idempotency-Key is still in flight. Nothing was relayed to Wolt. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **422** — The action failed on our side and was not completed. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **429** — Rate limit reached: 60 writes a minute per token. Retry after the number of seconds in the Retry-After header. | Field | Type | Description | | --- | --- | --- | | `message` | string | | ```json { "message": "Hello there" } ``` **502** — Wolt refused or did not answer. Safe to retry with the same Idempotency-Key. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` ### GET /api/partner/v1/wolt/orders/{id}/invoice Get the order's fiscal invoice Returns the fiscal invoice issued for the order: `IIC`, `FIC` and `EIC` identifiers, verification through `pdf_url`, the client, the amounts and the lines. The invoice object is identical to the one from `GET /api/v1/invoice/{id}/details`, so anything already written against that endpoint works here unchanged. ## While it is still null `invoice` is `null` until the order has been fiscalised. Track `fiscal_state` rather than polling blindly: | `fiscal_state` | Meaning | | --- | --- | | `pending` | No invoice yet. Mark the order ready to create one | | `deferred` | Issued, waiting on the tax service. It will complete on its own | | `fiscalised` | Done. `invoice` is populated | | `failed` | Needs a retry | Better still, watch the `order.fiscalized` event on the feed instead of polling. Full URL: `https://fature.al/api/partner/v1/wolt/orders/{id}/invoice` Authentication: required (bearer token). #### Path parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `id` | integer | yes | The order's Fatureal id, from the feed or the order list. | #### Example request ```bash curl -X GET 'https://fature.al/api/partner/v1/wolt/orders/8801/invoice' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — OK | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.fiscal_state` | string | | | `data.invoice` | object, nullable | | | `data.invoice.lines` | array | | | `data.invoice.lines[].name` | string | | | `data.invoice.lines[].product_code` | string, nullable | Internal product code, when the line is a mapped product | | `data.invoice.lines[].unit` | string, nullable | | | `data.invoice.lines[].unit_code` | string, nullable | | | `data.invoice.lines[].quantity` | number | | | `data.invoice.lines[].unitPrice` | number | Unit price with the line discount already taken off, major units | | `data.invoice.lines[].vat_rate` | number, nullable | VAT rate percent | | `data.invoice.lines[].vat_exempt_type` | string, nullable | VAT exemption type, when the line is exempt | | `data.invoice.lines[].discount_rate` | number, nullable | Line discount percent, as sent in `lines[].discount` when the line was discounted | | `data.invoice.lines[].discount` | number, nullable | Line discount amount, net-denominated, major units | | `data.invoice.lines[].amount_net` | number | | | `data.invoice.lines[].amount_vat` | number | | | `data.invoice.lines[].total` | number | Gross line total, major units | ```json { "status": true, "data": { "fiscal_state": "fiscal state", "invoice": { "lines": [ { "name": "Jane Doe", "product_code": "product code", "unit": "unit", "unit_code": "unit code", "quantity": 2, "unitPrice": 1999, "vat_rate": 19.99, "vat_exempt_type": "vat exempt type", "discount_rate": 3, "discount": 3, "amount_net": 4200, "amount_vat": 4200, "total": 4200 } ] } } } ``` **403** — The company has no Wolt add-on, the token has no Wolt right, or it resolves to no single active venue. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **404** — No such order for this venue. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **429** — Rate limit reached: 180 reads a minute per token. Retry after the number of seconds in the Retry-After header. | Field | Type | Description | | --- | --- | --- | | `message` | string | | ```json { "message": "Hello there" } ``` ### POST /api/partner/v1/wolt/orders/{id}/pickup-completed Self-delivery step 1: the venue's own courier collected the order Only for **self-delivery** orders, where the venue delivers with its own courier rather than a Wolt one. Marketplace and takeaway orders never call this. This is **not** delivery. The order moves to `picked_up` and stays open through `courier-at-customer` and `delivered`, so it remains on the board until the drop-off is confirmed. Full URL: `https://fature.al/api/partner/v1/wolt/orders/{id}/pickup-completed` Authentication: required (bearer token). #### Path parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `id` | integer | yes | The order's Fatureal id, from the feed or the order list. | #### Header parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `Idempotency-Key` | string | yes | Your own unique key for this action. A retry with the same key replays the first result instead of relaying a second action to Wolt, and the replay carries an Idempotent-Replayed: true header. Kept for 24 hours. | #### Example request ```bash curl -X POST 'https://fature.al/api/partner/v1/wolt/orders/8801/pickup-completed' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' \ -H 'Idempotency-Key: a2f1c9e4-5b60-4d7a-9c31-8e0f2b6d4a17' ``` #### Responses **201** — Created | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.order` | object | | | `data.order.customer` | object | | | `data.order.customer.name` | string, nullable | | | `data.order.customer.phone` | string, nullable | Shared by Wolt only for self-delivery orders | | `data.order.customer.note` | string, nullable | Customer note left with the order | | `data.order.company` | object, nullable | B2B billing company, or null for a normal consumer order | | `data.order.company.tax_id` | string | Tax id (NUIS/NIPT) the customer asked to bill | | `data.order.company.name` | string, nullable | | | `data.order.company.address` | string, nullable | | | `data.order.preorder` | object, nullable | Scheduled pre-order info, or null for an instant order | | `data.order.preorder.time` | string | Scheduled time (ISO-8601) | | `data.order.preorder.status` | string, nullable | Wolt pre-order status | | `data.order.lines` | array | | | `data.order.lines[].name` | string | Item name | | `data.order.lines[].quantity` | number | | | `data.order.lines[].unit_price` | number | Unit price in major units | | `data.order.lines[].total` | number | Line total in major units, after discount | | `data.order.lines[].discount` | number | Discount applied to the line, major units | | `data.order.lines[].product` | object, nullable | Linked internal product, or null when the Wolt item is unmapped | | `data.order.lines[].options` | array | Chosen modifiers/options for the line | | `data.order.totals` | object | | | `data.order.totals.subtotal_before_discount` | number | Basket total before any discount, major units | | `data.order.totals.discount` | number | Total discount applied, major units | | `data.order.totals.total` | number | Charged total, major units | | `data.order.totals.currency` | string | ISO 4217 currency code | | `data.order.totals.campaigns` | array | Applied promotion labels | ```json { "status": true, "data": { "order": { "customer": { "name": "Jane Doe", "phone": "+15551234567", "note": "note" }, "company": { "tax_id": "tax id", "name": "Jane Doe", "address": "1 Example Street" }, "preorder": { "time": "time", "status": "status" }, "lines": [ { "name": "Jane Doe", "quantity": 2, "unit_price": 1999, "total": 4200, "discount": 3, "product": [], "options": [ "options" ] } ], "totals": { "subtotal_before_discount": 4200, "discount": 3, "total": 4200, "currency": "USD", "campaigns": [ "campaigns" ] } } } } ``` **400** — The Idempotency-Key header is missing. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **403** — The company has no Wolt add-on, the token has no Wolt right, or it resolves to no single active venue. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **404** — No such order for this venue. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **409** — The order's current status does not allow this action, or a call with the same Idempotency-Key is still in flight. Nothing was relayed to Wolt. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **422** — The action failed on our side and was not completed. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **429** — Rate limit reached: 60 writes a minute per token. Retry after the number of seconds in the Retry-After header. | Field | Type | Description | | --- | --- | --- | | `message` | string | | ```json { "message": "Hello there" } ``` **502** — Wolt refused or did not answer. Safe to retry with the same Idempotency-Key. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` ### POST /api/partner/v1/wolt/orders/{id}/ready Mark an order ready for handover **This is the step that creates the fiscal invoice.** If the order has no invoice yet, one is issued and fiscalised here, so marking ready is the point at which the sale becomes a legal document. Calling it again on an order that already has one does not issue a second. What happens next depends on the delivery type: | Delivery type | After ready | | --- | --- | | Marketplace | A Wolt courier collects the order | | Takeaway | The customer collects it, then call `delivered` | | Self-delivery | Call `pickup-completed`, then `courier-at-customer`, then `delivered` | The order moves to status `ready`. Full URL: `https://fature.al/api/partner/v1/wolt/orders/{id}/ready` Authentication: required (bearer token). #### Path parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `id` | integer | yes | The order's Fatureal id, from the feed or the order list. | #### Header parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `Idempotency-Key` | string | yes | Your own unique key for this action. A retry with the same key replays the first result instead of relaying a second action to Wolt, and the replay carries an Idempotent-Replayed: true header. Kept for 24 hours. | #### Example request ```bash curl -X POST 'https://fature.al/api/partner/v1/wolt/orders/8801/ready' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' \ -H 'Idempotency-Key: a2f1c9e4-5b60-4d7a-9c31-8e0f2b6d4a17' ``` #### Responses **201** — Created | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.order` | object | | | `data.order.customer` | object | | | `data.order.customer.name` | string, nullable | | | `data.order.customer.phone` | string, nullable | Shared by Wolt only for self-delivery orders | | `data.order.customer.note` | string, nullable | Customer note left with the order | | `data.order.company` | object, nullable | B2B billing company, or null for a normal consumer order | | `data.order.company.tax_id` | string | Tax id (NUIS/NIPT) the customer asked to bill | | `data.order.company.name` | string, nullable | | | `data.order.company.address` | string, nullable | | | `data.order.preorder` | object, nullable | Scheduled pre-order info, or null for an instant order | | `data.order.preorder.time` | string | Scheduled time (ISO-8601) | | `data.order.preorder.status` | string, nullable | Wolt pre-order status | | `data.order.lines` | array | | | `data.order.lines[].name` | string | Item name | | `data.order.lines[].quantity` | number | | | `data.order.lines[].unit_price` | number | Unit price in major units | | `data.order.lines[].total` | number | Line total in major units, after discount | | `data.order.lines[].discount` | number | Discount applied to the line, major units | | `data.order.lines[].product` | object, nullable | Linked internal product, or null when the Wolt item is unmapped | | `data.order.lines[].options` | array | Chosen modifiers/options for the line | | `data.order.totals` | object | | | `data.order.totals.subtotal_before_discount` | number | Basket total before any discount, major units | | `data.order.totals.discount` | number | Total discount applied, major units | | `data.order.totals.total` | number | Charged total, major units | | `data.order.totals.currency` | string | ISO 4217 currency code | | `data.order.totals.campaigns` | array | Applied promotion labels | ```json { "status": true, "data": { "order": { "customer": { "name": "Jane Doe", "phone": "+15551234567", "note": "note" }, "company": { "tax_id": "tax id", "name": "Jane Doe", "address": "1 Example Street" }, "preorder": { "time": "time", "status": "status" }, "lines": [ { "name": "Jane Doe", "quantity": 2, "unit_price": 1999, "total": 4200, "discount": 3, "product": [], "options": [ "options" ] } ], "totals": { "subtotal_before_discount": 4200, "discount": 3, "total": 4200, "currency": "USD", "campaigns": [ "campaigns" ] } } } } ``` **400** — The Idempotency-Key header is missing. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **403** — The company has no Wolt add-on, the token has no Wolt right, or it resolves to no single active venue. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **404** — No such order for this venue. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **409** — The order's current status does not allow this action, or a call with the same Idempotency-Key is still in flight. Nothing was relayed to Wolt. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **422** — The action failed on our side and was not completed. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **429** — Rate limit reached: 60 writes a minute per token. Retry after the number of seconds in the Retry-After header. | Field | Type | Description | | --- | --- | --- | | `message` | string | | ```json { "message": "Hello there" } ``` **502** — Wolt refused or did not answer. Safe to retry with the same Idempotency-Key. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` ### POST /api/partner/v1/wolt/orders/{id}/reject Reject an order Declines the order and relays the refusal to Wolt. This is terminal: a rejected order cannot be accepted afterwards, and no fiscal invoice is created for it. | Field | Notes | | --- | --- | | `reason` | Free text, up to 255 characters. **Wolt may show it to the customer**, so keep it presentable | | `code` | `GENERIC`, `ITEMS_UNAVAILABLE` or `VENUE_CLOSING_SOON`. Defaults to `GENERIC` | Both are optional, but sending a specific `code` helps Wolt route the customer to a sensible alternative instead of a generic apology. Full URL: `https://fature.al/api/partner/v1/wolt/orders/{id}/reject` Authentication: required (bearer token). #### Path parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `id` | integer | yes | The order's Fatureal id, from the feed or the order list. | #### Header parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `Idempotency-Key` | string | yes | Your own unique key for this action. A retry with the same key replays the first result instead of relaying a second action to Wolt, and the replay carries an Idempotent-Replayed: true header. Kept for 24 hours. | #### Body parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `reason` | string, maxLength 255, nullable | no | A short human-readable reason; Wolt may show it to the customer. | | `code` | string, nullable | no | Machine reason code. Defaults to GENERIC. | #### Example request ```bash curl -X POST 'https://fature.al/api/partner/v1/wolt/orders/8801/reject' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -H 'Idempotency-Key: a2f1c9e4-5b60-4d7a-9c31-8e0f2b6d4a17' \ -d '{ "reason": "Kitchen is closing", "code": "ITEMS_UNAVAILABLE" }' ``` #### Responses **201** — Created | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.order` | object | | | `data.order.customer` | object | | | `data.order.customer.name` | string, nullable | | | `data.order.customer.phone` | string, nullable | Shared by Wolt only for self-delivery orders | | `data.order.customer.note` | string, nullable | Customer note left with the order | | `data.order.company` | object, nullable | B2B billing company, or null for a normal consumer order | | `data.order.company.tax_id` | string | Tax id (NUIS/NIPT) the customer asked to bill | | `data.order.company.name` | string, nullable | | | `data.order.company.address` | string, nullable | | | `data.order.preorder` | object, nullable | Scheduled pre-order info, or null for an instant order | | `data.order.preorder.time` | string | Scheduled time (ISO-8601) | | `data.order.preorder.status` | string, nullable | Wolt pre-order status | | `data.order.lines` | array | | | `data.order.lines[].name` | string | Item name | | `data.order.lines[].quantity` | number | | | `data.order.lines[].unit_price` | number | Unit price in major units | | `data.order.lines[].total` | number | Line total in major units, after discount | | `data.order.lines[].discount` | number | Discount applied to the line, major units | | `data.order.lines[].product` | object, nullable | Linked internal product, or null when the Wolt item is unmapped | | `data.order.lines[].options` | array | Chosen modifiers/options for the line | | `data.order.totals` | object | | | `data.order.totals.subtotal_before_discount` | number | Basket total before any discount, major units | | `data.order.totals.discount` | number | Total discount applied, major units | | `data.order.totals.total` | number | Charged total, major units | | `data.order.totals.currency` | string | ISO 4217 currency code | | `data.order.totals.campaigns` | array | Applied promotion labels | ```json { "status": true, "data": { "order": { "customer": { "name": "Jane Doe", "phone": "+15551234567", "note": "note" }, "company": { "tax_id": "tax id", "name": "Jane Doe", "address": "1 Example Street" }, "preorder": { "time": "time", "status": "status" }, "lines": [ { "name": "Jane Doe", "quantity": 2, "unit_price": 1999, "total": 4200, "discount": 3, "product": [], "options": [ "options" ] } ], "totals": { "subtotal_before_discount": 4200, "discount": 3, "total": 4200, "currency": "USD", "campaigns": [ "campaigns" ] } } } } ``` **400** — The Idempotency-Key header is missing. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **403** — The company has no Wolt add-on, the token has no Wolt right, or it resolves to no single active venue. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **404** — No such order for this venue. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **409** — The order's current status does not allow this action, or a call with the same Idempotency-Key is still in flight. Nothing was relayed to Wolt. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **422** — The reject code is not one of GENERIC, ITEMS_UNAVAILABLE or VENUE_CLOSING_SOON, or the action failed on our side. A validation failure adds an errors object to the envelope. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **429** — Rate limit reached: 60 writes a minute per token. Retry after the number of seconds in the Retry-After header. | Field | Type | Description | | --- | --- | --- | | `message` | string | | ```json { "message": "Hello there" } ``` **502** — Wolt refused or did not answer. Safe to retry with the same Idempotency-Key. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` ### POST /api/partner/v1/wolt/orders/{id}/retry-fiscalize Retry a deferred or failed fiscalisation for this order Use it when `fiscal_state` is `deferred` or `failed`, which happens when the tax service was unreachable at the moment the invoice was issued. The retry does whichever of these applies: - the order already has an unfiscalised invoice, so that invoice is fiscalised; - the order has no invoice at all, so one is issued and fiscalised now. **A cancelled order cannot be fiscalised** and the call is refused. Retrying an order that is already fiscalised is harmless and changes nothing. Full URL: `https://fature.al/api/partner/v1/wolt/orders/{id}/retry-fiscalize` Authentication: required (bearer token). #### Path parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `id` | integer | yes | The order's Fatureal id, from the feed or the order list. | #### Header parameters | Name | Type | Required | Description | | --- | --- | --- | --- | | `Idempotency-Key` | string | yes | Your own unique key for this action. A retry with the same key replays the first result instead of relaying a second action to Wolt, and the replay carries an Idempotent-Replayed: true header. Kept for 24 hours. | #### Example request ```bash curl -X POST 'https://fature.al/api/partner/v1/wolt/orders/8801/retry-fiscalize' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' \ -H 'Idempotency-Key: a2f1c9e4-5b60-4d7a-9c31-8e0f2b6d4a17' ``` #### Responses **201** — Created | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.order` | object | | | `data.order.customer` | object | | | `data.order.customer.name` | string, nullable | | | `data.order.customer.phone` | string, nullable | Shared by Wolt only for self-delivery orders | | `data.order.customer.note` | string, nullable | Customer note left with the order | | `data.order.company` | object, nullable | B2B billing company, or null for a normal consumer order | | `data.order.company.tax_id` | string | Tax id (NUIS/NIPT) the customer asked to bill | | `data.order.company.name` | string, nullable | | | `data.order.company.address` | string, nullable | | | `data.order.preorder` | object, nullable | Scheduled pre-order info, or null for an instant order | | `data.order.preorder.time` | string | Scheduled time (ISO-8601) | | `data.order.preorder.status` | string, nullable | Wolt pre-order status | | `data.order.lines` | array | | | `data.order.lines[].name` | string | Item name | | `data.order.lines[].quantity` | number | | | `data.order.lines[].unit_price` | number | Unit price in major units | | `data.order.lines[].total` | number | Line total in major units, after discount | | `data.order.lines[].discount` | number | Discount applied to the line, major units | | `data.order.lines[].product` | object, nullable | Linked internal product, or null when the Wolt item is unmapped | | `data.order.lines[].options` | array | Chosen modifiers/options for the line | | `data.order.totals` | object | | | `data.order.totals.subtotal_before_discount` | number | Basket total before any discount, major units | | `data.order.totals.discount` | number | Total discount applied, major units | | `data.order.totals.total` | number | Charged total, major units | | `data.order.totals.currency` | string | ISO 4217 currency code | | `data.order.totals.campaigns` | array | Applied promotion labels | ```json { "status": true, "data": { "order": { "customer": { "name": "Jane Doe", "phone": "+15551234567", "note": "note" }, "company": { "tax_id": "tax id", "name": "Jane Doe", "address": "1 Example Street" }, "preorder": { "time": "time", "status": "status" }, "lines": [ { "name": "Jane Doe", "quantity": 2, "unit_price": 1999, "total": 4200, "discount": 3, "product": [], "options": [ "options" ] } ], "totals": { "subtotal_before_discount": 4200, "discount": 3, "total": 4200, "currency": "USD", "campaigns": [ "campaigns" ] } } } } ``` **400** — The Idempotency-Key header is missing. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **403** — The company has no Wolt add-on, the token has no Wolt right, or it resolves to no single active venue. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **404** — No such order for this venue. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **409** — The order's current status does not allow this action, or a call with the same Idempotency-Key is still in flight. Nothing was relayed to Wolt. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **422** — The action failed on our side and was not completed. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **429** — Rate limit reached: 60 writes a minute per token. Retry after the number of seconds in the Retry-After header. | Field | Type | Description | | --- | --- | --- | | `message` | string | | ```json { "message": "Hello there" } ``` **502** — Wolt refused or did not answer. Safe to retry with the same Idempotency-Key. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` ### GET /api/partner/v1/wolt/ping Ping Verify the token and return the single Wolt venue it is bound to. Call this first to confirm credentials and discover which company/branch/venue the token operates on. Full URL: `https://fature.al/api/partner/v1/wolt/ping` Authentication: required (bearer token). #### Example request ```bash curl -X GET 'https://fature.al/api/partner/v1/wolt/ping' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'X-Client-Id: YOUR_CLIENT_ID' \ -H 'X-Client-Secret: YOUR_CLIENT_SECRET' \ -H 'Accept: application/json' ``` #### Responses **200** — OK | Field | Type | Description | | --- | --- | --- | | `status` | boolean | | | `data` | object | | | `data.company` | string | | | `data.branch` | string | | | `data.venue_id` | string | | | `data.connection_status` | string | | | `data.server_time` | string | | ```json { "status": true, "data": { "company": "company", "branch": "branch", "venue_id": "venue id", "connection_status": "connection status", "server_time": "server time" } } ``` **403** — The company has no Wolt add-on, the token has no Wolt right, or it resolves to no single active venue. | Field | Type | Description | | --- | --- | --- | | `status` | boolean | Always false | | `message` | string | Localised explanation, safe to log but not to branch on | | `code` | string | Stable machine readable reason: `unauthenticated`, `wolt_not_enabled`, `forbidden`, `no_venue`, `order_not_found`, `invalid_transition`, `invalid_data`, `action_failed`, `wolt_upstream_error`, `idempotency_key_required`, `idempotency_in_progress` | ```json { "status": true, "message": "Hello there", "code": "code" } ``` **429** — Rate limit reached: 180 reads a minute per token. Retry after the number of seconds in the Retry-After header. | Field | Type | Description | | --- | --- | --- | | `message` | string | | ```json { "message": "Hello there" } ```