# F-sąskaita API > Programiškai kurkite ir tvarkykite Lietuvos verslo sąskaitas faktūras ir išlaidas. REST, JSON, bearer prieigos raktai, webhook pranešimai. F-sąskaita API leidžia išrašyti sąskaitas faktūras, registruoti išlaidas ir atsisiųsti dokumentus verslui, kurį valdote [app.fsaskaita.lt](https://app.fsaskaita.lt). Tai nedidelė REST API: JSON įeina, JSON išeina, bearer prieigos raktai, priskirti vienam verslui. ``` https://app.fsaskaita.lt/api ``` ## Ką galite daryti | Resursas | Operacijos | |---|---| | Sąskaitos faktūros | sąrašas, kūrimas, peržiūra, atnaujinimas, šalinimas, PDF atsisiuntimas | | Išlaidos | sąrašas, kūrimas su failu, peržiūra, atnaujinimas, failo pakeitimas, šalinimas, failo atsisiuntimas | | Profilis | verslo, kuriam priklauso prieigos raktas, peržiūra | | Valiutos | priimamų valiutų kodų sąrašas | | Webhook pranešimai | gaukite `invoice.*` ir `expense.*` įvykius į savo HTTPS galinį tašką | ## Pradėkite čia 1. [Autentifikacija](/lt/guides/authentication): sukurkite verslo prieigos raktą ir atlikite pirmą užklausą. 2. [Sąskaitos faktūros](/lt/guides/invoices): sąskaitos modelis, numeracija ir kūrimo užklausa. 3. [Išlaidos](/lt/guides/expenses): multipart įkėlimai ir failo pakeitimas. 4. [Webhook pranešimai](/lt/guides/webhooks): prenumerata, parašo tikrinimas, pakartotiniai siuntimai. 5. [Konvencijos](/lt/guides/conventions): puslapiavimas, klaidos, užklausų limitai, datos ir pinigų sumos. [Žinynas](/lt/reference) aprašo visus galinius taškus. Pati specifikacija pasiekiama adresu [`/openapi.json`](/openapi.json). ## AI agentams Skaitykite [`/llms.txt`](/lt/llms.txt), kur pateiktas visų puslapių indeksas, [`/llms-full.txt`](/lt/llms-full.txt), kur yra visas tekstas, ir [agentų puslapį](/lt/agents), kuriame glaustai aprašyta, kaip integruotis. Instrukcijos agentui: https://docs.fsaskaita.lt/agents/prompt.md ## Plano reikalavimas API prieiga ir webhook pranešimai įtraukti į Premium planą. Kituose planuose prieigos rakto ir webhook nustatymai programėlėje nepasiekiami. --- # Integracija AI agentams > Glaustas, agentams skirtas F-sąskaita API aprašymas. Bazinis URL, autentifikacija, specifikacijos vieta, puslapiavimas, klaidų apdorojimas ir taisyklės, padedančios išvengti dažnų klaidų. Šis puslapis skirtas LLM agentams ir programavimo asistentams. Jis sąmoningai glaustas. Žmonėms gali būti patogesni [gidai](/lt/guides/authentication). ## Faktai - Bazinis URL: `https://app.fsaskaita.lt/api` - OpenAPI 3.1 specifikacija: `https://docs.fsaskaita.lt/openapi.json` - Visa dokumentacija tekstu: `https://docs.fsaskaita.lt/lt/llms-full.txt` - Autentifikacija: `Authorization: Bearer `. Prieigos raktas priklauso vienam verslui; naudotojo lygio ar kelių verslų prieigos rakto nėra. - Visada siųskite `Accept: application/json`. Be jo neautentifikuotos ir užklausų limitą viršijusios užklausos vietoj JSON grąžina HTML peradresavimą arba puslapį. - Sąskaitų faktūrų ir profilio turinio tipas: `application/json`. Išlaidos naudoja `multipart/form-data`, nes kartu siunčiamas failas. - Užklausų limitas: 60 užklausų per minutę vienam verslui, bendras visiems jo prieigos raktams. Skaitykite `X-RateLimit-Remaining`; gavę `429`, laukite `Retry-After` sekundžių. - Puslapiavimas: `?page=N`, fiksuotai 50 įrašų puslapyje, filtravimo ar rikiavimo parametrų nėra. Atsakymo forma `{ "data": [...], "meta": { "current_page", "last_page", "per_page", "total", "from", "to", "path" } }`. - Pavieniai resursai įvilkti: `{ "data": { ... } }`. - Identifikatoriai yra UUID eilutės. Datos – `YYYY-MM-DD`. `created_at` ir `updated_at` – Unix laiko žymos sekundėmis. Pinigų sumos – JSON skaičiai. Valiutų kodai – didžiosiomis raidėmis pagal ISO 4217 ir privalo būti `GET /currencies` sąraše. - Šalinimas grąžina `200` su tuščiu atsakymo turiniu. - Validacijos klaidos grąžina `422` su `{ "message": "...", "errors": { "field.path": ["..."] } }`. Pranešimai yra lietuvių kalba. - Kitam verslui priklausantys resursai grąžina `404`. ## Taisyklės, padedančios išvengti klaidų 1. Atnaujindami sąskaitą faktūrą per `PUT /invoices/{id}`, siųskite visą sąskaitą, įskaitant jos dabartinį `invoice_number`. Nenurodžius numerio, priskiriamas naujas numeris iš serijos skaitiklio. 2. Kiekvienai sąskaitos eilutei siųskite lygiai vieną iš `price`, `total` arba `total_incl_vat`. Kitus du serveris apskaičiuoja pats. 3. `type` reikšmės, kurios baigiasi `vat_invoice`, yra PVM sąskaitos faktūros. Joms kiekvienoje eilutėje privalomas `vat_percentage` ir pardavėjo `vat_code` (kai `use_default_seller_info` yra `true`, imamas jūsų kodas iš profilio). 4. Rinkitės `use_default_seller_info: true`, nebent kviečiantysis aiškiai nori pakeisti pardavėjo duomenis. 5. Sąskaitų juodraščiai API niekada nerodomi. Viskas, ką API sukuria, yra užbaigta, sunumeruota sąskaita faktūra. 6. Jei PDF dar neparengtas, `GET /invoices/{id}/download` jo laukia iki maždaug 20 sekundžių, todėl kvieskite šį galinį tašką po sukūrimo, o ne tikėkitės failo kūrimo atsakyme. 7. Webhook pranešimų turinys yra `{ "event": "", "data": { ... } }`, pasirašytas neapdoroto turinio HMAC-SHA256 parašu antraštėje `Signature`. Prieš pasitikėdami turiniu, patikrinkite jį su prenumeratos paslaptimi. Pristatymas bandomas iki 3 kartų (du pakartojimai – po 10 s ir po 100 s); laikykite juos „bent vieną kartą“ pristatymais. 8. Prieigos raktų ar webhook prenumeratų valdymo API nėra. Abu kuria žmogus programėlėje, skiltyje Nustatymai, Integracijos. 9. Idempotentiškumo rakto nėra. Nekartokite `POST` užklausos, kuri grąžino tinklo klaidą, prieš tai neperžiūrėję naujausių sąskaitų sąrašo. ## Instrukcijos jūsų agentui Įklijuokite tai į savo programavimo agentą arba nurodykite jam `https://docs.fsaskaita.lt/agents/prompt.md`. ```text Implement invoicing in this project with the F-sąskaita API. Read first, in this order: 1. https://docs.fsaskaita.lt/llms.txt — the index of every documentation page. Fetch the Invoices and Conventions guides from it. 2. https://docs.fsaskaita.lt/openapi.json — the Spec: every endpoint, field and enum. Take field names and behaviour from the Spec. Where this prompt and the Spec disagree, the Spec wins. Facts - Base URL: https://app.fsaskaita.lt/api. JSON in, JSON out. - Authentication: a Business token, scoped to one business, sent as `Authorization: Bearer `. Read it from the FSASKAITA_TOKEN environment variable and keep it out of code, logs and version control. - Send `Accept: application/json` on every request; without it, 401 and 429 responses are HTML. - Rate limit: 60 requests per minute per business. On 429, wait `Retry-After` seconds, then retry. - Validation errors: 422 with `{ "message", "errors": { "field.path": ["..."] } }`. Messages are in Lithuanian; show them to the user unchanged. - Lists: `?page=N`, 50 per page, newest first, no filters. Single resources are wrapped in `{ "data": ... }`. - Identifiers are UUIDs, dates are `YYYY-MM-DD`, money values are JSON numbers, currency codes are uppercase ISO 4217 and must appear in `GET /currencies`. Build 1. One client module with a narrow interface: base URL, both headers, JSON encoding, and typed errors for 401, 404, 422, 429 and 500. Retry only on 429, and only GET, PUT and DELETE. 2. createInvoice(input): `POST /invoices`. Default `use_default_seller_info: true`. For each line in `products` send exactly one of `price`, `total` or `total_incl_vat`. Types ending in `vat_invoice` need `vat_percentage` on every line. Omit `invoice_number` so the series assigns the next one. Return `data` from the 201 response; it includes `share_link`, a public page where the buyer views and downloads the invoice. 3. downloadInvoicePdf(id): `GET /invoices/{id}/download`, called after create. Stream the body: there is no Content-Length, and the response can take up to about 20 seconds if the PDF is not ready yet. 4. updateInvoice(id, input): `PUT /invoices/{id}` replaces the whole invoice. Read it first, change what you need, and send it back including the current `invoice_number`; an update without it renumbers the invoice. 5. Webhooks, when the project needs them: an HTTPS endpoint that verifies the `Signature` header (hex HMAC-SHA256 of the raw body with the subscription secret) before parsing, and treats deliveries as at-least-once. Rules - There is no idempotency key. After a network error on POST, list recent invoices with `GET /invoices` and check before creating again. - Every invoice the API creates is final and numbered; drafts exist only in the app. - Tokens and webhook subscriptions have no API. A person creates them in the app under Settings, Integrations, and the integration reads them from configuration. Done when - Unit tests with recorded responses cover 201, 422 and 429. - A live check runs only when FSASKAITA_TOKEN is set. It creates a real, numbered invoice, so ask before running it and delete the invoice afterwards with `DELETE /invoices/{id}`. - Your report names what you built, which endpoints you used, and what in the Spec you left out. ``` ## Minimali užklausa ```bash curl https://app.fsaskaita.lt/api/profile \ -H "Authorization: Bearer $FSASKAITA_TOKEN" \ -H "Accept: application/json" ``` ## Kur žiūrėti toliau - Galinių taškų formos ir visi laukai: [OpenAPI specifikacija](/openapi.json) arba [Žinynas](/lt/reference). - Išsamūs sąskaitų faktūrų užklausų pavyzdžiai: [Sąskaitos faktūros](/lt/guides/invoices). - Parašo tikrinimo kodas: [Webhook pranešimai](/lt/guides/webhooks). - Elgsenos pokyčiai laikui bėgant: [Pakeitimų žurnalas](/lt/changelog), taip pat pasiekiamas RSS formatu adresu `/changelog.xml`. --- # Pakeitimų žurnalas > Public API ir integracijų pakeitimai. ## 2026-09-08 — Nauja programuotojų dokumentacija docs.fsaskaita.lt F-sąskaita API dokumentacija dabar pasiekiama docs.fsaskaita.lt: integravimo gidai, pilnas API žinynas ir šis pakeitimų žurnalas. --- # Autentifikacija > Sukurkite verslo prieigos raktą programėlėje, siųskite jį kaip bearer prieigos raktą ir supraskite jo apimtį bei galiojimą. Kiekviena užklausa į F-sąskaita API autentifikuojama **verslo prieigos raktu** (Business token). Prieigos raktas identifikuoja vieną jūsų paskyros verslą, ir kiekviena sąskaita faktūra, išlaidų dokumentas ar profilis, su kuriuo dirbate, priklauso tam verslui. ## Sukurkite prieigos raktą 1. Prisijunkite prie [app.fsaskaita.lt](https://app.fsaskaita.lt) kaip naudotojas, galintis valdyti verslą. 2. Atidarykite **Nustatymai**, tada **Integracijos**, tada **API**. 3. Suteikite prieigos raktui pavadinimą, iš kurio aišku, kur jis naudojamas, pavyzdžiui `accounting-sync`, ir sukurkite jį. 4. Iš karto nusikopijuokite prieigos raktą. Jis parodomas tik vieną kartą. Vėliau sąraše matomas tik jo pavadinimas. Prieigos raktai pasiekiami tik planuose, kuriuose įtraukta API funkcija. Jei vietoj formos skiltyje rodomas pranešimas apie plano atnaujinimą, dabartinis planas jos neapima. ## Naudokite prieigos raktą Siųskite jį antraštėje `Authorization` ir visada prašykite JSON: ```bash tab="cURL" tab-group="request" curl https://app.fsaskaita.lt/api/profile \ -H "Authorization: Bearer $FSASKAITA_TOKEN" \ -H "Accept: application/json" ``` ```js tab="JavaScript" tab-group="request" const response = await fetch('https://app.fsaskaita.lt/api/profile', { headers: { Authorization: `Bearer ${process.env.FSASKAITA_TOKEN}`, Accept: 'application/json', }, }); console.log(response.status, await response.json()); ``` ```go tab="Go" tab-group="request" package main import ( "fmt" "io" "net/http" "os" ) func main() { req, _ := http.NewRequest("GET", "https://app.fsaskaita.lt/api/profile", nil) req.Header.Set("Authorization", "Bearer "+os.Getenv("FSASKAITA_TOKEN")) req.Header.Set("Accept", "application/json") res, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(res.Status, string(body)) } ``` ```python tab="Python" tab-group="request" import os import requests response = requests.get( "https://app.fsaskaita.lt/api/profile", headers={ "Authorization": f"Bearer {os.environ['FSASKAITA_TOKEN']}", "Accept": "application/json", }, ) print(response.status_code, response.json()) ``` ```java tab="Java" tab-group="request" import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; public class GetProfile { public static void main(String[] args) throws Exception { HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.fsaskaita.lt/api/profile")) .header("Authorization", "Bearer " + System.getenv("FSASKAITA_TOKEN")) .header("Accept", "application/json") .GET() .build(); HttpResponse response = HttpClient.newHttpClient() .send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.statusCode() + " " + response.body()); } } ``` ```csharp tab="C#" tab-group="request" using System.Net.Http.Headers; using var client = new HttpClient(); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue( "Bearer", Environment.GetEnvironmentVariable("FSASKAITA_TOKEN")); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); var response = await client.GetAsync("https://app.fsaskaita.lt/api/profile"); Console.WriteLine($"{(int)response.StatusCode} {await response.Content.ReadAsStringAsync()}"); ``` Sėkmingas atsakymas aprašo verslą, kuriam priklauso prieigos raktas: ```json { "data": { "business_id": "9c1f7b2e-3a6d-4d5e-9f0a-2b7c8d9e0f11", "business_title": "Pavyzdys, MB", "business_type": "small_partnership", "address": "Gedimino pr. 1, Vilnius", "vat_code": "LT100001234567", "company_name": "Pavyzdys, MB", "company_code": "305000001" } } ``` Jei verslas registruotas kaip individuali veikla, profilyje vietoj `company_name` ir `company_code` pateikiami `individual_activity_id`, `first_name` ir `last_name`. ## Kodėl svarbi Accept antraštė Programos klaidos bet kuriuo atveju grąžinamos JSON formatu. Tačiau be `Accept: application/json` trūkstamas arba panaikintas prieigos raktas gauna HTML peradresavimą į prisijungimo puslapį, o užklausų limitą viršijusi užklausa – HTML klaidos puslapį. Su šia antrašte gausite `401 {"message":"Unauthenticated."}` ir `429 {"message":"Too Many Attempts."}`. ## Apimtis ir galiojimas - Prieigos raktas suteikia pilną prieigą prie savo verslo. Atskirų teisių pagal galinius taškus nėra. - Prieigos raktų galiojimas nesibaigia. Raktą panaikinsite ištrynę jį tame pačiame nustatymų puslapyje; užklausos su ištrintu raktu gauna `401`. - Jei jūsų paskyroje yra keli verslai, kiekvienam sukurkite atskirą prieigos raktą. - Visi vieno verslo prieigos raktai dalijasi tuo pačiu 60 užklausų per minutę limitu. ## Laikykite jį paslaptyje Su prieigos raktu elkitės kaip su slaptažodžiu. Saugokite jį paslapčių tvarkyklėje arba aplinkos kintamajame, niekada – repozitorijoje ar naršyklės pusės programoje. Jei prieigos raktas nutekėjo, ištrinkite jį programėlėje ir sukurkite naują. --- # Konvencijos, klaidos ir užklausų limitai > Užklausų ir atsakymų formatai, puslapiavimas, identifikatoriai, datos ir pinigų sumos, HTTP būsenos kodai ir 60 užklausų per minutę limitas. ## Užklausos - Bazinis URL `https://app.fsaskaita.lt/api`. - Antraštės kiekvienoje užklausoje: `Authorization: Bearer ` ir `Accept: application/json`. - Sąskaitų faktūrų galiniai taškai priima JSON turinį (`Content-Type: application/json`). Išlaidų galiniai taškai priima `multipart/form-data`, nes kartu keliauja failas. - Šioje API `PUT` ir `PATCH` yra lygiaverčiai. Abu pakeičia visą resursą jūsų siunčiamu turiniu, todėl visada siųskite visus laukus. ## Atsakymai Pavienis resursas įvilktas į `data`: ```json { "data": { "id": "…", "…": "…" } } ``` Sąrašas įvilktas į `data` su `meta` bloku: ```json { "data": [ … ], "meta": { "current_page": 1, "from": 1, "last_page": 3, "path": "https://app.fsaskaita.lt/api/invoices", "per_page": 50, "to": 50, "total": 132 } } ``` Šalinimas grąžina `200` su tuščiu turiniu. ## Puslapiavimas Sąrašai grąžina 50 įrašų puslapyje, naujausius pirmus, ir priima tik `?page=N`. Filtrų, rikiavimo parametrų ar puslapio dydžio pasirinkimų nėra. Sinchronizuodami eikite per puslapius, kol `current_page` susilygins su `last_page`. `GET /currencies` nepuslapiuojamas. ## Identifikatoriai, datos, pinigų sumos | Tipas | Formatas | Pavyzdys | |---|---|---| | Identifikatoriai | UUID eilutė | `"9c1f7b2e-3a6d-4d5e-9f0a-2b7c8d9e0f11"` | | Datos užklausose ir atsakymuose | `YYYY-MM-DD` | `"2026-09-08"` | | `created_at`, `updated_at` | Unix laiko žyma, sekundės, sveikasis skaičius | `1757318400` | | Pinigų sumos | JSON skaičius | `60.5` | | Valiuta | ISO 4217 kodas didžiosiomis raidėmis, priimamas `GET /currencies` | `"EUR"` | | Sąskaitų numeriai | eilutė, atsakymuose užpildyta nuliais iki trijų skaitmenų | `"007"` | Išvardintosios reikšmės yra mažųjų raidžių snake_case eilutės, pavyzdžiui `vat_invoice` arba `not_paid`. Žinyne pateiktos leidžiamos kiekvieno lauko reikšmės. ## Klaidos | Būsena | Reikšmė | Turinys | |---|---|---| | `401` | Trūkstamas, neteisingas arba ištrintas prieigos raktas | `{"message":"Unauthenticated."}` | | `404` | Nežinomas id arba resursas priklauso kitam verslui | `{"message":"…"}` | | `422` | Validacija nepavyko | žr. toliau | | `429` | Viršytas užklausų limitas | `{"message":"Too Many Attempts."}` ir `Retry-After` | | `500` | Netikėta serverio klaida | `{"message":"Server Error"}` | Validacijos klaidos išvardija visus netinkamus laukus. Įdėtiniams laukams naudojami taškiniai keliai. Pranešimai yra lietuvių kalba. ```json { "message": "Laukas type yra privalomas. (and 2 more errors)", "errors": { "type": ["Laukas type yra privalomas."], "buyer.company_name": ["…"], "products.0.quantity": ["…"] } } ``` `403` nėra. Prieigos raktas arba veikia savo verslui, arba atmetamas su `401`. ## Užklausų limitai Kiekvienas verslas gali atlikti 60 užklausų per minutę visais savo prieigos raktais kartu. Kiekvienas atsakymas turi antraštes `X-RateLimit-Limit` ir `X-RateLimit-Remaining`. Pasiekus limitą, atsakymas yra `429` su `Retry-After` sekundėmis ir `X-RateLimit-Reset` kaip Unix laiko žyma. Palaukite iki tol; bandant anksčiau gausite tik daugiau `429` atsakymų. ## Idempotentiškumas ir pakartotiniai bandymai API neturi idempotentiškumo rakto. `POST` užklausa, kuriai baigėsi tinklo laukimo laikas, vis tiek galėjo sukurti resursą. Prieš kartodami, peržiūrėkite naujausių įrašų sąrašą ir patikrinkite, ar jūsiškis jau yra. `PUT` ir `DELETE` kartoti saugu. ## Lokalizacija Validacijos pranešimai ir tipo pavadinimas PDF failų pavadinimuose yra lietuvių kalba, nebent sąskaitos `language` nurodo kitaip. `Accept-Language` derinimo nėra. --- # Išlaidos > Registruokite pirkimo dokumentus su jų failu, atnaujinkite juos, pakeiskite failą ir atsisiųskite originalą. Išlaidų dokumentas – tai jūsų gautas pirkimo dokumentas: tiekėjo sąskaita faktūra, kvitas, mokėjimo pranešimas. API saugo jo pagrindinius skaičius ir originalų failą. Kadangi failas keliauja kartu su užklausa, išlaidų galiniai taškai naudoja `multipart/form-data`, o ne JSON. ## Galiniai taškai | Metodas | Kelias | Aprašymas | |---|---|---| | `GET` | [`/expenses`](/lt/reference/expenses/listExpenses/) | List expenses | | `POST` | [`/expenses`](/lt/reference/expenses/createExpense/) | Create an expense | | `GET` | [`/expenses/{expense}`](/lt/reference/expenses/getExpense/) | Get an expense | | `DELETE` | [`/expenses/{expense}`](/lt/reference/expenses/deleteExpense/) | Delete an expense | | `PUT` | [`/expenses/{expense}`](/lt/reference/expenses/updateExpense/) | Replace an expense | | `POST` | [`/expenses/{expense}/file`](/lt/reference/expenses/replaceExpenseFile/) | Replace the expense file | | `GET` | [`/expenses/{expense}/download`](/lt/reference/expenses/downloadExpenseFile/) | Download the expense file | ## Laukai | Laukas | Privalomas | Pastabos | |---|---|---| | `file` | kuriant | Vienas failas. Leidžiami plėtiniai: `pdf`, `jpg`, `jpeg`, `png`, `gif`, `bmp`, `tiff`, `xls`, `xlsx`, `doc`, `docx`, `odf` | | `date` | taip | `YYYY-MM-DD`, dokumento data | | `total` | taip | Suma su PVM, skaičius | | `currency` | taip | Kodas iš `GET /currencies`, pavyzdžiui `EUR` | | `seller` | taip | Tiekėjo pavadinimas, iki 255 simbolių | | `vat` | ne | PVM suma, skaičius | | `invoice_number` | ne | Tiekėjo dokumento numeris | ## Sukurkite išlaidų dokumentą ```bash tab="cURL" tab-group="request" curl -X POST https://app.fsaskaita.lt/api/expenses \ -H "Authorization: Bearer $FSASKAITA_TOKEN" \ -H "Accept: application/json" \ -F "file=@receipt.pdf" \ -F "date=2026-09-08" \ -F "total=60.50" \ -F "vat=10.50" \ -F "currency=EUR" \ -F "seller=Telia Lietuva, AB" \ -F "invoice_number=TL-2026-000123" ``` ```js tab="JavaScript" tab-group="request" import { openAsBlob } from 'node:fs'; const form = new FormData(); form.append('file', await openAsBlob('receipt.pdf', { type: 'application/pdf' }), 'receipt.pdf'); form.append('date', '2026-09-08'); form.append('total', '60.50'); form.append('vat', '10.50'); form.append('currency', 'EUR'); form.append('seller', 'Telia Lietuva, AB'); form.append('invoice_number', 'TL-2026-000123'); const response = await fetch('https://app.fsaskaita.lt/api/expenses', { method: 'POST', headers: { Authorization: `Bearer ${process.env.FSASKAITA_TOKEN}`, Accept: 'application/json', }, body: form, }); console.log(response.status, await response.json()); ``` ```go tab="Go" tab-group="request" package main import ( "bytes" "fmt" "io" "mime/multipart" "net/http" "os" ) func main() { var body bytes.Buffer form := multipart.NewWriter(&body) file, err := os.Open("receipt.pdf") if err != nil { panic(err) } defer file.Close() part, _ := form.CreateFormFile("file", "receipt.pdf") if _, err := io.Copy(part, file); err != nil { panic(err) } for name, value := range map[string]string{ "date": "2026-09-08", "total": "60.50", "vat": "10.50", "currency": "EUR", "seller": "Telia Lietuva, AB", "invoice_number": "TL-2026-000123", } { form.WriteField(name, value) } form.Close() req, _ := http.NewRequest("POST", "https://app.fsaskaita.lt/api/expenses", &body) req.Header.Set("Authorization", "Bearer "+os.Getenv("FSASKAITA_TOKEN")) req.Header.Set("Accept", "application/json") req.Header.Set("Content-Type", form.FormDataContentType()) res, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer res.Body.Close() response, _ := io.ReadAll(res.Body) fmt.Println(res.Status, string(response)) } ``` ```python tab="Python" tab-group="request" import os import requests with open("receipt.pdf", "rb") as file: response = requests.post( "https://app.fsaskaita.lt/api/expenses", headers={ "Authorization": f"Bearer {os.environ['FSASKAITA_TOKEN']}", "Accept": "application/json", }, data={ "date": "2026-09-08", "total": "60.50", "vat": "10.50", "currency": "EUR", "seller": "Telia Lietuva, AB", "invoice_number": "TL-2026-000123", }, files={"file": ("receipt.pdf", file, "application/pdf")}, ) print(response.status_code, response.json()) ``` ```java tab="Java" tab-group="request" import java.io.ByteArrayOutputStream; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.Map; import java.util.UUID; public class CreateExpense { public static void main(String[] args) throws Exception { String boundary = UUID.randomUUID().toString(); Map fields = Map.of( "date", "2026-09-08", "total", "60.50", "vat", "10.50", "currency", "EUR", "seller", "Telia Lietuva, AB", "invoice_number", "TL-2026-000123"); ByteArrayOutputStream body = new ByteArrayOutputStream(); for (Map.Entry field : fields.entrySet()) { body.write(("--" + boundary + "\r\n" + "Content-Disposition: form-data; name=\"" + field.getKey() + "\"\r\n\r\n" + field.getValue() + "\r\n").getBytes(StandardCharsets.UTF_8)); } body.write(("--" + boundary + "\r\n" + "Content-Disposition: form-data; name=\"file\"; filename=\"receipt.pdf\"\r\n" + "Content-Type: application/pdf\r\n\r\n").getBytes(StandardCharsets.UTF_8)); body.write(Files.readAllBytes(Path.of("receipt.pdf"))); body.write(("\r\n--" + boundary + "--\r\n").getBytes(StandardCharsets.UTF_8)); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.fsaskaita.lt/api/expenses")) .header("Authorization", "Bearer " + System.getenv("FSASKAITA_TOKEN")) .header("Accept", "application/json") .header("Content-Type", "multipart/form-data; boundary=" + boundary) .POST(HttpRequest.BodyPublishers.ofByteArray(body.toByteArray())) .build(); HttpResponse response = HttpClient.newHttpClient() .send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.statusCode() + " " + response.body()); } } ``` ```csharp tab="C#" tab-group="request" using System.Net.Http.Headers; using var client = new HttpClient(); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue( "Bearer", Environment.GetEnvironmentVariable("FSASKAITA_TOKEN")); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); using var form = new MultipartFormDataContent(); var file = new StreamContent(File.OpenRead("receipt.pdf")); file.Headers.ContentType = new MediaTypeHeaderValue("application/pdf"); form.Add(file, "file", "receipt.pdf"); form.Add(new StringContent("2026-09-08"), "date"); form.Add(new StringContent("60.50"), "total"); form.Add(new StringContent("10.50"), "vat"); form.Add(new StringContent("EUR"), "currency"); form.Add(new StringContent("Telia Lietuva, AB"), "seller"); form.Add(new StringContent("TL-2026-000123"), "invoice_number"); var response = await client.PostAsync("https://app.fsaskaita.lt/api/expenses", form); Console.WriteLine($"{(int)response.StatusCode} {await response.Content.ReadAsStringAsync()}"); ``` Atsakymas: ```json { "data": { "id": "2a7d6c1b-8e9f-4a0b-9c1d-2e3f4a5b6c7d", "date": "2026-09-08", "total": 60.5, "currency": "EUR", "seller": "Telia Lietuva, AB", "created_at": 1757318400, "updated_at": 1757318400 } } ``` Atsakyme negrąžinami `vat`, `invoice_number` ir failo metaduomenys. Jei jų reikia, saugokite juos savo pusėje; patį failą visada galima atsisiųsti per atsisiuntimo galinį tašką. ## Atnaujinimas `PUT /expenses/{id}` priima tuos pačius multipart laukus. `file` čia neprivalomas; jei pateiktas, jis pakeičia saugomą failą. Daug HTTP klientų negali siųsti multipart turinio su `PUT`. Naudokite `PATCH`, kuris veikia identiškai, arba siųskite `POST` su papildomu formos lauku `_method=PUT` (arba antrašte `X-HTTP-Method-Override: PUT`), kurį API traktuoja kaip `PUT`. Jei reikia pakeisti tik failą, naudokite `POST /expenses/{id}/file`. ## Atsisiųskite originalą ```bash tab="cURL" tab-group="request" curl -L https://app.fsaskaita.lt/api/expenses/$ID/download \ -H "Authorization: Bearer $FSASKAITA_TOKEN" \ -H "Accept: application/json" \ -o receipt.pdf ``` ```js tab="JavaScript" tab-group="request" import { createWriteStream } from 'node:fs'; import { Readable } from 'node:stream'; import { pipeline } from 'node:stream/promises'; const id = '2a7d6c1b-8e9f-4a0b-9c1d-2e3f4a5b6c7d'; const response = await fetch(`https://app.fsaskaita.lt/api/expenses/${id}/download`, { headers: { Authorization: `Bearer ${process.env.FSASKAITA_TOKEN}`, Accept: 'application/json', }, }); if (!response.ok) throw new Error(`${response.status} ${await response.text()}`); await pipeline(Readable.fromWeb(response.body), createWriteStream('receipt.pdf')); ``` ```go tab="Go" tab-group="request" package main import ( "io" "net/http" "os" ) func main() { id := "2a7d6c1b-8e9f-4a0b-9c1d-2e3f4a5b6c7d" req, _ := http.NewRequest("GET", "https://app.fsaskaita.lt/api/expenses/"+id+"/download", nil) req.Header.Set("Authorization", "Bearer "+os.Getenv("FSASKAITA_TOKEN")) req.Header.Set("Accept", "application/json") res, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer res.Body.Close() if res.StatusCode != http.StatusOK { body, _ := io.ReadAll(res.Body) panic(res.Status + " " + string(body)) } file, err := os.Create("receipt.pdf") if err != nil { panic(err) } defer file.Close() if _, err := io.Copy(file, res.Body); err != nil { panic(err) } } ``` ```python tab="Python" tab-group="request" import os import requests expense_id = "2a7d6c1b-8e9f-4a0b-9c1d-2e3f4a5b6c7d" with requests.get( f"https://app.fsaskaita.lt/api/expenses/{expense_id}/download", headers={ "Authorization": f"Bearer {os.environ['FSASKAITA_TOKEN']}", "Accept": "application/json", }, stream=True, ) as response: response.raise_for_status() with open("receipt.pdf", "wb") as file: for chunk in response.iter_content(chunk_size=65536): file.write(chunk) ``` ```java tab="Java" tab-group="request" import java.io.InputStream; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; public class DownloadExpense { public static void main(String[] args) throws Exception { String id = "2a7d6c1b-8e9f-4a0b-9c1d-2e3f4a5b6c7d"; HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.fsaskaita.lt/api/expenses/" + id + "/download")) .header("Authorization", "Bearer " + System.getenv("FSASKAITA_TOKEN")) .header("Accept", "application/json") .GET() .build(); HttpResponse response = HttpClient.newHttpClient() .send(request, HttpResponse.BodyHandlers.ofInputStream()); try (InputStream body = response.body()) { if (response.statusCode() != 200) { throw new IllegalStateException(response.statusCode() + " " + new String(body.readAllBytes())); } Files.copy(body, Path.of("receipt.pdf"), StandardCopyOption.REPLACE_EXISTING); } } } ``` ```csharp tab="C#" tab-group="request" using System.Net.Http.Headers; var id = "2a7d6c1b-8e9f-4a0b-9c1d-2e3f4a5b6c7d"; using var client = new HttpClient(); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue( "Bearer", Environment.GetEnvironmentVariable("FSASKAITA_TOKEN")); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); using var response = await client.GetAsync( $"https://app.fsaskaita.lt/api/expenses/{id}/download", HttpCompletionOption.ResponseHeadersRead); response.EnsureSuccessStatusCode(); await using var file = File.Create("receipt.pdf"); await response.Content.CopyToAsync(file); ``` Atsakymas srautu perduoda saugomą failą su originaliu failo pavadinimu antraštėje `Content-Disposition`. Turinio tipas atitinka failą. ## Šalutiniai efektai Kūrimas išsiunčia `expense.created` [webhook pranešimą](/lt/guides/webhooks); skaičių ar failo atnaujinimas išsiunčia `expense.updated`. Šalinimas išsiunčia `expense.deleted` ir pašalina saugomą failą. --- # Sąskaitos faktūros > Sąskaitos faktūros modelis, sąskaitų tipai, numeracija ir serijos, kūrimo ir atnaujinimo užklausos bei PDF atsisiuntimas. Sąskaita faktūra F-sąskaita sistemoje – tai užbaigtas, sunumeruotas dokumentas, kurį jūsų verslas (**pardavėjas**) išrašo **pirkėjui**, su viena ar daugiau **eilučių** (`products`) ir neprivalomais **mokėjimo būdais**. API mato tik užbaigtas sąskaitas; programėlėje sukurti juodraščiai čia nematomi. ## Galiniai taškai | Metodas | Kelias | Aprašymas | |---|---|---| | `GET` | [`/invoices`](/lt/reference/invoices/listInvoices/) | List invoices | | `POST` | [`/invoices`](/lt/reference/invoices/createInvoice/) | Create an invoice | | `GET` | [`/invoices/{invoice}`](/lt/reference/invoices/getInvoice/) | Get an invoice | | `DELETE` | [`/invoices/{invoice}`](/lt/reference/invoices/deleteInvoice/) | Delete an invoice | | `PUT` | [`/invoices/{invoice}`](/lt/reference/invoices/updateInvoice/) | Replace an invoice | | `GET` | [`/invoices/{invoice}/download`](/lt/reference/invoices/downloadInvoicePdf/) | Download the invoice PDF | ## Sąskaitų tipai | `type` | PVM | Naudojimas | |---|---|---| | `regular_invoice` | ne | Standartinė sąskaita ne PVM mokėtojui | | `vat_invoice` | taip | PVM sąskaita faktūra | | `preliminary_invoice` | ne | Išankstinė sąskaita | | `preliminary_vat_invoice` | taip | Išankstinė sąskaita su PVM | | `credit_invoice` | ne | Kreditinė sąskaita | | `credit_vat_invoice` | taip | Kreditinė sąskaita su PVM | PVM tipams kiekvienoje eilutėje privalomas `vat_percentage` ir pardavėjo PVM kodas. Kai pardavėju naudojate savo profilį, PVM kodas imamas iš profilio. ## Serijos ir numeracija Kiekviena sąskaita priklauso **serijai** – trumpam kodui, tokiam kaip `SF`, – ir turi numerį, unikalų toje jūsų verslo serijoje. - Kurdami nenurodykite `invoice_number`, ir API priskirs kitą serijos numerį. Dar neegzistuojanti serija pradedama nuo `1`. - Nurodykite `invoice_number` aiškiai, kai numeraciją valdote patys. Jis privalo būti unikalus serijoje. Užpildyta nuliais (`"007"`) ir neužpildyta (`"7"`) formos lyginamos tiksliai taip, kaip išsiųstos, todėl vienoje serijoje naudokite vieną formą. - **Atnaujindami visada siųskite dabartinį `invoice_number`.** Atnaujinimas be jo priskiria naują numerį iš serijos skaitiklio. - Atsakymuose numeris grąžinamas užpildytas nuliais iki trijų skaitmenų (`"7"` grąžinamas kaip `"007"`). ## Sukurkite sąskaitą faktūrą Trumpiausia naudinga užklausa pardavėju naudoja jūsų profilį, o kainas nurodo eilutėse: ```bash tab="cURL" tab-group="request" curl -X POST https://app.fsaskaita.lt/api/invoices \ -H "Authorization: Bearer $FSASKAITA_TOKEN" \ -H "Accept: application/json" \ -H "Content-Type: application/json" \ -d @- <<'JSON' { "type": "vat_invoice", "invoice_date": "2026-09-08", "pay_until_date": "2026-09-22", "series": "SF", "currency": "EUR", "language": "lt", "use_default_seller_info": true, "buyer": { "type": "company", "company_name": "Pirkėjas, UAB", "company_code": "300000001", "vat_code": "LT100000000011", "address": "Konstitucijos pr. 7, Vilnius", "email": "buhalterija@pirkejas.lt" }, "products": [ { "name": "Konsultacija", "units": "val.", "quantity": 2, "price": 50, "vat_percentage": 21 } ], "payment_options": [ { "type": "bank", "bank_name": "Swedbank", "bank_account": "LT12 7300 0100 0000 0001", "swift_bic_code": "HABALT22" } ] } JSON ``` ```js tab="JavaScript" tab-group="request" const response = await fetch('https://app.fsaskaita.lt/api/invoices', { method: 'POST', headers: { Authorization: `Bearer ${process.env.FSASKAITA_TOKEN}`, Accept: 'application/json', 'Content-Type': 'application/json', }, body: JSON.stringify({ type: 'vat_invoice', invoice_date: '2026-09-08', pay_until_date: '2026-09-22', series: 'SF', currency: 'EUR', language: 'lt', use_default_seller_info: true, buyer: { type: 'company', company_name: 'Pirkėjas, UAB', company_code: '300000001', vat_code: 'LT100000000011', address: 'Konstitucijos pr. 7, Vilnius', email: 'buhalterija@pirkejas.lt', }, products: [ { name: 'Konsultacija', units: 'val.', quantity: 2, price: 50, vat_percentage: 21 }, ], payment_options: [ { type: 'bank', bank_name: 'Swedbank', bank_account: 'LT12 7300 0100 0000 0001', swift_bic_code: 'HABALT22' }, ], }), }); console.log(response.status, await response.json()); ``` ```go tab="Go" tab-group="request" package main import ( "fmt" "io" "net/http" "os" "strings" ) const invoice = `{ "type": "vat_invoice", "invoice_date": "2026-09-08", "pay_until_date": "2026-09-22", "series": "SF", "currency": "EUR", "language": "lt", "use_default_seller_info": true, "buyer": { "type": "company", "company_name": "Pirkėjas, UAB", "company_code": "300000001", "vat_code": "LT100000000011", "address": "Konstitucijos pr. 7, Vilnius", "email": "buhalterija@pirkejas.lt" }, "products": [ { "name": "Konsultacija", "units": "val.", "quantity": 2, "price": 50, "vat_percentage": 21 } ], "payment_options": [ { "type": "bank", "bank_name": "Swedbank", "bank_account": "LT12 7300 0100 0000 0001", "swift_bic_code": "HABALT22" } ] }` func main() { req, _ := http.NewRequest("POST", "https://app.fsaskaita.lt/api/invoices", strings.NewReader(invoice)) req.Header.Set("Authorization", "Bearer "+os.Getenv("FSASKAITA_TOKEN")) req.Header.Set("Accept", "application/json") req.Header.Set("Content-Type", "application/json") res, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(res.Status, string(body)) } ``` ```python tab="Python" tab-group="request" import os import requests response = requests.post( "https://app.fsaskaita.lt/api/invoices", headers={ "Authorization": f"Bearer {os.environ['FSASKAITA_TOKEN']}", "Accept": "application/json", }, json={ "type": "vat_invoice", "invoice_date": "2026-09-08", "pay_until_date": "2026-09-22", "series": "SF", "currency": "EUR", "language": "lt", "use_default_seller_info": True, "buyer": { "type": "company", "company_name": "Pirkėjas, UAB", "company_code": "300000001", "vat_code": "LT100000000011", "address": "Konstitucijos pr. 7, Vilnius", "email": "buhalterija@pirkejas.lt", }, "products": [ {"name": "Konsultacija", "units": "val.", "quantity": 2, "price": 50, "vat_percentage": 21}, ], "payment_options": [ {"type": "bank", "bank_name": "Swedbank", "bank_account": "LT12 7300 0100 0000 0001", "swift_bic_code": "HABALT22"}, ], }, ) print(response.status_code, response.json()) ``` ```java tab="Java" tab-group="request" import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; public class CreateInvoice { public static void main(String[] args) throws Exception { String invoice = """ { "type": "vat_invoice", "invoice_date": "2026-09-08", "pay_until_date": "2026-09-22", "series": "SF", "currency": "EUR", "language": "lt", "use_default_seller_info": true, "buyer": { "type": "company", "company_name": "Pirkėjas, UAB", "company_code": "300000001", "vat_code": "LT100000000011", "address": "Konstitucijos pr. 7, Vilnius", "email": "buhalterija@pirkejas.lt" }, "products": [ { "name": "Konsultacija", "units": "val.", "quantity": 2, "price": 50, "vat_percentage": 21 } ], "payment_options": [ { "type": "bank", "bank_name": "Swedbank", "bank_account": "LT12 7300 0100 0000 0001", "swift_bic_code": "HABALT22" } ] } """; HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.fsaskaita.lt/api/invoices")) .header("Authorization", "Bearer " + System.getenv("FSASKAITA_TOKEN")) .header("Accept", "application/json") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(invoice)) .build(); HttpResponse response = HttpClient.newHttpClient() .send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.statusCode() + " " + response.body()); } } ``` ```csharp tab="C#" tab-group="request" using System.Net.Http.Headers; using System.Text; var invoice = """ { "type": "vat_invoice", "invoice_date": "2026-09-08", "pay_until_date": "2026-09-22", "series": "SF", "currency": "EUR", "language": "lt", "use_default_seller_info": true, "buyer": { "type": "company", "company_name": "Pirkėjas, UAB", "company_code": "300000001", "vat_code": "LT100000000011", "address": "Konstitucijos pr. 7, Vilnius", "email": "buhalterija@pirkejas.lt" }, "products": [ { "name": "Konsultacija", "units": "val.", "quantity": 2, "price": 50, "vat_percentage": 21 } ], "payment_options": [ { "type": "bank", "bank_name": "Swedbank", "bank_account": "LT12 7300 0100 0000 0001", "swift_bic_code": "HABALT22" } ] } """; using var client = new HttpClient(); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue( "Bearer", Environment.GetEnvironmentVariable("FSASKAITA_TOKEN")); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); var response = await client.PostAsync( "https://app.fsaskaita.lt/api/invoices", new StringContent(invoice, Encoding.UTF8, "application/json")); Console.WriteLine($"{(int)response.StatusCode} {await response.Content.ReadAsStringAsync()}"); ``` Pagrindinės taisyklės: - `buyer.type` yra `company` arba `individual`. Įmonėms reikia `company_name`; fiziniams asmenims naudojami `first_name` ir `last_name`. Nesiųskite įmonės laukų fiziniam asmeniui ar asmens vardų įmonei. - Kiekvienai eilutei reikia `name`, `units`, `quantity` ir **lygiai vieno** iš `price` (vieneto kaina be PVM), `total` (eilutės suma be PVM) arba `total_incl_vat`. Kitus serveris apskaičiuoja pats. - `payment_options` įrašai yra arba `type: "bank"` su `bank_account` ir `bank_name` (bei neprivalomais `routing_or_sort_number`, `swift_bic_code`), arba `type: "other"` su `fields` sąrašu iš `{ "label", "value" }` porų. - `payment_status` kuriant pagal nutylėjimą yra `not_paid`, o atnaujinant nenurodytas paliekamas nepakeistas. Nustatykite `"paid"`, kad pažymėtumėte sąskaitą apmokėta. - `language` (`lt`, `en`, `es`, `de`, `fr`) nustato PDF kalbą. Pagal nutylėjimą `lt`. - `notes` – laisvas tekstas iki 255 simbolių, spausdinamas sąskaitoje. ### Savo pardavėjo bloko pateikimas Nustatykite `use_default_seller_info` į `false` (arba nenurodykite) ir siųskite `seller`. Privalomi pardavėjo laukai priklauso nuo to, kaip registruotas jūsų verslas: įmonės siunčia `company_name` ir `company_code`; individuali veikla siunčia `first_name`, `last_name` ir `individual_activity_id`. PVM tipams papildomai privalomas `seller.vat_code`. `seller.custom_fields` priima papildomas `{ "label", "value" }` poras, spausdinamas po pardavėjo duomenimis. ## Atsakymas ```json { "data": { "id": "6f1e9d2a-0b3c-4e5f-8a9b-1c2d3e4f5a6b", "business_id": "9c1f7b2e-3a6d-4d5e-9f0a-2b7c8d9e0f11", "invoice_type": "vat_invoice", "series": "SF", "invoice_number": "007", "invoice_date": "2026-09-08", "pay_until_date": "2026-09-22", "language": "lt", "subtotal": 100, "vat": 21, "total_incl_vat": 121, "currency": "EUR", "payment_status": "not_paid", "notes": null, "share_link": "https://app.fsaskaita.lt/invoice/share/…", "seller": { "business_type": "small_partnership", "company_name": "Pavyzdys, MB", "…": "…", "custom_fields": [] }, "buyer": { "type": "company", "company_name": "Pirkėjas, UAB", "…": "…" }, "items": [ { "id": "…", "name": "Konsultacija", "price": 50, "vat_percentage": 21, "quantity": 2, "units": "val." } ], "payment_options": [ { "type": "bank", "bank_account": "LT12 7300 0100 0000 0001", "bank_name": "Swedbank", "routing_or_sort_number": null, "swift_bic_code": "HABALT22", "fields": [] } ], "created_at": 1757318400, "updated_at": 1757318400 } } ``` `share_link` – viešas puslapis, kuriame pirkėjas gali peržiūrėti ir atsisiųsti sąskaitą neprisijungęs. `items[].price` yra vieneto kaina be PVM; eilučių sumos negrąžinamos. ## Atnaujinkite sąskaitą faktūrą `PUT /invoices/{id}` priima tokį patį turinį kaip kūrimas ir pakeičia visas sąskaitos dalis: eilutes, mokėjimo būdus ir pardavėjo bloką. Pirmiausia nuskaitykite sąskaitą, pakeiskite reikiamus laukus ir išsiųskite visą dokumentą atgal kartu su jo `invoice_number`. Pakeitus `series`, sąskaita perkeliama į kitą seriją ir iš naujo sinchronizuojami abiejų serijų skaitikliai. ## Atsisiųskite PDF ```bash tab="cURL" tab-group="request" curl -L https://app.fsaskaita.lt/api/invoices/$ID/download \ -H "Authorization: Bearer $FSASKAITA_TOKEN" \ -H "Accept: application/json" \ -o invoice.pdf ``` ```js tab="JavaScript" tab-group="request" import { createWriteStream } from 'node:fs'; import { Readable } from 'node:stream'; import { pipeline } from 'node:stream/promises'; const id = '6f1e9d2a-0b3c-4e5f-8a9b-1c2d3e4f5a6b'; const response = await fetch(`https://app.fsaskaita.lt/api/invoices/${id}/download`, { headers: { Authorization: `Bearer ${process.env.FSASKAITA_TOKEN}`, Accept: 'application/json', }, }); if (!response.ok) throw new Error(`${response.status} ${await response.text()}`); await pipeline(Readable.fromWeb(response.body), createWriteStream('invoice.pdf')); ``` ```go tab="Go" tab-group="request" package main import ( "io" "net/http" "os" ) func main() { id := "6f1e9d2a-0b3c-4e5f-8a9b-1c2d3e4f5a6b" req, _ := http.NewRequest("GET", "https://app.fsaskaita.lt/api/invoices/"+id+"/download", nil) req.Header.Set("Authorization", "Bearer "+os.Getenv("FSASKAITA_TOKEN")) req.Header.Set("Accept", "application/json") res, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer res.Body.Close() if res.StatusCode != http.StatusOK { body, _ := io.ReadAll(res.Body) panic(res.Status + " " + string(body)) } file, err := os.Create("invoice.pdf") if err != nil { panic(err) } defer file.Close() if _, err := io.Copy(file, res.Body); err != nil { panic(err) } } ``` ```python tab="Python" tab-group="request" import os import requests invoice_id = "6f1e9d2a-0b3c-4e5f-8a9b-1c2d3e4f5a6b" with requests.get( f"https://app.fsaskaita.lt/api/invoices/{invoice_id}/download", headers={ "Authorization": f"Bearer {os.environ['FSASKAITA_TOKEN']}", "Accept": "application/json", }, stream=True, ) as response: response.raise_for_status() with open("invoice.pdf", "wb") as file: for chunk in response.iter_content(chunk_size=65536): file.write(chunk) ``` ```java tab="Java" tab-group="request" import java.io.InputStream; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; public class DownloadInvoice { public static void main(String[] args) throws Exception { String id = "6f1e9d2a-0b3c-4e5f-8a9b-1c2d3e4f5a6b"; HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://app.fsaskaita.lt/api/invoices/" + id + "/download")) .header("Authorization", "Bearer " + System.getenv("FSASKAITA_TOKEN")) .header("Accept", "application/json") .GET() .build(); HttpResponse response = HttpClient.newHttpClient() .send(request, HttpResponse.BodyHandlers.ofInputStream()); try (InputStream body = response.body()) { if (response.statusCode() != 200) { throw new IllegalStateException(response.statusCode() + " " + new String(body.readAllBytes())); } Files.copy(body, Path.of("invoice.pdf"), StandardCopyOption.REPLACE_EXISTING); } } } ``` ```csharp tab="C#" tab-group="request" using System.Net.Http.Headers; var id = "6f1e9d2a-0b3c-4e5f-8a9b-1c2d3e4f5a6b"; using var client = new HttpClient(); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue( "Bearer", Environment.GetEnvironmentVariable("FSASKAITA_TOKEN")); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); using var response = await client.GetAsync( $"https://app.fsaskaita.lt/api/invoices/{id}/download", HttpCompletionOption.ResponseHeadersRead); response.EnsureSuccessStatusCode(); await using var file = File.Create("invoice.pdf"); await response.Content.CopyToAsync(file); ``` Atsakymas yra `application/pdf` su `Content-Disposition: attachment` failo pavadinimu, sudarytu iš tipo pavadinimo, serijos ir numerio. Jei PDF dar neparengtas, atsisiuntimas jo laukia iki maždaug 20 sekundžių. `Content-Length` antraštės nėra, todėl skaitykite turinį srautu, o ne iš anksto rezervuokite atmintį. ## Ko tikėtis: šalutiniai efektai - Kūrimas arba atnaujinimas išsiunčia `invoice.created` arba `invoice.updated` [webhook pranešimą](/lt/guides/webhooks). Šalinimas išsiunčia `invoice.deleted`. - Pirkėjas išsaugomas jūsų klientų sąraše programėlėje. - API prieigai reikalingas Premium planas. --- # Webhook pranešimai > Užprenumeruokite HTTPS galinį tašką sąskaitų faktūrų ir išlaidų įvykiams, tikrinkite HMAC-SHA256 parašą ir tvarkykite pakartotinius siuntimus. Webhook pranešimai siunčia JSON žinutę į jūsų HTTPS galinį tašką kaskart, kai jūsų versle pasikeičia sąskaita faktūra ar išlaidų dokumentas, nesvarbu, ar pokytis atėjo iš API, programėlės, periodinės sąskaitos ar apmokėjimo. Jie įtraukti į tą patį planą kaip ir API. ## Prenumerata Prenumeratų valdymo API nėra. Programėlėje atidarykite **Nustatymai**, **Integracijos**, **Webhooks**, pridėkite savo galinio taško URL ir pažymėkite norimus įvykius. Programėlė sugeneruoja prenumeratos **pasirašymo paslaptį** su priešdėliu `whsec_`. Atskleiskite ją ir išsaugokite kartu su savo galinio taško konfigūracija. Galinio taško taisyklės: - Privalo būti `https://`. - Iki 2048 simbolių. ## Įvykiai | Metodas | Kelias | Aprašymas | |---|---|---| | `EVENT` | [`invoice.created`](/lt/reference/invoices/webhookInvoiceCreated/) | invoice.created | | `EVENT` | [`invoice.updated`](/lt/reference/invoices/webhookInvoiceUpdated/) | invoice.updated | | `EVENT` | [`invoice.deleted`](/lt/reference/invoices/webhookInvoiceDeleted/) | invoice.deleted | | `EVENT` | [`expense.created`](/lt/reference/expenses/webhookExpenseCreated/) | expense.created | | `EVENT` | [`expense.updated`](/lt/reference/expenses/webhookExpenseUpdated/) | expense.updated | | `EVENT` | [`expense.deleted`](/lt/reference/expenses/webhookExpenseDeleted/) | expense.deleted | Ką kiekvienas įvykis perduoda ir kada jis siunčiamas: | Įvykis | `data` | Kada | |---|---|---| | `invoice.created` | visa sąskaita, tokios pačios formos kaip `GET /invoices/{id}` | sukuriama sąskaita, kuri nėra juodraštis | | `invoice.updated` | visa sąskaita | bet koks pokytis, įskaitant apmokėjimo būsenos pasikeitimus ir per programėlę gautus apmokėjimus | | `invoice.deleted` | `{ "id": "" }` | pašalinama sąskaita, kuri nėra juodraštis | | `expense.created` | visas išlaidų dokumentas, tokios pačios formos kaip `GET /expenses/{id}` | sukuriamas išlaidų dokumentas | | `expense.updated` | visas išlaidų dokumentas | pasikeitė skaičiai arba failas | | `expense.deleted` | `{ "id": "" }` | pašalinamas išlaidų dokumentas per API arba programėlėje | Sąskaitų juodraščiai įvykių niekada nesukelia. `invoice.created` išsiunčiamas iš karto, kai sąskaita išsaugoma, dar prieš sugeneruojant jos PDF; apdorojimo funkcijoje atlikta atsisiuntimo užklausa PDF palaukia. ## Pristatymas Kiekvienas pristatymas yra HTTP `POST` su: ``` Content-Type: application/json Signature: ``` Turinys: ```json { "event": "invoice.updated", "data": { "id": "6f1e9d2a-0b3c-4e5f-8a9b-1c2d3e4f5a6b", "invoice_type": "vat_invoice", "series": "SF", "invoice_number": "007", "payment_status": "paid", "…": "…" } } ``` Jūsų galinis taškas privalo atsakyti bet kokia `2xx` būsena per 10 sekundžių. Viskas kita, įskaitant laiko limito viršijimą, laikoma nesėkme. ## Pakartotiniai siuntimai Nepavykęs pristatymas kartojamas dar du kartus: po maždaug 10 sekundžių, tada po maždaug 100 sekundžių. Po trijų nesėkmių pranešimas nebesiunčiamas. Todėl pristatymai gali atkeliauti daugiau nei vieną kartą, o intensyviai keičiamo resurso atveju – ir ne iš eilės. Padarykite savo apdorojimo funkciją idempotentišką: dublikatams aptikti naudokite `data.id` kartu su `data.updated_at`, o kai svarbi eilės tvarka, gaukite dabartinę būseną per `GET /invoices/{id}`. Įvykio identifikatoriaus ar laiko žymos antraštės nėra, programėlėje nėra ir pristatymų žurnalo. ## Patikrinkite parašą Apskaičiuokite HMAC-SHA256 nuo **neapdoroto užklausos turinio** tiksliai tokio, koks gautas, naudodami prenumeratos paslaptį, ir palyginkite jį pastovaus laiko palyginimu su antrašte `Signature`. ```php tab="PHP" tab-group="signature" $secret = getenv('FSASKAITA_WEBHOOK_SECRET'); // whsec_… $payload = file_get_contents('php://input'); $expected = hash_hmac('sha256', $payload, $secret); $signature = $_SERVER['HTTP_SIGNATURE'] ?? ''; if (! hash_equals($expected, $signature)) { http_response_code(401); exit; } $event = json_decode($payload, true); // handle $event['event'] and $event['data'] http_response_code(200); ``` ```js tab="JavaScript" tab-group="signature" import { createHmac, timingSafeEqual } from 'node:crypto'; export function verify(rawBody, signatureHeader, secret) { const expected = createHmac('sha256', secret).update(rawBody).digest('hex'); const a = Buffer.from(expected); const b = Buffer.from(signatureHeader ?? ''); return a.length === b.length && timingSafeEqual(a, b); } ``` ```go tab="Go" tab-group="signature" package webhooks import ( "crypto/hmac" "crypto/sha256" "encoding/hex" ) func Verify(rawBody []byte, signatureHeader, secret string) bool { mac := hmac.New(sha256.New, []byte(secret)) mac.Write(rawBody) expected := hex.EncodeToString(mac.Sum(nil)) return hmac.Equal([]byte(expected), []byte(signatureHeader)) } ``` ```python tab="Python" tab-group="signature" import hashlib import hmac def verify(raw_body: bytes, signature_header: str | None, secret: str) -> bool: expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest() return hmac.compare_digest(expected.encode(), (signature_header or "").encode()) ``` ```java tab="Java" tab-group="signature" import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.util.HexFormat; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; public final class WebhookSignature { public static boolean verify(byte[] rawBody, String signatureHeader, String secret) throws Exception { Mac mac = Mac.getInstance("HmacSHA256"); mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256")); String expected = HexFormat.of().formatHex(mac.doFinal(rawBody)); return MessageDigest.isEqual( expected.getBytes(StandardCharsets.UTF_8), (signatureHeader == null ? "" : signatureHeader).getBytes(StandardCharsets.UTF_8)); } } ``` ```csharp tab="C#" tab-group="signature" using System.Security.Cryptography; using System.Text; public static class WebhookSignature { public static bool Verify(byte[] rawBody, string? signatureHeader, string secret) { var hash = HMACSHA256.HashData(Encoding.UTF8.GetBytes(secret), rawBody); var expected = Convert.ToHexString(hash).ToLowerInvariant(); return CryptographicOperations.FixedTimeEquals( Encoding.UTF8.GetBytes(expected), Encoding.UTF8.GetBytes(signatureHeader ?? "")); } } ``` Nuskaitykite turinį kaip neapdorotus baitus prieš bet kokį JSON parsinimą; iš naujo serializuojant išparsintą objektą gali pasikeisti tarpai ar raktų tvarka, ir palyginimas nepavyks. ## Atsakykite greitai Pirmiausia patvirtinkite gavimą `2xx` atsakymu, o apdorokite vėliau. Lėtos apdorojimo funkcijos viršija 10 sekundžių limitą, o tai sukelia pakartotinius siuntimus ir dvigubą darbą. ## Pakeiskite paslaptį Ištrinkite prenumeratą ir sukurkite naują; nauja prenumerata gauna naują paslaptį. Jei negalite sau leisti pertrūkio, atnaujinkite galinio taško konfigūraciją prieš ištrindami senąją prenumeratą. --- # Žinynas > Visos Public API operacijos, užklausos ir atsakymai vienoje vietoje. - [List currencies](/lt/reference/currencies/listCurrencies/): Returns every accepted currency code. Not paginated. - [Create an expense](/lt/reference/expenses/createExpense/): Creates an expense from a multipart/form-data body. file is required and must have one of the extensions jpeg, jpg, bmp, gif, pdf, png, tiff, xlsx, xls, doc, docx or odf. vat, invoice_number and the file are stored but not returned; fetch the file with the download endpoint. Fires the expense.created webhook. - [Delete an expense](/lt/reference/expenses/deleteExpense/): Deletes the expense and its file. Fires the expense.deleted webhook. - [Download the expense file](/lt/reference/expenses/downloadExpenseFile/): Streams the stored file under its original name. Content-Length is not sent. - [Get an expense](/lt/reference/expenses/getExpense/): - [List expenses](/lt/reference/expenses/listExpenses/): Returns the business's expenses, newest first, 50 per page. Use ?page= to paginate; the page size cannot be changed. - [Replace the expense file](/lt/reference/expenses/replaceExpenseFile/): Replaces only the stored file; every other field is kept. Fires the expense.updated webhook. - [Replace an expense](/lt/reference/expenses/updateExpense/): Replaces every field of the expense with the multipart/form-data body. file is optional here; when present it replaces the stored file. Fires the expense.updated webhook. - [expense.created](/lt/reference/expenses/webhookExpenseCreated/): Sent when an expense is created through the API or the app. Each event is attempted up to 3 times: the first delivery, then retries after 10 s and 100 s; only a 2xx response counts as success. The request times out after 10 seconds. - [expense.deleted](/lt/reference/expenses/webhookExpenseDeleted/): Sent when an expense is deleted through the API or the app. The payload contains only the id of the deleted expense. Each event is attempted up to 3 times: the first delivery, then retries after 10 s and 100 s; only a 2xx response counts as success. The request times out after 10 seconds. - [expense.updated](/lt/reference/expenses/webhookExpenseUpdated/): Sent when an expense is replaced or its file is swapped. Each event is attempted up to 3 times: the first delivery, then retries after 10 s and 100 s; only a 2xx response counts as success. The request times out after 10 seconds. - [Create an invoice](/lt/reference/invoices/createInvoice/): Creates a finalized invoice and queues its PDF. Fires the invoice.created webhook. - [Delete an invoice](/lt/reference/invoices/deleteInvoice/): Deletes the invoice together with its PDF, items, payment options and e-mail logs, and recalculates the series counter. Fires the invoice.deleted webhook. - [Download the invoice PDF](/lt/reference/invoices/downloadInvoicePdf/): Streams the invoice PDF. The PDF is rendered asynchronously after create and update; if it does not exist yet the request waits for it for up to 20 seconds and then fails with 500. Content-Length is not sent. - [Get an invoice](/lt/reference/invoices/getInvoice/): - [List invoices](/lt/reference/invoices/listInvoices/): Returns the business's finalized invoices, newest first, 50 per page. Use ?page= to paginate; the page size cannot be changed. Drafts made in the app are never included. - [Replace an invoice](/lt/reference/invoices/updateInvoice/): Replaces every field of the invoice with the request body, under the same rules as create. Always resend the current invoice_number: when it is omitted the invoice is renumbered from the series counter. Items, payment options and custom fields are rewritten, totals recalculated and the PDF regenerated. Fires the invoice.updated webhook. - [invoice.created](/lt/reference/invoices/webhookInvoiceCreated/): Sent when a finalized invoice is created, whether through the API, the app or a recurring invoice. The PDF is rendered asynchronously, so it may not exist yet when this event arrives; GET /invoices/{invoice}/download waits for it. Each event is attempted up to 3 times: the first delivery, then retries after 10 s and 100 s; only a 2xx response counts as success. The request times out after 10 seconds. - [invoice.deleted](/lt/reference/invoices/webhookInvoiceDeleted/): Sent when a finalized invoice is deleted. The payload contains only the id of the deleted invoice. Each event is attempted up to 3 times: the first delivery, then retries after 10 s and 100 s; only a 2xx response counts as success. The request times out after 10 seconds. - [invoice.updated](/lt/reference/invoices/webhookInvoiceUpdated/): Sent when an invoice is replaced, when its payment status changes (including a Stripe payment), or after any other save. Each event is attempted up to 3 times: the first delivery, then retries after 10 s and 100 s; only a 2xx response counts as success. The request times out after 10 seconds. - [Get the business profile](/lt/reference/profile/getProfile/): Returns the business the token is scoped to. Companies include company_name and company_code; individual activities include first_name, last_name and individual_activity_id. --- # List currencies > Returns every accepted currency code. Not paginated. ## GET /currencies Returns every accepted currency code. Not paginated. ### Request and responses ```json { "servers": [ { "url": "https://app.fsaskaita.lt/api", "description": "Production" } ], "security": [ { "bearerAuth": [] } ], "operation": { "operationId": "listCurrencies", "description": "Returns every accepted currency code. Not paginated.", "summary": "List currencies", "tags": [ "Currencies" ], "responses": { "200": { "description": "Array of `Currency`", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Currency" } } }, "required": [ "data" ] } } } }, "401": { "$ref": "#/components/responses/AuthenticationException" }, "429": { "description": "Rate limit exceeded. The limit is 60 requests per minute per business, shared across all of its tokens. Wait `Retry-After` seconds before retrying.", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string" } }, "required": [ "message" ] } } }, "headers": { "Retry-After": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } }, "X-RateLimit-Limit": { "description": "Requests allowed per minute.", "schema": { "type": "integer" } }, "X-RateLimit-Remaining": { "description": "Requests left in the current minute.", "schema": { "type": "integer" } }, "X-RateLimit-Reset": { "description": "Unix timestamp at which the window resets.", "schema": { "type": "integer" } } } } } }, "securitySchemes": { "bearerAuth": { "type": "http", "description": "Business token created in the app under Settings, Integrations, API. The token is scoped to exactly one business, has no expiry and is shown only once. Send it as `Authorization: Bearer ` together with `Accept: application/json`.", "scheme": "bearer" } } } ``` ### Referenced components ```json { "#/components/schemas/Currency": { "type": "object", "properties": { "code": { "type": "string", "description": "ISO 4217 code, e.g. `EUR`." }, "title": { "type": "string" } }, "required": [ "code", "title" ], "title": "Currency" }, "#/components/responses/AuthenticationException": { "description": "Unauthenticated", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string", "description": "Error overview." } }, "required": [ "message" ] } } } } } ``` --- # Create an expense > Creates an expense from a multipart/form-data body. file is required and must have one of the extensions jpeg, jpg, bmp, gif, pdf, png, tiff, xlsx, xls, doc, docx or odf. vat, invoice_number and the file are stored but not returned; fetch the file with the download endpoint. Fires the expense.created webhook. ## POST /expenses Creates an expense from a `multipart/form-data` body. `file` is required and must have one of the extensions jpeg, jpg, bmp, gif, pdf, png, tiff, xlsx, xls, doc, docx or odf. `vat`, `invoice_number` and the file are stored but not returned; fetch the file with the download endpoint. Fires the `expense.created` webhook. ### Request and responses ```json { "servers": [ { "url": "https://app.fsaskaita.lt/api", "description": "Production" } ], "security": [ { "bearerAuth": [] } ], "operation": { "operationId": "createExpense", "description": "Creates an expense from a `multipart/form-data` body. `file` is required and must have one of the\nextensions jpeg, jpg, bmp, gif, pdf, png, tiff, xlsx, xls, doc, docx or odf. `vat`, `invoice_number` and the\nfile are stored but not returned; fetch the file with the download endpoint. Fires the `expense.created`\nwebhook.", "summary": "Create an expense", "tags": [ "Expenses" ], "requestBody": { "required": true, "content": { "multipart/form-data": { "schema": { "$ref": "#/components/schemas/ExpenseCreateInput" } } } }, "responses": { "201": { "description": "`Expense`", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "$ref": "#/components/schemas/Expense" } }, "required": [ "data" ] } } } }, "401": { "$ref": "#/components/responses/AuthenticationException" }, "403": { "$ref": "#/components/responses/AuthorizationException" }, "422": { "$ref": "#/components/responses/ValidationException" }, "429": { "description": "Rate limit exceeded. The limit is 60 requests per minute per business, shared across all of its tokens. Wait `Retry-After` seconds before retrying.", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string" } }, "required": [ "message" ] } } }, "headers": { "Retry-After": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } }, "X-RateLimit-Limit": { "description": "Requests allowed per minute.", "schema": { "type": "integer" } }, "X-RateLimit-Remaining": { "description": "Requests left in the current minute.", "schema": { "type": "integer" } }, "X-RateLimit-Reset": { "description": "Unix timestamp at which the window resets.", "schema": { "type": "integer" } } } } } }, "securitySchemes": { "bearerAuth": { "type": "http", "description": "Business token created in the app under Settings, Integrations, API. The token is scoped to exactly one business, has no expiry and is shown only once. Send it as `Authorization: Bearer ` together with `Accept: application/json`.", "scheme": "bearer" } } } ``` ### Referenced components ```json { "#/components/schemas/ExpenseCreateInput": { "type": "object", "description": "Multipart body of `POST /expenses`: the same fields as `ExpenseInput`, but `file` is required.", "properties": { "currency": { "type": "string", "description": "One of the codes from `GET /currencies`.", "examples": [ "EUR" ] }, "total": { "type": "number", "description": "Amount including VAT.", "examples": [ 121 ] }, "vat": { "type": [ "number", "null" ], "description": "VAT amount contained in `total`. Stored but not returned.", "examples": [ 21 ] }, "seller": { "type": "string", "description": "Supplier name.", "examples": [ "Tiekėjas UAB" ], "maxLength": 255 }, "date": { "type": "string", "format": "date", "description": "Document date.", "examples": [ "2026-09-12" ] }, "invoice_number": { "type": [ "string", "null" ], "description": "Supplier's document number. Stored but not returned.", "examples": [ "TK-0042" ], "maxLength": 255 }, "file": { "type": "string", "format": "binary", "contentMediaType": "application/octet-stream", "description": "The document file: jpeg, jpg, bmp, gif, pdf, png, tiff, xlsx, xls, doc, docx or odf. Required when\ncreating an expense; optional on update, where it replaces the stored file." } }, "required": [ "currency", "total", "seller", "date", "file" ], "title": "ExpenseCreateInput" }, "#/components/schemas/Expense": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "date": { "type": [ "string", "null" ], "format": "date", "description": "Document date, `Y-m-d`." }, "total": { "type": "number", "description": "Amount including VAT." }, "currency": { "type": "string" }, "seller": { "type": "string" }, "created_at": { "type": "integer", "description": "Unix timestamp, seconds." }, "updated_at": { "type": "integer", "description": "Unix timestamp, seconds." } }, "required": [ "id", "date", "total", "currency", "seller", "created_at", "updated_at" ], "title": "Expense" }, "#/components/responses/AuthenticationException": { "description": "Unauthenticated", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string", "description": "Error overview." } }, "required": [ "message" ] } } } }, "#/components/responses/AuthorizationException": { "description": "Authorization error", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string", "description": "Error overview." } }, "required": [ "message" ] } } } }, "#/components/responses/ValidationException": { "description": "Validation error", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string", "description": "Errors overview." }, "errors": { "type": "object", "description": "A detailed description of each field that failed validation.", "additionalProperties": { "type": "array", "items": { "type": "string" } } } }, "required": [ "message", "errors" ] } } } } } ``` --- # Delete an expense > Deletes the expense and its file. Fires the expense.deleted webhook. ## DELETE /expenses/{expense} Deletes the expense and its file. Fires the `expense.deleted` webhook. ### Request and responses ```json { "servers": [ { "url": "https://app.fsaskaita.lt/api", "description": "Production" } ], "security": [ { "bearerAuth": [] } ], "operation": { "operationId": "deleteExpense", "description": "Deletes the expense and its file. Fires the `expense.deleted` webhook.", "summary": "Delete an expense", "tags": [ "Expenses" ], "parameters": [ { "name": "expense", "in": "path", "required": true, "description": "The expense ID.", "schema": { "type": "string" } } ], "responses": { "200": { "description": "Deleted. The body is empty." }, "401": { "$ref": "#/components/responses/AuthenticationException" }, "404": { "description": "The expense does not exist or belongs to another business.", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string" } }, "required": [ "message" ] } } } }, "429": { "description": "Rate limit exceeded. The limit is 60 requests per minute per business, shared across all of its tokens. Wait `Retry-After` seconds before retrying.", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string" } }, "required": [ "message" ] } } }, "headers": { "Retry-After": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } }, "X-RateLimit-Limit": { "description": "Requests allowed per minute.", "schema": { "type": "integer" } }, "X-RateLimit-Remaining": { "description": "Requests left in the current minute.", "schema": { "type": "integer" } }, "X-RateLimit-Reset": { "description": "Unix timestamp at which the window resets.", "schema": { "type": "integer" } } } } } }, "securitySchemes": { "bearerAuth": { "type": "http", "description": "Business token created in the app under Settings, Integrations, API. The token is scoped to exactly one business, has no expiry and is shown only once. Send it as `Authorization: Bearer ` together with `Accept: application/json`.", "scheme": "bearer" } } } ``` ### Referenced components ```json { "#/components/responses/AuthenticationException": { "description": "Unauthenticated", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string", "description": "Error overview." } }, "required": [ "message" ] } } } } } ``` --- # Download the expense file > Streams the stored file under its original name. Content-Length is not sent. ## GET /expenses/{expense}/download Streams the stored file under its original name. `Content-Length` is not sent. ### Request and responses ```json { "servers": [ { "url": "https://app.fsaskaita.lt/api", "description": "Production" } ], "security": [ { "bearerAuth": [] } ], "operation": { "operationId": "downloadExpenseFile", "description": "Streams the stored file under its original name. `Content-Length` is not sent.", "summary": "Download the expense file", "tags": [ "Expenses" ], "parameters": [ { "name": "expense", "in": "path", "required": true, "description": "The expense ID.", "schema": { "type": "string" } } ], "responses": { "200": { "description": "The stored file.", "content": { "application/octet-stream": { "schema": { "type": "string", "format": "binary" } }, "application/pdf": { "schema": { "type": "string", "format": "binary" } } }, "headers": { "Transfer-Encoding": { "required": true, "schema": { "type": "string", "enum": [ "chunked" ] } }, "Content-Disposition": { "description": "Attachment with the original file name.", "schema": { "type": "string" } } } }, "401": { "$ref": "#/components/responses/AuthenticationException" }, "404": { "description": "The expense does not exist or belongs to another business.", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string" } }, "required": [ "message" ] } } } }, "429": { "description": "Rate limit exceeded. The limit is 60 requests per minute per business, shared across all of its tokens. Wait `Retry-After` seconds before retrying.", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string" } }, "required": [ "message" ] } } }, "headers": { "Retry-After": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } }, "X-RateLimit-Limit": { "description": "Requests allowed per minute.", "schema": { "type": "integer" } }, "X-RateLimit-Remaining": { "description": "Requests left in the current minute.", "schema": { "type": "integer" } }, "X-RateLimit-Reset": { "description": "Unix timestamp at which the window resets.", "schema": { "type": "integer" } } } } } }, "securitySchemes": { "bearerAuth": { "type": "http", "description": "Business token created in the app under Settings, Integrations, API. The token is scoped to exactly one business, has no expiry and is shown only once. Send it as `Authorization: Bearer ` together with `Accept: application/json`.", "scheme": "bearer" } } } ``` ### Referenced components ```json { "#/components/responses/AuthenticationException": { "description": "Unauthenticated", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string", "description": "Error overview." } }, "required": [ "message" ] } } } } } ``` --- # Get an expense > ## GET /expenses/{expense} ### Request and responses ```json { "servers": [ { "url": "https://app.fsaskaita.lt/api", "description": "Production" } ], "security": [ { "bearerAuth": [] } ], "operation": { "operationId": "getExpense", "summary": "Get an expense", "tags": [ "Expenses" ], "parameters": [ { "name": "expense", "in": "path", "required": true, "description": "The expense ID.", "schema": { "type": "string" } } ], "responses": { "200": { "description": "`Expense`", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "$ref": "#/components/schemas/Expense" } }, "required": [ "data" ] } } } }, "401": { "$ref": "#/components/responses/AuthenticationException" }, "404": { "description": "The expense does not exist or belongs to another business.", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string" } }, "required": [ "message" ] } } } }, "429": { "description": "Rate limit exceeded. The limit is 60 requests per minute per business, shared across all of its tokens. Wait `Retry-After` seconds before retrying.", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string" } }, "required": [ "message" ] } } }, "headers": { "Retry-After": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } }, "X-RateLimit-Limit": { "description": "Requests allowed per minute.", "schema": { "type": "integer" } }, "X-RateLimit-Remaining": { "description": "Requests left in the current minute.", "schema": { "type": "integer" } }, "X-RateLimit-Reset": { "description": "Unix timestamp at which the window resets.", "schema": { "type": "integer" } } } } } }, "securitySchemes": { "bearerAuth": { "type": "http", "description": "Business token created in the app under Settings, Integrations, API. The token is scoped to exactly one business, has no expiry and is shown only once. Send it as `Authorization: Bearer ` together with `Accept: application/json`.", "scheme": "bearer" } } } ``` ### Referenced components ```json { "#/components/schemas/Expense": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "date": { "type": [ "string", "null" ], "format": "date", "description": "Document date, `Y-m-d`." }, "total": { "type": "number", "description": "Amount including VAT." }, "currency": { "type": "string" }, "seller": { "type": "string" }, "created_at": { "type": "integer", "description": "Unix timestamp, seconds." }, "updated_at": { "type": "integer", "description": "Unix timestamp, seconds." } }, "required": [ "id", "date", "total", "currency", "seller", "created_at", "updated_at" ], "title": "Expense" }, "#/components/responses/AuthenticationException": { "description": "Unauthenticated", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string", "description": "Error overview." } }, "required": [ "message" ] } } } } } ``` --- # List expenses > Returns the business's expenses, newest first, 50 per page. Use ?page= to paginate; the page size cannot be changed. ## GET /expenses Returns the business's expenses, newest first, 50 per page. Use `?page=` to paginate; the page size cannot be changed. ### Request and responses ```json { "servers": [ { "url": "https://app.fsaskaita.lt/api", "description": "Production" } ], "security": [ { "bearerAuth": [] } ], "operation": { "operationId": "listExpenses", "description": "Returns the business's expenses, newest first, 50 per page. Use `?page=` to paginate; the page size cannot\nbe changed.", "summary": "List expenses", "tags": [ "Expenses" ], "parameters": [ { "name": "page", "in": "query", "description": "Page number, starting at 1. The page size is fixed at 50.", "schema": { "type": "integer", "default": 1 } } ], "responses": { "200": { "description": "Paginated set of `Expense`", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Expense" } }, "meta": { "type": "object", "properties": { "current_page": { "type": "integer", "minimum": 1 }, "from": { "type": [ "integer", "null" ], "minimum": 1 }, "last_page": { "type": "integer", "minimum": 1 }, "path": { "type": [ "string", "null" ], "description": "Base path for paginator generated URLs." }, "per_page": { "type": "integer", "description": "Number of items shown per page.", "minimum": 0 }, "to": { "type": [ "integer", "null" ], "description": "Number of the last item in the slice.", "minimum": 1 }, "total": { "type": "integer", "description": "Total number of items being paginated.", "minimum": 0 } }, "required": [ "current_page", "from", "last_page", "path", "per_page", "to", "total" ] } }, "required": [ "data", "meta" ] } } } }, "401": { "$ref": "#/components/responses/AuthenticationException" }, "429": { "description": "Rate limit exceeded. The limit is 60 requests per minute per business, shared across all of its tokens. Wait `Retry-After` seconds before retrying.", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string" } }, "required": [ "message" ] } } }, "headers": { "Retry-After": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } }, "X-RateLimit-Limit": { "description": "Requests allowed per minute.", "schema": { "type": "integer" } }, "X-RateLimit-Remaining": { "description": "Requests left in the current minute.", "schema": { "type": "integer" } }, "X-RateLimit-Reset": { "description": "Unix timestamp at which the window resets.", "schema": { "type": "integer" } } } } } }, "securitySchemes": { "bearerAuth": { "type": "http", "description": "Business token created in the app under Settings, Integrations, API. The token is scoped to exactly one business, has no expiry and is shown only once. Send it as `Authorization: Bearer ` together with `Accept: application/json`.", "scheme": "bearer" } } } ``` ### Referenced components ```json { "#/components/schemas/Expense": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "date": { "type": [ "string", "null" ], "format": "date", "description": "Document date, `Y-m-d`." }, "total": { "type": "number", "description": "Amount including VAT." }, "currency": { "type": "string" }, "seller": { "type": "string" }, "created_at": { "type": "integer", "description": "Unix timestamp, seconds." }, "updated_at": { "type": "integer", "description": "Unix timestamp, seconds." } }, "required": [ "id", "date", "total", "currency", "seller", "created_at", "updated_at" ], "title": "Expense" }, "#/components/responses/AuthenticationException": { "description": "Unauthenticated", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string", "description": "Error overview." } }, "required": [ "message" ] } } } } } ``` --- # Replace the expense file > Replaces only the stored file; every other field is kept. Fires the expense.updated webhook. ## POST /expenses/{expense}/file Replaces only the stored file; every other field is kept. Fires the `expense.updated` webhook. ### Request and responses ```json { "servers": [ { "url": "https://app.fsaskaita.lt/api", "description": "Production" } ], "security": [ { "bearerAuth": [] } ], "operation": { "operationId": "replaceExpenseFile", "description": "Replaces only the stored file; every other field is kept. Fires the `expense.updated` webhook.", "summary": "Replace the expense file", "tags": [ "Expenses" ], "parameters": [ { "name": "expense", "in": "path", "required": true, "description": "The expense ID.", "schema": { "type": "string" } } ], "requestBody": { "required": true, "content": { "multipart/form-data": { "schema": { "$ref": "#/components/schemas/ExpenseFileInput" } } } }, "responses": { "200": { "description": "`Expense`", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "$ref": "#/components/schemas/Expense" } }, "required": [ "data" ] } } } }, "401": { "$ref": "#/components/responses/AuthenticationException" }, "403": { "$ref": "#/components/responses/AuthorizationException" }, "404": { "description": "The expense does not exist or belongs to another business.", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string" } }, "required": [ "message" ] } } } }, "422": { "$ref": "#/components/responses/ValidationException" }, "429": { "description": "Rate limit exceeded. The limit is 60 requests per minute per business, shared across all of its tokens. Wait `Retry-After` seconds before retrying.", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string" } }, "required": [ "message" ] } } }, "headers": { "Retry-After": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } }, "X-RateLimit-Limit": { "description": "Requests allowed per minute.", "schema": { "type": "integer" } }, "X-RateLimit-Remaining": { "description": "Requests left in the current minute.", "schema": { "type": "integer" } }, "X-RateLimit-Reset": { "description": "Unix timestamp at which the window resets.", "schema": { "type": "integer" } } } } } }, "securitySchemes": { "bearerAuth": { "type": "http", "description": "Business token created in the app under Settings, Integrations, API. The token is scoped to exactly one business, has no expiry and is shown only once. Send it as `Authorization: Bearer ` together with `Accept: application/json`.", "scheme": "bearer" } } } ``` ### Referenced components ```json { "#/components/schemas/ExpenseFileInput": { "type": "object", "description": "Multipart body of `POST /expenses/{expense}/file`.", "properties": { "file": { "type": "string", "format": "binary", "contentMediaType": "application/octet-stream", "description": "The new document file: jpeg, jpg, bmp, gif, pdf, png, tiff, xlsx, xls, doc, docx or odf." } }, "required": [ "file" ], "title": "ExpenseFileInput" }, "#/components/schemas/Expense": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "date": { "type": [ "string", "null" ], "format": "date", "description": "Document date, `Y-m-d`." }, "total": { "type": "number", "description": "Amount including VAT." }, "currency": { "type": "string" }, "seller": { "type": "string" }, "created_at": { "type": "integer", "description": "Unix timestamp, seconds." }, "updated_at": { "type": "integer", "description": "Unix timestamp, seconds." } }, "required": [ "id", "date", "total", "currency", "seller", "created_at", "updated_at" ], "title": "Expense" }, "#/components/responses/AuthenticationException": { "description": "Unauthenticated", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string", "description": "Error overview." } }, "required": [ "message" ] } } } }, "#/components/responses/AuthorizationException": { "description": "Authorization error", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string", "description": "Error overview." } }, "required": [ "message" ] } } } }, "#/components/responses/ValidationException": { "description": "Validation error", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string", "description": "Errors overview." }, "errors": { "type": "object", "description": "A detailed description of each field that failed validation.", "additionalProperties": { "type": "array", "items": { "type": "string" } } } }, "required": [ "message", "errors" ] } } } } } ``` --- # Replace an expense > Replaces every field of the expense with the multipart/form-data body. file is optional here; when present it replaces the stored file. Fires the expense.updated webhook. ## PUT /expenses/{expense} Replaces every field of the expense with the `multipart/form-data` body. `file` is optional here; when present it replaces the stored file. Fires the `expense.updated` webhook. ### Request and responses ```json { "servers": [ { "url": "https://app.fsaskaita.lt/api", "description": "Production" } ], "security": [ { "bearerAuth": [] } ], "operation": { "operationId": "updateExpense", "description": "Replaces every field of the expense with the `multipart/form-data` body. `file` is optional here; when\npresent it replaces the stored file. Fires the `expense.updated` webhook.", "summary": "Replace an expense", "tags": [ "Expenses" ], "parameters": [ { "name": "expense", "in": "path", "required": true, "description": "The expense ID.", "schema": { "type": "string" } } ], "requestBody": { "required": true, "content": { "multipart/form-data": { "schema": { "$ref": "#/components/schemas/ExpenseInput" } } } }, "responses": { "200": { "description": "`Expense`", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "$ref": "#/components/schemas/Expense" } }, "required": [ "data" ] } } } }, "401": { "$ref": "#/components/responses/AuthenticationException" }, "403": { "$ref": "#/components/responses/AuthorizationException" }, "404": { "description": "The expense does not exist or belongs to another business.", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string" } }, "required": [ "message" ] } } } }, "422": { "$ref": "#/components/responses/ValidationException" }, "429": { "description": "Rate limit exceeded. The limit is 60 requests per minute per business, shared across all of its tokens. Wait `Retry-After` seconds before retrying.", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string" } }, "required": [ "message" ] } } }, "headers": { "Retry-After": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } }, "X-RateLimit-Limit": { "description": "Requests allowed per minute.", "schema": { "type": "integer" } }, "X-RateLimit-Remaining": { "description": "Requests left in the current minute.", "schema": { "type": "integer" } }, "X-RateLimit-Reset": { "description": "Unix timestamp at which the window resets.", "schema": { "type": "integer" } } } } } }, "securitySchemes": { "bearerAuth": { "type": "http", "description": "Business token created in the app under Settings, Integrations, API. The token is scoped to exactly one business, has no expiry and is shown only once. Send it as `Authorization: Bearer ` together with `Accept: application/json`.", "scheme": "bearer" } } } ``` ### Referenced components ```json { "#/components/schemas/ExpenseInput": { "type": "object", "description": "Multipart body of `PUT /expenses/{expense}`. `POST /expenses` uses `ExpenseCreateInput` (StoreExpenseRequest),\nwhich additionally requires `file`.", "properties": { "currency": { "type": "string", "description": "One of the codes from `GET /currencies`.", "examples": [ "EUR" ] }, "total": { "type": "number", "description": "Amount including VAT.", "examples": [ 121 ] }, "vat": { "type": [ "number", "null" ], "description": "VAT amount contained in `total`. Stored but not returned.", "examples": [ 21 ] }, "seller": { "type": "string", "description": "Supplier name.", "examples": [ "Tiekėjas UAB" ], "maxLength": 255 }, "date": { "type": "string", "format": "date", "description": "Document date.", "examples": [ "2026-09-12" ] }, "invoice_number": { "type": [ "string", "null" ], "description": "Supplier's document number. Stored but not returned.", "examples": [ "TK-0042" ], "maxLength": 255 }, "file": { "type": "string", "format": "binary", "contentMediaType": "application/octet-stream", "description": "The document file: jpeg, jpg, bmp, gif, pdf, png, tiff, xlsx, xls, doc, docx or odf. Required when\ncreating an expense; optional on update, where it replaces the stored file." } }, "required": [ "currency", "total", "seller", "date" ], "title": "ExpenseInput" }, "#/components/schemas/Expense": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "date": { "type": [ "string", "null" ], "format": "date", "description": "Document date, `Y-m-d`." }, "total": { "type": "number", "description": "Amount including VAT." }, "currency": { "type": "string" }, "seller": { "type": "string" }, "created_at": { "type": "integer", "description": "Unix timestamp, seconds." }, "updated_at": { "type": "integer", "description": "Unix timestamp, seconds." } }, "required": [ "id", "date", "total", "currency", "seller", "created_at", "updated_at" ], "title": "Expense" }, "#/components/responses/AuthenticationException": { "description": "Unauthenticated", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string", "description": "Error overview." } }, "required": [ "message" ] } } } }, "#/components/responses/AuthorizationException": { "description": "Authorization error", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string", "description": "Error overview." } }, "required": [ "message" ] } } } }, "#/components/responses/ValidationException": { "description": "Validation error", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string", "description": "Errors overview." }, "errors": { "type": "object", "description": "A detailed description of each field that failed validation.", "additionalProperties": { "type": "array", "items": { "type": "string" } } } }, "required": [ "message", "errors" ] } } } } } ``` --- # expense.created > Sent when an expense is created through the API or the app. Each event is attempted up to 3 times: the first delivery, then retries after 10 s and 100 s; only a 2xx response counts as success. The request times out after 10 seconds. ## Webhook event: POST expense.created Sent when an expense is created through the API or the app. Each event is attempted up to 3 times: the first delivery, then retries after 10 s and 100 s; only a 2xx response counts as success. The request times out after 10 seconds. ### Request and responses ```json { "servers": [ { "url": "https://app.fsaskaita.lt/api", "description": "Production" } ], "operation": { "tags": [ "Expenses" ], "operationId": "webhookExpenseCreated", "summary": "expense.created", "description": "Sent when an expense is created through the API or the app. Each event is attempted up to 3 times: the first delivery, then retries after 10 s and 100 s; only a 2xx response counts as success. The request times out after 10 seconds.", "parameters": [ { "$ref": "#/components/parameters/webhookSignature" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "event", "data" ], "properties": { "event": { "const": "expense.created" }, "data": { "$ref": "#/components/schemas/Expense" } } } } } }, "responses": { "2XX": { "description": "Return any 2xx status to acknowledge the delivery. Any other status or a timeout schedules a retry." } } }, "securitySchemes": { "bearerAuth": { "type": "http", "description": "Business token created in the app under Settings, Integrations, API. The token is scoped to exactly one business, has no expiry and is shown only once. Send it as `Authorization: Bearer ` together with `Accept: application/json`.", "scheme": "bearer" } } } ``` ### Referenced components ```json { "#/components/parameters/webhookSignature": { "name": "Signature", "in": "header", "required": true, "description": "Lowercase hex HMAC-SHA256 of the raw request body, keyed with the webhook's signing secret (`whsec_…`). Recompute it over the exact bytes received and compare with a constant-time function before trusting the payload. No timestamp or event-id header is sent.", "schema": { "type": "string", "pattern": "^[0-9a-f]{64}$" }, "example": "5f1c0d8f9a7e4b2c6d3e1f0a9b8c7d6e5f4a3b2c1d0e9f8a7b6c5d4e3f2a1b0c" }, "#/components/schemas/Expense": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "date": { "type": [ "string", "null" ], "format": "date", "description": "Document date, `Y-m-d`." }, "total": { "type": "number", "description": "Amount including VAT." }, "currency": { "type": "string" }, "seller": { "type": "string" }, "created_at": { "type": "integer", "description": "Unix timestamp, seconds." }, "updated_at": { "type": "integer", "description": "Unix timestamp, seconds." } }, "required": [ "id", "date", "total", "currency", "seller", "created_at", "updated_at" ], "title": "Expense" } } ``` --- # expense.deleted > Sent when an expense is deleted through the API or the app. The payload contains only the id of the deleted expense. Each event is attempted up to 3 times: the first delivery, then retries after 10 s and 100 s; only a 2xx response counts as success. The request times out after 10 seconds. ## Webhook event: POST expense.deleted Sent when an expense is deleted through the API or the app. The payload contains only the id of the deleted expense. Each event is attempted up to 3 times: the first delivery, then retries after 10 s and 100 s; only a 2xx response counts as success. The request times out after 10 seconds. ### Request and responses ```json { "servers": [ { "url": "https://app.fsaskaita.lt/api", "description": "Production" } ], "operation": { "tags": [ "Expenses" ], "operationId": "webhookExpenseDeleted", "summary": "expense.deleted", "description": "Sent when an expense is deleted through the API or the app. The payload contains only the id of the deleted expense. Each event is attempted up to 3 times: the first delivery, then retries after 10 s and 100 s; only a 2xx response counts as success. The request times out after 10 seconds.", "parameters": [ { "$ref": "#/components/parameters/webhookSignature" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "event", "data" ], "properties": { "event": { "const": "expense.deleted" }, "data": { "$ref": "#/components/schemas/DeletedResource" } } } } } }, "responses": { "2XX": { "description": "Return any 2xx status to acknowledge the delivery. Any other status or a timeout schedules a retry." } } }, "securitySchemes": { "bearerAuth": { "type": "http", "description": "Business token created in the app under Settings, Integrations, API. The token is scoped to exactly one business, has no expiry and is shown only once. Send it as `Authorization: Bearer ` together with `Accept: application/json`.", "scheme": "bearer" } } } ``` ### Referenced components ```json { "#/components/parameters/webhookSignature": { "name": "Signature", "in": "header", "required": true, "description": "Lowercase hex HMAC-SHA256 of the raw request body, keyed with the webhook's signing secret (`whsec_…`). Recompute it over the exact bytes received and compare with a constant-time function before trusting the payload. No timestamp or event-id header is sent.", "schema": { "type": "string", "pattern": "^[0-9a-f]{64}$" }, "example": "5f1c0d8f9a7e4b2c6d3e1f0a9b8c7d6e5f4a3b2c1d0e9f8a7b6c5d4e3f2a1b0c" }, "#/components/schemas/DeletedResource": { "type": "object", "description": "Identifies a resource that no longer exists.", "required": [ "id" ], "properties": { "id": { "type": "string", "format": "uuid" } } } } ``` --- # expense.updated > Sent when an expense is replaced or its file is swapped. Each event is attempted up to 3 times: the first delivery, then retries after 10 s and 100 s; only a 2xx response counts as success. The request times out after 10 seconds. ## Webhook event: POST expense.updated Sent when an expense is replaced or its file is swapped. Each event is attempted up to 3 times: the first delivery, then retries after 10 s and 100 s; only a 2xx response counts as success. The request times out after 10 seconds. ### Request and responses ```json { "servers": [ { "url": "https://app.fsaskaita.lt/api", "description": "Production" } ], "operation": { "tags": [ "Expenses" ], "operationId": "webhookExpenseUpdated", "summary": "expense.updated", "description": "Sent when an expense is replaced or its file is swapped. Each event is attempted up to 3 times: the first delivery, then retries after 10 s and 100 s; only a 2xx response counts as success. The request times out after 10 seconds.", "parameters": [ { "$ref": "#/components/parameters/webhookSignature" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "event", "data" ], "properties": { "event": { "const": "expense.updated" }, "data": { "$ref": "#/components/schemas/Expense" } } } } } }, "responses": { "2XX": { "description": "Return any 2xx status to acknowledge the delivery. Any other status or a timeout schedules a retry." } } }, "securitySchemes": { "bearerAuth": { "type": "http", "description": "Business token created in the app under Settings, Integrations, API. The token is scoped to exactly one business, has no expiry and is shown only once. Send it as `Authorization: Bearer ` together with `Accept: application/json`.", "scheme": "bearer" } } } ``` ### Referenced components ```json { "#/components/parameters/webhookSignature": { "name": "Signature", "in": "header", "required": true, "description": "Lowercase hex HMAC-SHA256 of the raw request body, keyed with the webhook's signing secret (`whsec_…`). Recompute it over the exact bytes received and compare with a constant-time function before trusting the payload. No timestamp or event-id header is sent.", "schema": { "type": "string", "pattern": "^[0-9a-f]{64}$" }, "example": "5f1c0d8f9a7e4b2c6d3e1f0a9b8c7d6e5f4a3b2c1d0e9f8a7b6c5d4e3f2a1b0c" }, "#/components/schemas/Expense": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "date": { "type": [ "string", "null" ], "format": "date", "description": "Document date, `Y-m-d`." }, "total": { "type": "number", "description": "Amount including VAT." }, "currency": { "type": "string" }, "seller": { "type": "string" }, "created_at": { "type": "integer", "description": "Unix timestamp, seconds." }, "updated_at": { "type": "integer", "description": "Unix timestamp, seconds." } }, "required": [ "id", "date", "total", "currency", "seller", "created_at", "updated_at" ], "title": "Expense" } } ``` --- # Create an invoice > Creates a finalized invoice and queues its PDF. Fires the invoice.created webhook. ## POST /invoices Creates a finalized invoice and queues its PDF. Fires the `invoice.created` webhook. **Numbering.** Omit `invoice_number` to take the next number of the `series`: the series counter, otherwise the highest existing number in that series plus one, otherwise `1`. An explicit number must be unique within the series. Numbers are returned zero-padded to three digits. **Amounts.** Each product line carries exactly one of `price` (unit price excluding VAT), `total` (line total excluding VAT) or `total_incl_vat`; the other two are derived. `vat_percentage` is required on the VAT invoice types (`vat_invoice`, `preliminary_vat_invoice`, `credit_vat_invoice`) and whenever the seller has a `vat_code`; leave it out on non-VAT types. **Seller.** Send `use_default_seller_info: true` to copy the seller block from the business profile (plus the custom fields of the latest invoice); `seller` is then prohibited. Otherwise send `seller` with the fields that match the business type: companies use `company_name` and `company_code`, individual activities use `first_name`, `last_name` and `individual_activity_id` (`company_code` and `individual_activity_id` are optional). VAT invoice types require `seller.vat_code` when `seller` is sent; with the default seller info the profile's VAT code is copied as it is. ### Request and responses ```json { "servers": [ { "url": "https://app.fsaskaita.lt/api", "description": "Production" } ], "security": [ { "bearerAuth": [] } ], "operation": { "operationId": "createInvoice", "description": "Creates a finalized invoice and queues its PDF. Fires the `invoice.created` webhook.\n\n**Numbering.** Omit `invoice_number` to take the next number of the `series`: the series counter, otherwise\nthe highest existing number in that series plus one, otherwise `1`. An explicit number must be unique\nwithin the series. Numbers are returned zero-padded to three digits.\n\n**Amounts.** Each product line carries exactly one of `price` (unit price excluding VAT), `total` (line total\nexcluding VAT) or `total_incl_vat`; the other two are derived. `vat_percentage` is required on the VAT\ninvoice types (`vat_invoice`, `preliminary_vat_invoice`, `credit_vat_invoice`) and whenever the seller has a\n`vat_code`; leave it out on non-VAT types.\n\n**Seller.** Send `use_default_seller_info: true` to copy the seller block from the business profile (plus\nthe custom fields of the latest invoice); `seller` is then prohibited. Otherwise send `seller` with the fields\nthat match the business type: companies use `company_name` and `company_code`, individual activities use\n`first_name`, `last_name` and `individual_activity_id` (`company_code` and `individual_activity_id` are\noptional). VAT invoice types require `seller.vat_code` when `seller` is sent; with the default seller info the\nprofile's VAT code is copied as it is.", "summary": "Create an invoice", "tags": [ "Invoices" ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/InvoiceInput" } } } }, "responses": { "201": { "description": "`Invoice`", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "$ref": "#/components/schemas/Invoice" } }, "required": [ "data" ] } } } }, "401": { "$ref": "#/components/responses/AuthenticationException" }, "403": { "$ref": "#/components/responses/AuthorizationException" }, "422": { "$ref": "#/components/responses/ValidationException" }, "429": { "description": "Rate limit exceeded. The limit is 60 requests per minute per business, shared across all of its tokens. Wait `Retry-After` seconds before retrying.", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string" } }, "required": [ "message" ] } } }, "headers": { "Retry-After": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } }, "X-RateLimit-Limit": { "description": "Requests allowed per minute.", "schema": { "type": "integer" } }, "X-RateLimit-Remaining": { "description": "Requests left in the current minute.", "schema": { "type": "integer" } }, "X-RateLimit-Reset": { "description": "Unix timestamp at which the window resets.", "schema": { "type": "integer" } } } } } }, "securitySchemes": { "bearerAuth": { "type": "http", "description": "Business token created in the app under Settings, Integrations, API. The token is scoped to exactly one business, has no expiry and is shown only once. Send it as `Authorization: Bearer ` together with `Accept: application/json`.", "scheme": "bearer" } } } ``` ### Referenced components ```json { "#/components/schemas/InvoiceInput": { "type": "object", "description": "Body of `POST /invoices` and `PUT /invoices/{invoice}`. On update every field is replaced with what you send;\nalways resend `invoice_number` or the invoice is renumbered.", "properties": { "type": { "type": "string", "description": "Invoice type. The `*vat_invoice` types require `seller.vat_code` and `vat_percentage` on every line.", "enum": [ "regular_invoice", "vat_invoice", "preliminary_invoice", "preliminary_vat_invoice", "credit_invoice", "credit_vat_invoice" ], "examples": [ "vat_invoice" ] }, "invoice_date": { "type": "string", "format": "date", "description": "Issue date.", "examples": [ "2026-09-12" ] }, "pay_until_date": { "type": [ "string", "null" ], "format": "date", "description": "Due date.", "examples": [ "2026-09-26" ] }, "series": { "type": "string", "description": "Series code the number belongs to. A new code starts its own counter.", "examples": [ "SF" ], "maxLength": 255 }, "notes": { "type": [ "string", "null" ], "description": "Free text printed under the lines.", "maxLength": 255 }, "currency": { "type": "string", "description": "One of the codes from `GET /currencies`.", "examples": [ "EUR" ] }, "payment_status": { "anyOf": [ { "description": "Defaults to `not_paid` on create; when omitted on update the current status is kept.", "$ref": "#/components/schemas/PaymentStatus" }, { "type": "null" } ] }, "language": { "type": [ "string", "null" ], "description": "Language of the PDF and the share page. Defaults to `lt`.", "enum": [ "en", "lt", "es", "de", "fr", null ] }, "invoice_number": { "type": [ "string", "null" ], "description": "Number within the series; must be unique there. Omit on create to auto-number. **On update always\nresend the current number**, otherwise the invoice is renumbered from the series counter. Accepts the\npadded (`\"007\"`) or unpadded (`\"7\"`) form; numbers are compared exactly as sent, so use one form\nconsistently within a series.", "pattern": "^(.*)+$", "examples": [ "7" ], "maxLength": 255 }, "buyer": { "type": "object", "properties": { "type": { "type": "string", "description": "`company` or `individual`. `person` is accepted as a legacy alias of `individual`; responses always\nreturn `individual`.", "enum": [ "company", "person", "individual" ], "examples": [ "company" ] }, "company_name": { "type": [ "string", "null" ], "description": "Required for companies, prohibited for individuals." }, "company_code": { "type": [ "string", "null" ], "description": "Prohibited for individuals.", "maxLength": 255 }, "first_name": { "type": [ "string", "null" ], "description": "Required for individuals, prohibited for companies.", "maxLength": 255 }, "last_name": { "type": [ "string", "null" ], "description": "Required for individuals, prohibited for companies.", "maxLength": 255 }, "individual_activity_id": { "type": [ "string", "null" ], "description": "Individual activity certificate number; prohibited for companies.", "maxLength": 255 }, "address": { "type": [ "string", "null" ], "maxLength": 255 }, "vat_code": { "type": [ "string", "null" ], "maxLength": 255 }, "email": { "type": [ "string", "null" ], "maxLength": 255 }, "phone": { "type": [ "string", "null" ], "maxLength": 255 } }, "required": [ "type" ] }, "use_default_seller_info": { "type": [ "boolean", "null" ], "description": "When `true` the seller block is copied from the business profile (plus the custom fields of the latest\ninvoice) and `seller` must be omitted.", "examples": [ true ] }, "seller": { "type": "object", "description": "Required unless `use_default_seller_info` is `true`. Which fields are required depends on the business\ntype: companies send `company_name` (required) and `company_code` (optional); individual activities send\n`first_name` and `last_name` (required) and `individual_activity_id` (optional). Fields of the other kind\nare rejected.", "properties": { "address": { "type": [ "string", "null" ], "maxLength": 255 }, "vat_code": { "type": [ "string", "null" ], "description": "Required for the `*vat_invoice` types when `seller` is sent.", "maxLength": 255 }, "email": { "type": [ "string", "null" ], "maxLength": 255 }, "phone": { "type": [ "string", "null" ], "maxLength": 255 }, "company_name": { "type": [ "string", "null" ], "description": "Companies only.", "maxLength": 255 }, "company_code": { "type": [ "string", "null" ], "description": "Companies only.", "maxLength": 255 }, "first_name": { "type": [ "string", "null" ], "description": "Individual activities only.", "maxLength": 255 }, "last_name": { "type": [ "string", "null" ], "description": "Individual activities only.", "maxLength": 255 }, "individual_activity_id": { "type": [ "string", "null" ], "description": "Individual activities only.", "maxLength": 255 }, "custom_fields": { "type": [ "array", "null" ], "description": "Extra label/value pairs printed in the seller block.", "items": { "type": "object", "properties": { "label": { "type": "string", "maxLength": 255 }, "value": { "type": "string", "maxLength": 255 } }, "required": [ "label", "value" ] } } } }, "products": { "type": "array", "description": "Invoice lines. Each line carries exactly one of `price`, `total` or `total_incl_vat`.", "items": { "type": "object", "properties": { "name": { "type": "string", "examples": [ "Consulting" ], "maxLength": 255 }, "units": { "type": "string", "examples": [ "h" ], "maxLength": 255 }, "quantity": { "type": "number", "examples": [ 2 ] }, "price": { "type": [ "number", "null" ], "description": "Unit price excluding VAT. Mutually exclusive with `total` and `total_incl_vat`.", "examples": [ 50 ] }, "total": { "type": [ "number", "null" ], "description": "Line total excluding VAT. Mutually exclusive with `price` and `total_incl_vat`." }, "total_incl_vat": { "type": [ "number", "null" ], "description": "Line total including VAT. Mutually exclusive with `price` and `total`." }, "vat_percentage": { "type": [ "number", "null" ], "description": "VAT rate, 0-100. Required whenever `seller.vat_code` is sent and, with `use_default_seller_info`, on the\n`*vat_invoice` types. On non-VAT types the value is ignored and stored as null.", "examples": [ 21 ], "minimum": 0, "maximum": 100 } }, "required": [ "name", "units", "quantity" ] }, "minItems": 1 }, "payment_options": { "type": [ "array", "null" ], "description": "Payment details printed on the invoice.", "items": { "type": "object", "properties": { "type": { "description": "`bank` takes the bank fields below; `other` takes free-form `fields`.", "$ref": "#/components/schemas/PaymentOptionType" }, "bank_account": { "type": "string", "description": "IBAN. Required for `bank`, prohibited otherwise.", "examples": [ "LT601010012345678901" ], "maxLength": 255 }, "bank_name": { "type": "string", "description": "Required for `bank`, prohibited otherwise.", "maxLength": 255 }, "routing_or_sort_number": { "type": [ "string", "null" ], "maxLength": 255 }, "swift_bic_code": { "type": [ "string", "null" ], "maxLength": 255 }, "fields": { "type": [ "array", "null" ], "description": "Required for `other`.", "items": { "type": "object", "properties": { "label": { "type": "string", "maxLength": 255 }, "value": { "type": "string", "maxLength": 255 } }, "required": [ "label", "value" ] } } }, "required": [ "type" ] } } }, "required": [ "type", "invoice_date", "series", "currency", "buyer", "seller", "products" ], "title": "InvoiceInput" }, "#/components/schemas/PaymentStatus": { "type": "string", "enum": [ "not_paid", "paid" ], "title": "PaymentStatus" }, "#/components/schemas/PaymentOptionType": { "type": "string", "description": "`bank` carries the bank account fields; `other` carries free-form label/value `fields`.\n", "enum": [ "bank", "other" ], "title": "PaymentOptionType" }, "#/components/schemas/Invoice": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "business_id": { "type": "string", "format": "uuid" }, "invoice_type": { "$ref": "#/components/schemas/InvoiceType" }, "series": { "type": "string" }, "invoice_number": { "type": "string", "description": "Zero-padded to three digits, e.g. `\"007\"`. Send it back padded or unpadded on update; both are accepted." }, "invoice_date": { "type": "string", "format": "date", "description": "Issue date, `Y-m-d`." }, "pay_until_date": { "type": [ "string", "null" ], "format": "date", "description": "Due date, `Y-m-d`." }, "language": { "$ref": "#/components/schemas/InvoiceLanguage" }, "subtotal": { "type": "number", "description": "Sum of the lines excluding VAT." }, "vat": { "type": "number" }, "total_incl_vat": { "type": "number" }, "currency": { "type": "string" }, "payment_status": { "$ref": "#/components/schemas/PaymentStatus" }, "notes": { "type": [ "string", "null" ] }, "share_link": { "type": "string", "format": "uri", "description": "Public link to the invoice; anyone with the link can view it." }, "seller": { "type": "object", "properties": { "business_type": { "$ref": "#/components/schemas/BusinessType" }, "first_name": { "type": [ "string", "null" ] }, "last_name": { "type": [ "string", "null" ] }, "company_name": { "type": [ "string", "null" ] }, "company_code": { "type": [ "string", "null" ] }, "individual_activity_id": { "type": [ "string", "null" ] }, "vat_code": { "type": [ "string", "null" ] }, "address": { "type": [ "string", "null" ] }, "email": { "type": [ "string", "null" ] }, "phone": { "type": [ "string", "null" ] }, "custom_fields": { "type": "array", "items": { "type": "object", "properties": { "label": { "type": "string" }, "value": { "type": "string" } }, "required": [ "label", "value" ] } } }, "required": [ "business_type", "first_name", "last_name", "company_name", "company_code", "individual_activity_id", "vat_code", "address", "email", "phone", "custom_fields" ] }, "buyer": { "type": "object", "properties": { "type": { "type": "string", "description": "`person` sent on input is returned as `individual`.", "enum": [ "company", "individual" ] }, "first_name": { "type": [ "string", "null" ] }, "last_name": { "type": [ "string", "null" ] }, "company_name": { "type": [ "string", "null" ] }, "company_code": { "type": [ "string", "null" ] }, "individual_activity_id": { "type": [ "string", "null" ] }, "vat_code": { "type": [ "string", "null" ] }, "address": { "type": [ "string", "null" ] }, "email": { "type": [ "string", "null" ] }, "phone": { "type": [ "string", "null" ] } }, "required": [ "type", "first_name", "last_name", "company_name", "company_code", "individual_activity_id", "vat_code", "address", "email", "phone" ] }, "items": { "type": "array", "items": { "$ref": "#/components/schemas/InvoiceItem" } }, "payment_options": { "type": "array", "items": { "$ref": "#/components/schemas/PaymentOption" } }, "created_at": { "type": "integer", "description": "Unix timestamp, seconds." }, "updated_at": { "type": "integer", "description": "Unix timestamp, seconds." } }, "required": [ "id", "business_id", "invoice_type", "series", "invoice_number", "invoice_date", "pay_until_date", "language", "subtotal", "vat", "total_incl_vat", "currency", "payment_status", "notes", "share_link", "seller", "buyer", "items", "payment_options", "created_at", "updated_at" ], "title": "Invoice" }, "#/components/schemas/InvoiceType": { "type": "string", "description": "The three `*vat_invoice` types require `vat_percentage` on every line and, when `seller` is sent, `seller.vat_code`.\n", "enum": [ "regular_invoice", "vat_invoice", "preliminary_invoice", "preliminary_vat_invoice", "credit_invoice", "credit_vat_invoice" ], "title": "InvoiceType" }, "#/components/schemas/InvoiceLanguage": { "type": "string", "description": "Language of the PDF and the public share page.\n", "enum": [ "en", "lt", "es", "de", "fr" ], "title": "InvoiceLanguage" }, "#/components/schemas/BusinessType": { "type": "string", "description": "Every type except `individual_activity` is a company.\n", "enum": [ "small_partnership", "individual_activity", "private_limited_liability_company", "sole_proprietorship", "public_institution", "association", "joint_stock_company" ], "title": "BusinessType" }, "#/components/schemas/InvoiceItem": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "name": { "type": "string" }, "price": { "type": "number" }, "vat_percentage": { "type": [ "number", "null" ] }, "quantity": { "type": "number" }, "units": { "type": "string" } }, "required": [ "id", "name", "price", "vat_percentage", "quantity", "units" ], "title": "InvoiceItem" }, "#/components/schemas/PaymentOption": { "type": "object", "properties": { "type": { "$ref": "#/components/schemas/PaymentOptionType" }, "bank_account": { "type": [ "string", "null" ] }, "bank_name": { "type": [ "string", "null" ] }, "routing_or_sort_number": { "type": [ "string", "null" ] }, "swift_bic_code": { "type": [ "string", "null" ] }, "fields": { "type": "array", "items": { "$ref": "#/components/schemas/LabelValue" } } }, "required": [ "type", "fields" ], "title": "PaymentOption" }, "#/components/schemas/LabelValue": { "type": "object", "properties": { "label": { "type": "string" }, "value": { "type": "string" } }, "required": [ "label", "value" ], "title": "LabelValue" }, "#/components/responses/AuthenticationException": { "description": "Unauthenticated", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string", "description": "Error overview." } }, "required": [ "message" ] } } } }, "#/components/responses/AuthorizationException": { "description": "Authorization error", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string", "description": "Error overview." } }, "required": [ "message" ] } } } }, "#/components/responses/ValidationException": { "description": "Validation error", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string", "description": "Errors overview." }, "errors": { "type": "object", "description": "A detailed description of each field that failed validation.", "additionalProperties": { "type": "array", "items": { "type": "string" } } } }, "required": [ "message", "errors" ] } } } } } ``` --- # Delete an invoice > Deletes the invoice together with its PDF, items, payment options and e-mail logs, and recalculates the series counter. Fires the invoice.deleted webhook. ## DELETE /invoices/{invoice} Deletes the invoice together with its PDF, items, payment options and e-mail logs, and recalculates the series counter. Fires the `invoice.deleted` webhook. ### Request and responses ```json { "servers": [ { "url": "https://app.fsaskaita.lt/api", "description": "Production" } ], "security": [ { "bearerAuth": [] } ], "operation": { "operationId": "deleteInvoice", "description": "Deletes the invoice together with its PDF, items, payment options and e-mail logs, and recalculates the\nseries counter. Fires the `invoice.deleted` webhook.", "summary": "Delete an invoice", "tags": [ "Invoices" ], "parameters": [ { "name": "invoice", "in": "path", "required": true, "description": "The invoice ID.", "schema": { "type": "string" } } ], "responses": { "200": { "description": "Deleted. The body is empty." }, "401": { "$ref": "#/components/responses/AuthenticationException" }, "404": { "description": "The invoice does not exist or belongs to another business.", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string" } }, "required": [ "message" ] } } } }, "429": { "description": "Rate limit exceeded. The limit is 60 requests per minute per business, shared across all of its tokens. Wait `Retry-After` seconds before retrying.", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string" } }, "required": [ "message" ] } } }, "headers": { "Retry-After": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } }, "X-RateLimit-Limit": { "description": "Requests allowed per minute.", "schema": { "type": "integer" } }, "X-RateLimit-Remaining": { "description": "Requests left in the current minute.", "schema": { "type": "integer" } }, "X-RateLimit-Reset": { "description": "Unix timestamp at which the window resets.", "schema": { "type": "integer" } } } } } }, "securitySchemes": { "bearerAuth": { "type": "http", "description": "Business token created in the app under Settings, Integrations, API. The token is scoped to exactly one business, has no expiry and is shown only once. Send it as `Authorization: Bearer ` together with `Accept: application/json`.", "scheme": "bearer" } } } ``` ### Referenced components ```json { "#/components/responses/AuthenticationException": { "description": "Unauthenticated", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string", "description": "Error overview." } }, "required": [ "message" ] } } } } } ``` --- # Download the invoice PDF > Streams the invoice PDF. The PDF is rendered asynchronously after create and update; if it does not exist yet the request waits for it for up to 20 seconds and then fails with 500. Content-Length is not sent. ## GET /invoices/{invoice}/download Streams the invoice PDF. The PDF is rendered asynchronously after create and update; if it does not exist yet the request waits for it for up to 20 seconds and then fails with `500`. `Content-Length` is not sent. ### Request and responses ```json { "servers": [ { "url": "https://app.fsaskaita.lt/api", "description": "Production" } ], "security": [ { "bearerAuth": [] } ], "operation": { "operationId": "downloadInvoicePdf", "description": "Streams the invoice PDF. The PDF is rendered asynchronously after create and update; if it does not exist\nyet the request waits for it for up to 20 seconds and then fails with `500`. `Content-Length` is not sent.", "summary": "Download the invoice PDF", "tags": [ "Invoices" ], "parameters": [ { "name": "invoice", "in": "path", "required": true, "description": "The invoice ID.", "schema": { "type": "string" } } ], "responses": { "200": { "description": "The invoice PDF.", "content": { "application/pdf": { "schema": { "type": "string", "format": "binary" } } }, "headers": { "Content-Disposition": { "description": "Attachment with the file name ` .pdf`, e.g. `Sąskaita faktūra SF007.pdf`.", "schema": { "type": "string" } } } }, "401": { "$ref": "#/components/responses/AuthenticationException" }, "404": { "description": "The invoice does not exist or belongs to another business.", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string" } }, "required": [ "message" ] } } } }, "429": { "description": "Rate limit exceeded. The limit is 60 requests per minute per business, shared across all of its tokens. Wait `Retry-After` seconds before retrying.", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string" } }, "required": [ "message" ] } } }, "headers": { "Retry-After": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } }, "X-RateLimit-Limit": { "description": "Requests allowed per minute.", "schema": { "type": "integer" } }, "X-RateLimit-Remaining": { "description": "Requests left in the current minute.", "schema": { "type": "integer" } }, "X-RateLimit-Reset": { "description": "Unix timestamp at which the window resets.", "schema": { "type": "integer" } } } }, "500": { "description": "The PDF was still not rendered after waiting 20 seconds.", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string" } }, "required": [ "message" ] } } } } } }, "securitySchemes": { "bearerAuth": { "type": "http", "description": "Business token created in the app under Settings, Integrations, API. The token is scoped to exactly one business, has no expiry and is shown only once. Send it as `Authorization: Bearer ` together with `Accept: application/json`.", "scheme": "bearer" } } } ``` ### Referenced components ```json { "#/components/responses/AuthenticationException": { "description": "Unauthenticated", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string", "description": "Error overview." } }, "required": [ "message" ] } } } } } ``` --- # Get an invoice > ## GET /invoices/{invoice} ### Request and responses ```json { "servers": [ { "url": "https://app.fsaskaita.lt/api", "description": "Production" } ], "security": [ { "bearerAuth": [] } ], "operation": { "operationId": "getInvoice", "summary": "Get an invoice", "tags": [ "Invoices" ], "parameters": [ { "name": "invoice", "in": "path", "required": true, "description": "The invoice ID.", "schema": { "type": "string" } } ], "responses": { "200": { "description": "`Invoice`", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "$ref": "#/components/schemas/Invoice" } }, "required": [ "data" ] } } } }, "401": { "$ref": "#/components/responses/AuthenticationException" }, "404": { "description": "The invoice does not exist or belongs to another business.", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string" } }, "required": [ "message" ] } } } }, "429": { "description": "Rate limit exceeded. The limit is 60 requests per minute per business, shared across all of its tokens. Wait `Retry-After` seconds before retrying.", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string" } }, "required": [ "message" ] } } }, "headers": { "Retry-After": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } }, "X-RateLimit-Limit": { "description": "Requests allowed per minute.", "schema": { "type": "integer" } }, "X-RateLimit-Remaining": { "description": "Requests left in the current minute.", "schema": { "type": "integer" } }, "X-RateLimit-Reset": { "description": "Unix timestamp at which the window resets.", "schema": { "type": "integer" } } } } } }, "securitySchemes": { "bearerAuth": { "type": "http", "description": "Business token created in the app under Settings, Integrations, API. The token is scoped to exactly one business, has no expiry and is shown only once. Send it as `Authorization: Bearer ` together with `Accept: application/json`.", "scheme": "bearer" } } } ``` ### Referenced components ```json { "#/components/schemas/Invoice": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "business_id": { "type": "string", "format": "uuid" }, "invoice_type": { "$ref": "#/components/schemas/InvoiceType" }, "series": { "type": "string" }, "invoice_number": { "type": "string", "description": "Zero-padded to three digits, e.g. `\"007\"`. Send it back padded or unpadded on update; both are accepted." }, "invoice_date": { "type": "string", "format": "date", "description": "Issue date, `Y-m-d`." }, "pay_until_date": { "type": [ "string", "null" ], "format": "date", "description": "Due date, `Y-m-d`." }, "language": { "$ref": "#/components/schemas/InvoiceLanguage" }, "subtotal": { "type": "number", "description": "Sum of the lines excluding VAT." }, "vat": { "type": "number" }, "total_incl_vat": { "type": "number" }, "currency": { "type": "string" }, "payment_status": { "$ref": "#/components/schemas/PaymentStatus" }, "notes": { "type": [ "string", "null" ] }, "share_link": { "type": "string", "format": "uri", "description": "Public link to the invoice; anyone with the link can view it." }, "seller": { "type": "object", "properties": { "business_type": { "$ref": "#/components/schemas/BusinessType" }, "first_name": { "type": [ "string", "null" ] }, "last_name": { "type": [ "string", "null" ] }, "company_name": { "type": [ "string", "null" ] }, "company_code": { "type": [ "string", "null" ] }, "individual_activity_id": { "type": [ "string", "null" ] }, "vat_code": { "type": [ "string", "null" ] }, "address": { "type": [ "string", "null" ] }, "email": { "type": [ "string", "null" ] }, "phone": { "type": [ "string", "null" ] }, "custom_fields": { "type": "array", "items": { "type": "object", "properties": { "label": { "type": "string" }, "value": { "type": "string" } }, "required": [ "label", "value" ] } } }, "required": [ "business_type", "first_name", "last_name", "company_name", "company_code", "individual_activity_id", "vat_code", "address", "email", "phone", "custom_fields" ] }, "buyer": { "type": "object", "properties": { "type": { "type": "string", "description": "`person` sent on input is returned as `individual`.", "enum": [ "company", "individual" ] }, "first_name": { "type": [ "string", "null" ] }, "last_name": { "type": [ "string", "null" ] }, "company_name": { "type": [ "string", "null" ] }, "company_code": { "type": [ "string", "null" ] }, "individual_activity_id": { "type": [ "string", "null" ] }, "vat_code": { "type": [ "string", "null" ] }, "address": { "type": [ "string", "null" ] }, "email": { "type": [ "string", "null" ] }, "phone": { "type": [ "string", "null" ] } }, "required": [ "type", "first_name", "last_name", "company_name", "company_code", "individual_activity_id", "vat_code", "address", "email", "phone" ] }, "items": { "type": "array", "items": { "$ref": "#/components/schemas/InvoiceItem" } }, "payment_options": { "type": "array", "items": { "$ref": "#/components/schemas/PaymentOption" } }, "created_at": { "type": "integer", "description": "Unix timestamp, seconds." }, "updated_at": { "type": "integer", "description": "Unix timestamp, seconds." } }, "required": [ "id", "business_id", "invoice_type", "series", "invoice_number", "invoice_date", "pay_until_date", "language", "subtotal", "vat", "total_incl_vat", "currency", "payment_status", "notes", "share_link", "seller", "buyer", "items", "payment_options", "created_at", "updated_at" ], "title": "Invoice" }, "#/components/schemas/InvoiceType": { "type": "string", "description": "The three `*vat_invoice` types require `vat_percentage` on every line and, when `seller` is sent, `seller.vat_code`.\n", "enum": [ "regular_invoice", "vat_invoice", "preliminary_invoice", "preliminary_vat_invoice", "credit_invoice", "credit_vat_invoice" ], "title": "InvoiceType" }, "#/components/schemas/InvoiceLanguage": { "type": "string", "description": "Language of the PDF and the public share page.\n", "enum": [ "en", "lt", "es", "de", "fr" ], "title": "InvoiceLanguage" }, "#/components/schemas/PaymentStatus": { "type": "string", "enum": [ "not_paid", "paid" ], "title": "PaymentStatus" }, "#/components/schemas/BusinessType": { "type": "string", "description": "Every type except `individual_activity` is a company.\n", "enum": [ "small_partnership", "individual_activity", "private_limited_liability_company", "sole_proprietorship", "public_institution", "association", "joint_stock_company" ], "title": "BusinessType" }, "#/components/schemas/InvoiceItem": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "name": { "type": "string" }, "price": { "type": "number" }, "vat_percentage": { "type": [ "number", "null" ] }, "quantity": { "type": "number" }, "units": { "type": "string" } }, "required": [ "id", "name", "price", "vat_percentage", "quantity", "units" ], "title": "InvoiceItem" }, "#/components/schemas/PaymentOption": { "type": "object", "properties": { "type": { "$ref": "#/components/schemas/PaymentOptionType" }, "bank_account": { "type": [ "string", "null" ] }, "bank_name": { "type": [ "string", "null" ] }, "routing_or_sort_number": { "type": [ "string", "null" ] }, "swift_bic_code": { "type": [ "string", "null" ] }, "fields": { "type": "array", "items": { "$ref": "#/components/schemas/LabelValue" } } }, "required": [ "type", "fields" ], "title": "PaymentOption" }, "#/components/schemas/PaymentOptionType": { "type": "string", "description": "`bank` carries the bank account fields; `other` carries free-form label/value `fields`.\n", "enum": [ "bank", "other" ], "title": "PaymentOptionType" }, "#/components/schemas/LabelValue": { "type": "object", "properties": { "label": { "type": "string" }, "value": { "type": "string" } }, "required": [ "label", "value" ], "title": "LabelValue" }, "#/components/responses/AuthenticationException": { "description": "Unauthenticated", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string", "description": "Error overview." } }, "required": [ "message" ] } } } } } ``` --- # List invoices > Returns the business's finalized invoices, newest first, 50 per page. Use ?page= to paginate; the page size cannot be changed. Drafts made in the app are never included. ## GET /invoices Returns the business's finalized invoices, newest first, 50 per page. Use `?page=` to paginate; the page size cannot be changed. Drafts made in the app are never included. ### Request and responses ```json { "servers": [ { "url": "https://app.fsaskaita.lt/api", "description": "Production" } ], "security": [ { "bearerAuth": [] } ], "operation": { "operationId": "listInvoices", "description": "Returns the business's finalized invoices, newest first, 50 per page. Use `?page=` to paginate; the page\nsize cannot be changed. Drafts made in the app are never included.", "summary": "List invoices", "tags": [ "Invoices" ], "parameters": [ { "name": "page", "in": "query", "description": "Page number, starting at 1. The page size is fixed at 50.", "schema": { "type": "integer", "default": 1 } } ], "responses": { "200": { "description": "Paginated set of `Invoice`", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Invoice" } }, "meta": { "type": "object", "properties": { "current_page": { "type": "integer", "minimum": 1 }, "from": { "type": [ "integer", "null" ], "minimum": 1 }, "last_page": { "type": "integer", "minimum": 1 }, "path": { "type": [ "string", "null" ], "description": "Base path for paginator generated URLs." }, "per_page": { "type": "integer", "description": "Number of items shown per page.", "minimum": 0 }, "to": { "type": [ "integer", "null" ], "description": "Number of the last item in the slice.", "minimum": 1 }, "total": { "type": "integer", "description": "Total number of items being paginated.", "minimum": 0 } }, "required": [ "current_page", "from", "last_page", "path", "per_page", "to", "total" ] } }, "required": [ "data", "meta" ] } } } }, "401": { "$ref": "#/components/responses/AuthenticationException" }, "429": { "description": "Rate limit exceeded. The limit is 60 requests per minute per business, shared across all of its tokens. Wait `Retry-After` seconds before retrying.", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string" } }, "required": [ "message" ] } } }, "headers": { "Retry-After": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } }, "X-RateLimit-Limit": { "description": "Requests allowed per minute.", "schema": { "type": "integer" } }, "X-RateLimit-Remaining": { "description": "Requests left in the current minute.", "schema": { "type": "integer" } }, "X-RateLimit-Reset": { "description": "Unix timestamp at which the window resets.", "schema": { "type": "integer" } } } } } }, "securitySchemes": { "bearerAuth": { "type": "http", "description": "Business token created in the app under Settings, Integrations, API. The token is scoped to exactly one business, has no expiry and is shown only once. Send it as `Authorization: Bearer ` together with `Accept: application/json`.", "scheme": "bearer" } } } ``` ### Referenced components ```json { "#/components/schemas/Invoice": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "business_id": { "type": "string", "format": "uuid" }, "invoice_type": { "$ref": "#/components/schemas/InvoiceType" }, "series": { "type": "string" }, "invoice_number": { "type": "string", "description": "Zero-padded to three digits, e.g. `\"007\"`. Send it back padded or unpadded on update; both are accepted." }, "invoice_date": { "type": "string", "format": "date", "description": "Issue date, `Y-m-d`." }, "pay_until_date": { "type": [ "string", "null" ], "format": "date", "description": "Due date, `Y-m-d`." }, "language": { "$ref": "#/components/schemas/InvoiceLanguage" }, "subtotal": { "type": "number", "description": "Sum of the lines excluding VAT." }, "vat": { "type": "number" }, "total_incl_vat": { "type": "number" }, "currency": { "type": "string" }, "payment_status": { "$ref": "#/components/schemas/PaymentStatus" }, "notes": { "type": [ "string", "null" ] }, "share_link": { "type": "string", "format": "uri", "description": "Public link to the invoice; anyone with the link can view it." }, "seller": { "type": "object", "properties": { "business_type": { "$ref": "#/components/schemas/BusinessType" }, "first_name": { "type": [ "string", "null" ] }, "last_name": { "type": [ "string", "null" ] }, "company_name": { "type": [ "string", "null" ] }, "company_code": { "type": [ "string", "null" ] }, "individual_activity_id": { "type": [ "string", "null" ] }, "vat_code": { "type": [ "string", "null" ] }, "address": { "type": [ "string", "null" ] }, "email": { "type": [ "string", "null" ] }, "phone": { "type": [ "string", "null" ] }, "custom_fields": { "type": "array", "items": { "type": "object", "properties": { "label": { "type": "string" }, "value": { "type": "string" } }, "required": [ "label", "value" ] } } }, "required": [ "business_type", "first_name", "last_name", "company_name", "company_code", "individual_activity_id", "vat_code", "address", "email", "phone", "custom_fields" ] }, "buyer": { "type": "object", "properties": { "type": { "type": "string", "description": "`person` sent on input is returned as `individual`.", "enum": [ "company", "individual" ] }, "first_name": { "type": [ "string", "null" ] }, "last_name": { "type": [ "string", "null" ] }, "company_name": { "type": [ "string", "null" ] }, "company_code": { "type": [ "string", "null" ] }, "individual_activity_id": { "type": [ "string", "null" ] }, "vat_code": { "type": [ "string", "null" ] }, "address": { "type": [ "string", "null" ] }, "email": { "type": [ "string", "null" ] }, "phone": { "type": [ "string", "null" ] } }, "required": [ "type", "first_name", "last_name", "company_name", "company_code", "individual_activity_id", "vat_code", "address", "email", "phone" ] }, "items": { "type": "array", "items": { "$ref": "#/components/schemas/InvoiceItem" } }, "payment_options": { "type": "array", "items": { "$ref": "#/components/schemas/PaymentOption" } }, "created_at": { "type": "integer", "description": "Unix timestamp, seconds." }, "updated_at": { "type": "integer", "description": "Unix timestamp, seconds." } }, "required": [ "id", "business_id", "invoice_type", "series", "invoice_number", "invoice_date", "pay_until_date", "language", "subtotal", "vat", "total_incl_vat", "currency", "payment_status", "notes", "share_link", "seller", "buyer", "items", "payment_options", "created_at", "updated_at" ], "title": "Invoice" }, "#/components/schemas/InvoiceType": { "type": "string", "description": "The three `*vat_invoice` types require `vat_percentage` on every line and, when `seller` is sent, `seller.vat_code`.\n", "enum": [ "regular_invoice", "vat_invoice", "preliminary_invoice", "preliminary_vat_invoice", "credit_invoice", "credit_vat_invoice" ], "title": "InvoiceType" }, "#/components/schemas/InvoiceLanguage": { "type": "string", "description": "Language of the PDF and the public share page.\n", "enum": [ "en", "lt", "es", "de", "fr" ], "title": "InvoiceLanguage" }, "#/components/schemas/PaymentStatus": { "type": "string", "enum": [ "not_paid", "paid" ], "title": "PaymentStatus" }, "#/components/schemas/BusinessType": { "type": "string", "description": "Every type except `individual_activity` is a company.\n", "enum": [ "small_partnership", "individual_activity", "private_limited_liability_company", "sole_proprietorship", "public_institution", "association", "joint_stock_company" ], "title": "BusinessType" }, "#/components/schemas/InvoiceItem": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "name": { "type": "string" }, "price": { "type": "number" }, "vat_percentage": { "type": [ "number", "null" ] }, "quantity": { "type": "number" }, "units": { "type": "string" } }, "required": [ "id", "name", "price", "vat_percentage", "quantity", "units" ], "title": "InvoiceItem" }, "#/components/schemas/PaymentOption": { "type": "object", "properties": { "type": { "$ref": "#/components/schemas/PaymentOptionType" }, "bank_account": { "type": [ "string", "null" ] }, "bank_name": { "type": [ "string", "null" ] }, "routing_or_sort_number": { "type": [ "string", "null" ] }, "swift_bic_code": { "type": [ "string", "null" ] }, "fields": { "type": "array", "items": { "$ref": "#/components/schemas/LabelValue" } } }, "required": [ "type", "fields" ], "title": "PaymentOption" }, "#/components/schemas/PaymentOptionType": { "type": "string", "description": "`bank` carries the bank account fields; `other` carries free-form label/value `fields`.\n", "enum": [ "bank", "other" ], "title": "PaymentOptionType" }, "#/components/schemas/LabelValue": { "type": "object", "properties": { "label": { "type": "string" }, "value": { "type": "string" } }, "required": [ "label", "value" ], "title": "LabelValue" }, "#/components/responses/AuthenticationException": { "description": "Unauthenticated", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string", "description": "Error overview." } }, "required": [ "message" ] } } } } } ``` --- # Replace an invoice > Replaces every field of the invoice with the request body, under the same rules as create. Always resend the current invoice_number: when it is omitted the invoice is renumbered from the series counter. Items, payment options and custom fields are rewritten, totals recalculated and the PDF regenerated. Fires the invoice.updated webhook. ## PUT /invoices/{invoice} Replaces every field of the invoice with the request body, under the same rules as create. **Always resend the current `invoice_number`**: when it is omitted the invoice is renumbered from the series counter. Items, payment options and custom fields are rewritten, totals recalculated and the PDF regenerated. Fires the `invoice.updated` webhook. ### Request and responses ```json { "servers": [ { "url": "https://app.fsaskaita.lt/api", "description": "Production" } ], "security": [ { "bearerAuth": [] } ], "operation": { "operationId": "updateInvoice", "description": "Replaces every field of the invoice with the request body, under the same rules as create. **Always resend\nthe current `invoice_number`**: when it is omitted the invoice is renumbered from the series counter. Items,\npayment options and custom fields are rewritten, totals recalculated and the PDF regenerated. Fires the\n`invoice.updated` webhook.", "summary": "Replace an invoice", "tags": [ "Invoices" ], "parameters": [ { "name": "invoice", "in": "path", "required": true, "description": "The invoice ID.", "schema": { "type": "string" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/InvoiceInput" } } } }, "responses": { "200": { "description": "`Invoice`", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "$ref": "#/components/schemas/Invoice" } }, "required": [ "data" ] } } } }, "401": { "$ref": "#/components/responses/AuthenticationException" }, "403": { "$ref": "#/components/responses/AuthorizationException" }, "404": { "description": "The invoice does not exist or belongs to another business.", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string" } }, "required": [ "message" ] } } } }, "422": { "$ref": "#/components/responses/ValidationException" }, "429": { "description": "Rate limit exceeded. The limit is 60 requests per minute per business, shared across all of its tokens. Wait `Retry-After` seconds before retrying.", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string" } }, "required": [ "message" ] } } }, "headers": { "Retry-After": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } }, "X-RateLimit-Limit": { "description": "Requests allowed per minute.", "schema": { "type": "integer" } }, "X-RateLimit-Remaining": { "description": "Requests left in the current minute.", "schema": { "type": "integer" } }, "X-RateLimit-Reset": { "description": "Unix timestamp at which the window resets.", "schema": { "type": "integer" } } } } } }, "securitySchemes": { "bearerAuth": { "type": "http", "description": "Business token created in the app under Settings, Integrations, API. The token is scoped to exactly one business, has no expiry and is shown only once. Send it as `Authorization: Bearer ` together with `Accept: application/json`.", "scheme": "bearer" } } } ``` ### Referenced components ```json { "#/components/schemas/InvoiceInput": { "type": "object", "description": "Body of `POST /invoices` and `PUT /invoices/{invoice}`. On update every field is replaced with what you send;\nalways resend `invoice_number` or the invoice is renumbered.", "properties": { "type": { "type": "string", "description": "Invoice type. The `*vat_invoice` types require `seller.vat_code` and `vat_percentage` on every line.", "enum": [ "regular_invoice", "vat_invoice", "preliminary_invoice", "preliminary_vat_invoice", "credit_invoice", "credit_vat_invoice" ], "examples": [ "vat_invoice" ] }, "invoice_date": { "type": "string", "format": "date", "description": "Issue date.", "examples": [ "2026-09-12" ] }, "pay_until_date": { "type": [ "string", "null" ], "format": "date", "description": "Due date.", "examples": [ "2026-09-26" ] }, "series": { "type": "string", "description": "Series code the number belongs to. A new code starts its own counter.", "examples": [ "SF" ], "maxLength": 255 }, "notes": { "type": [ "string", "null" ], "description": "Free text printed under the lines.", "maxLength": 255 }, "currency": { "type": "string", "description": "One of the codes from `GET /currencies`.", "examples": [ "EUR" ] }, "payment_status": { "anyOf": [ { "description": "Defaults to `not_paid` on create; when omitted on update the current status is kept.", "$ref": "#/components/schemas/PaymentStatus" }, { "type": "null" } ] }, "language": { "type": [ "string", "null" ], "description": "Language of the PDF and the share page. Defaults to `lt`.", "enum": [ "en", "lt", "es", "de", "fr", null ] }, "invoice_number": { "type": [ "string", "null" ], "description": "Number within the series; must be unique there. Omit on create to auto-number. **On update always\nresend the current number**, otherwise the invoice is renumbered from the series counter. Accepts the\npadded (`\"007\"`) or unpadded (`\"7\"`) form; numbers are compared exactly as sent, so use one form\nconsistently within a series.", "pattern": "^(.*)+$", "examples": [ "7" ], "maxLength": 255 }, "buyer": { "type": "object", "properties": { "type": { "type": "string", "description": "`company` or `individual`. `person` is accepted as a legacy alias of `individual`; responses always\nreturn `individual`.", "enum": [ "company", "person", "individual" ], "examples": [ "company" ] }, "company_name": { "type": [ "string", "null" ], "description": "Required for companies, prohibited for individuals." }, "company_code": { "type": [ "string", "null" ], "description": "Prohibited for individuals.", "maxLength": 255 }, "first_name": { "type": [ "string", "null" ], "description": "Required for individuals, prohibited for companies.", "maxLength": 255 }, "last_name": { "type": [ "string", "null" ], "description": "Required for individuals, prohibited for companies.", "maxLength": 255 }, "individual_activity_id": { "type": [ "string", "null" ], "description": "Individual activity certificate number; prohibited for companies.", "maxLength": 255 }, "address": { "type": [ "string", "null" ], "maxLength": 255 }, "vat_code": { "type": [ "string", "null" ], "maxLength": 255 }, "email": { "type": [ "string", "null" ], "maxLength": 255 }, "phone": { "type": [ "string", "null" ], "maxLength": 255 } }, "required": [ "type" ] }, "use_default_seller_info": { "type": [ "boolean", "null" ], "description": "When `true` the seller block is copied from the business profile (plus the custom fields of the latest\ninvoice) and `seller` must be omitted.", "examples": [ true ] }, "seller": { "type": "object", "description": "Required unless `use_default_seller_info` is `true`. Which fields are required depends on the business\ntype: companies send `company_name` (required) and `company_code` (optional); individual activities send\n`first_name` and `last_name` (required) and `individual_activity_id` (optional). Fields of the other kind\nare rejected.", "properties": { "address": { "type": [ "string", "null" ], "maxLength": 255 }, "vat_code": { "type": [ "string", "null" ], "description": "Required for the `*vat_invoice` types when `seller` is sent.", "maxLength": 255 }, "email": { "type": [ "string", "null" ], "maxLength": 255 }, "phone": { "type": [ "string", "null" ], "maxLength": 255 }, "company_name": { "type": [ "string", "null" ], "description": "Companies only.", "maxLength": 255 }, "company_code": { "type": [ "string", "null" ], "description": "Companies only.", "maxLength": 255 }, "first_name": { "type": [ "string", "null" ], "description": "Individual activities only.", "maxLength": 255 }, "last_name": { "type": [ "string", "null" ], "description": "Individual activities only.", "maxLength": 255 }, "individual_activity_id": { "type": [ "string", "null" ], "description": "Individual activities only.", "maxLength": 255 }, "custom_fields": { "type": [ "array", "null" ], "description": "Extra label/value pairs printed in the seller block.", "items": { "type": "object", "properties": { "label": { "type": "string", "maxLength": 255 }, "value": { "type": "string", "maxLength": 255 } }, "required": [ "label", "value" ] } } } }, "products": { "type": "array", "description": "Invoice lines. Each line carries exactly one of `price`, `total` or `total_incl_vat`.", "items": { "type": "object", "properties": { "name": { "type": "string", "examples": [ "Consulting" ], "maxLength": 255 }, "units": { "type": "string", "examples": [ "h" ], "maxLength": 255 }, "quantity": { "type": "number", "examples": [ 2 ] }, "price": { "type": [ "number", "null" ], "description": "Unit price excluding VAT. Mutually exclusive with `total` and `total_incl_vat`.", "examples": [ 50 ] }, "total": { "type": [ "number", "null" ], "description": "Line total excluding VAT. Mutually exclusive with `price` and `total_incl_vat`." }, "total_incl_vat": { "type": [ "number", "null" ], "description": "Line total including VAT. Mutually exclusive with `price` and `total`." }, "vat_percentage": { "type": [ "number", "null" ], "description": "VAT rate, 0-100. Required whenever `seller.vat_code` is sent and, with `use_default_seller_info`, on the\n`*vat_invoice` types. On non-VAT types the value is ignored and stored as null.", "examples": [ 21 ], "minimum": 0, "maximum": 100 } }, "required": [ "name", "units", "quantity" ] }, "minItems": 1 }, "payment_options": { "type": [ "array", "null" ], "description": "Payment details printed on the invoice.", "items": { "type": "object", "properties": { "type": { "description": "`bank` takes the bank fields below; `other` takes free-form `fields`.", "$ref": "#/components/schemas/PaymentOptionType" }, "bank_account": { "type": "string", "description": "IBAN. Required for `bank`, prohibited otherwise.", "examples": [ "LT601010012345678901" ], "maxLength": 255 }, "bank_name": { "type": "string", "description": "Required for `bank`, prohibited otherwise.", "maxLength": 255 }, "routing_or_sort_number": { "type": [ "string", "null" ], "maxLength": 255 }, "swift_bic_code": { "type": [ "string", "null" ], "maxLength": 255 }, "fields": { "type": [ "array", "null" ], "description": "Required for `other`.", "items": { "type": "object", "properties": { "label": { "type": "string", "maxLength": 255 }, "value": { "type": "string", "maxLength": 255 } }, "required": [ "label", "value" ] } } }, "required": [ "type" ] } } }, "required": [ "type", "invoice_date", "series", "currency", "buyer", "seller", "products" ], "title": "InvoiceInput" }, "#/components/schemas/PaymentStatus": { "type": "string", "enum": [ "not_paid", "paid" ], "title": "PaymentStatus" }, "#/components/schemas/PaymentOptionType": { "type": "string", "description": "`bank` carries the bank account fields; `other` carries free-form label/value `fields`.\n", "enum": [ "bank", "other" ], "title": "PaymentOptionType" }, "#/components/schemas/Invoice": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "business_id": { "type": "string", "format": "uuid" }, "invoice_type": { "$ref": "#/components/schemas/InvoiceType" }, "series": { "type": "string" }, "invoice_number": { "type": "string", "description": "Zero-padded to three digits, e.g. `\"007\"`. Send it back padded or unpadded on update; both are accepted." }, "invoice_date": { "type": "string", "format": "date", "description": "Issue date, `Y-m-d`." }, "pay_until_date": { "type": [ "string", "null" ], "format": "date", "description": "Due date, `Y-m-d`." }, "language": { "$ref": "#/components/schemas/InvoiceLanguage" }, "subtotal": { "type": "number", "description": "Sum of the lines excluding VAT." }, "vat": { "type": "number" }, "total_incl_vat": { "type": "number" }, "currency": { "type": "string" }, "payment_status": { "$ref": "#/components/schemas/PaymentStatus" }, "notes": { "type": [ "string", "null" ] }, "share_link": { "type": "string", "format": "uri", "description": "Public link to the invoice; anyone with the link can view it." }, "seller": { "type": "object", "properties": { "business_type": { "$ref": "#/components/schemas/BusinessType" }, "first_name": { "type": [ "string", "null" ] }, "last_name": { "type": [ "string", "null" ] }, "company_name": { "type": [ "string", "null" ] }, "company_code": { "type": [ "string", "null" ] }, "individual_activity_id": { "type": [ "string", "null" ] }, "vat_code": { "type": [ "string", "null" ] }, "address": { "type": [ "string", "null" ] }, "email": { "type": [ "string", "null" ] }, "phone": { "type": [ "string", "null" ] }, "custom_fields": { "type": "array", "items": { "type": "object", "properties": { "label": { "type": "string" }, "value": { "type": "string" } }, "required": [ "label", "value" ] } } }, "required": [ "business_type", "first_name", "last_name", "company_name", "company_code", "individual_activity_id", "vat_code", "address", "email", "phone", "custom_fields" ] }, "buyer": { "type": "object", "properties": { "type": { "type": "string", "description": "`person` sent on input is returned as `individual`.", "enum": [ "company", "individual" ] }, "first_name": { "type": [ "string", "null" ] }, "last_name": { "type": [ "string", "null" ] }, "company_name": { "type": [ "string", "null" ] }, "company_code": { "type": [ "string", "null" ] }, "individual_activity_id": { "type": [ "string", "null" ] }, "vat_code": { "type": [ "string", "null" ] }, "address": { "type": [ "string", "null" ] }, "email": { "type": [ "string", "null" ] }, "phone": { "type": [ "string", "null" ] } }, "required": [ "type", "first_name", "last_name", "company_name", "company_code", "individual_activity_id", "vat_code", "address", "email", "phone" ] }, "items": { "type": "array", "items": { "$ref": "#/components/schemas/InvoiceItem" } }, "payment_options": { "type": "array", "items": { "$ref": "#/components/schemas/PaymentOption" } }, "created_at": { "type": "integer", "description": "Unix timestamp, seconds." }, "updated_at": { "type": "integer", "description": "Unix timestamp, seconds." } }, "required": [ "id", "business_id", "invoice_type", "series", "invoice_number", "invoice_date", "pay_until_date", "language", "subtotal", "vat", "total_incl_vat", "currency", "payment_status", "notes", "share_link", "seller", "buyer", "items", "payment_options", "created_at", "updated_at" ], "title": "Invoice" }, "#/components/schemas/InvoiceType": { "type": "string", "description": "The three `*vat_invoice` types require `vat_percentage` on every line and, when `seller` is sent, `seller.vat_code`.\n", "enum": [ "regular_invoice", "vat_invoice", "preliminary_invoice", "preliminary_vat_invoice", "credit_invoice", "credit_vat_invoice" ], "title": "InvoiceType" }, "#/components/schemas/InvoiceLanguage": { "type": "string", "description": "Language of the PDF and the public share page.\n", "enum": [ "en", "lt", "es", "de", "fr" ], "title": "InvoiceLanguage" }, "#/components/schemas/BusinessType": { "type": "string", "description": "Every type except `individual_activity` is a company.\n", "enum": [ "small_partnership", "individual_activity", "private_limited_liability_company", "sole_proprietorship", "public_institution", "association", "joint_stock_company" ], "title": "BusinessType" }, "#/components/schemas/InvoiceItem": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "name": { "type": "string" }, "price": { "type": "number" }, "vat_percentage": { "type": [ "number", "null" ] }, "quantity": { "type": "number" }, "units": { "type": "string" } }, "required": [ "id", "name", "price", "vat_percentage", "quantity", "units" ], "title": "InvoiceItem" }, "#/components/schemas/PaymentOption": { "type": "object", "properties": { "type": { "$ref": "#/components/schemas/PaymentOptionType" }, "bank_account": { "type": [ "string", "null" ] }, "bank_name": { "type": [ "string", "null" ] }, "routing_or_sort_number": { "type": [ "string", "null" ] }, "swift_bic_code": { "type": [ "string", "null" ] }, "fields": { "type": "array", "items": { "$ref": "#/components/schemas/LabelValue" } } }, "required": [ "type", "fields" ], "title": "PaymentOption" }, "#/components/schemas/LabelValue": { "type": "object", "properties": { "label": { "type": "string" }, "value": { "type": "string" } }, "required": [ "label", "value" ], "title": "LabelValue" }, "#/components/responses/AuthenticationException": { "description": "Unauthenticated", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string", "description": "Error overview." } }, "required": [ "message" ] } } } }, "#/components/responses/AuthorizationException": { "description": "Authorization error", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string", "description": "Error overview." } }, "required": [ "message" ] } } } }, "#/components/responses/ValidationException": { "description": "Validation error", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string", "description": "Errors overview." }, "errors": { "type": "object", "description": "A detailed description of each field that failed validation.", "additionalProperties": { "type": "array", "items": { "type": "string" } } } }, "required": [ "message", "errors" ] } } } } } ``` --- # invoice.created > Sent when a finalized invoice is created, whether through the API, the app or a recurring invoice. The PDF is rendered asynchronously, so it may not exist yet when this event arrives; GET /invoices/{invoice}/download waits for it. Each event is attempted up to 3 times: the first delivery, then retries after 10 s and 100 s; only a 2xx response counts as success. The request times out after 10 seconds. ## Webhook event: POST invoice.created Sent when a finalized invoice is created, whether through the API, the app or a recurring invoice. The PDF is rendered asynchronously, so it may not exist yet when this event arrives; `GET /invoices/{invoice}/download` waits for it. Each event is attempted up to 3 times: the first delivery, then retries after 10 s and 100 s; only a 2xx response counts as success. The request times out after 10 seconds. ### Request and responses ```json { "servers": [ { "url": "https://app.fsaskaita.lt/api", "description": "Production" } ], "operation": { "tags": [ "Invoices" ], "operationId": "webhookInvoiceCreated", "summary": "invoice.created", "description": "Sent when a finalized invoice is created, whether through the API, the app or a recurring invoice. The PDF is rendered asynchronously, so it may not exist yet when this event arrives; `GET /invoices/{invoice}/download` waits for it. Each event is attempted up to 3 times: the first delivery, then retries after 10 s and 100 s; only a 2xx response counts as success. The request times out after 10 seconds.", "parameters": [ { "$ref": "#/components/parameters/webhookSignature" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "event", "data" ], "properties": { "event": { "const": "invoice.created" }, "data": { "$ref": "#/components/schemas/Invoice" } } } } } }, "responses": { "2XX": { "description": "Return any 2xx status to acknowledge the delivery. Any other status or a timeout schedules a retry." } } }, "securitySchemes": { "bearerAuth": { "type": "http", "description": "Business token created in the app under Settings, Integrations, API. The token is scoped to exactly one business, has no expiry and is shown only once. Send it as `Authorization: Bearer ` together with `Accept: application/json`.", "scheme": "bearer" } } } ``` ### Referenced components ```json { "#/components/parameters/webhookSignature": { "name": "Signature", "in": "header", "required": true, "description": "Lowercase hex HMAC-SHA256 of the raw request body, keyed with the webhook's signing secret (`whsec_…`). Recompute it over the exact bytes received and compare with a constant-time function before trusting the payload. No timestamp or event-id header is sent.", "schema": { "type": "string", "pattern": "^[0-9a-f]{64}$" }, "example": "5f1c0d8f9a7e4b2c6d3e1f0a9b8c7d6e5f4a3b2c1d0e9f8a7b6c5d4e3f2a1b0c" }, "#/components/schemas/Invoice": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "business_id": { "type": "string", "format": "uuid" }, "invoice_type": { "$ref": "#/components/schemas/InvoiceType" }, "series": { "type": "string" }, "invoice_number": { "type": "string", "description": "Zero-padded to three digits, e.g. `\"007\"`. Send it back padded or unpadded on update; both are accepted." }, "invoice_date": { "type": "string", "format": "date", "description": "Issue date, `Y-m-d`." }, "pay_until_date": { "type": [ "string", "null" ], "format": "date", "description": "Due date, `Y-m-d`." }, "language": { "$ref": "#/components/schemas/InvoiceLanguage" }, "subtotal": { "type": "number", "description": "Sum of the lines excluding VAT." }, "vat": { "type": "number" }, "total_incl_vat": { "type": "number" }, "currency": { "type": "string" }, "payment_status": { "$ref": "#/components/schemas/PaymentStatus" }, "notes": { "type": [ "string", "null" ] }, "share_link": { "type": "string", "format": "uri", "description": "Public link to the invoice; anyone with the link can view it." }, "seller": { "type": "object", "properties": { "business_type": { "$ref": "#/components/schemas/BusinessType" }, "first_name": { "type": [ "string", "null" ] }, "last_name": { "type": [ "string", "null" ] }, "company_name": { "type": [ "string", "null" ] }, "company_code": { "type": [ "string", "null" ] }, "individual_activity_id": { "type": [ "string", "null" ] }, "vat_code": { "type": [ "string", "null" ] }, "address": { "type": [ "string", "null" ] }, "email": { "type": [ "string", "null" ] }, "phone": { "type": [ "string", "null" ] }, "custom_fields": { "type": "array", "items": { "type": "object", "properties": { "label": { "type": "string" }, "value": { "type": "string" } }, "required": [ "label", "value" ] } } }, "required": [ "business_type", "first_name", "last_name", "company_name", "company_code", "individual_activity_id", "vat_code", "address", "email", "phone", "custom_fields" ] }, "buyer": { "type": "object", "properties": { "type": { "type": "string", "description": "`person` sent on input is returned as `individual`.", "enum": [ "company", "individual" ] }, "first_name": { "type": [ "string", "null" ] }, "last_name": { "type": [ "string", "null" ] }, "company_name": { "type": [ "string", "null" ] }, "company_code": { "type": [ "string", "null" ] }, "individual_activity_id": { "type": [ "string", "null" ] }, "vat_code": { "type": [ "string", "null" ] }, "address": { "type": [ "string", "null" ] }, "email": { "type": [ "string", "null" ] }, "phone": { "type": [ "string", "null" ] } }, "required": [ "type", "first_name", "last_name", "company_name", "company_code", "individual_activity_id", "vat_code", "address", "email", "phone" ] }, "items": { "type": "array", "items": { "$ref": "#/components/schemas/InvoiceItem" } }, "payment_options": { "type": "array", "items": { "$ref": "#/components/schemas/PaymentOption" } }, "created_at": { "type": "integer", "description": "Unix timestamp, seconds." }, "updated_at": { "type": "integer", "description": "Unix timestamp, seconds." } }, "required": [ "id", "business_id", "invoice_type", "series", "invoice_number", "invoice_date", "pay_until_date", "language", "subtotal", "vat", "total_incl_vat", "currency", "payment_status", "notes", "share_link", "seller", "buyer", "items", "payment_options", "created_at", "updated_at" ], "title": "Invoice" }, "#/components/schemas/InvoiceType": { "type": "string", "description": "The three `*vat_invoice` types require `vat_percentage` on every line and, when `seller` is sent, `seller.vat_code`.\n", "enum": [ "regular_invoice", "vat_invoice", "preliminary_invoice", "preliminary_vat_invoice", "credit_invoice", "credit_vat_invoice" ], "title": "InvoiceType" }, "#/components/schemas/InvoiceLanguage": { "type": "string", "description": "Language of the PDF and the public share page.\n", "enum": [ "en", "lt", "es", "de", "fr" ], "title": "InvoiceLanguage" }, "#/components/schemas/PaymentStatus": { "type": "string", "enum": [ "not_paid", "paid" ], "title": "PaymentStatus" }, "#/components/schemas/BusinessType": { "type": "string", "description": "Every type except `individual_activity` is a company.\n", "enum": [ "small_partnership", "individual_activity", "private_limited_liability_company", "sole_proprietorship", "public_institution", "association", "joint_stock_company" ], "title": "BusinessType" }, "#/components/schemas/InvoiceItem": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "name": { "type": "string" }, "price": { "type": "number" }, "vat_percentage": { "type": [ "number", "null" ] }, "quantity": { "type": "number" }, "units": { "type": "string" } }, "required": [ "id", "name", "price", "vat_percentage", "quantity", "units" ], "title": "InvoiceItem" }, "#/components/schemas/PaymentOption": { "type": "object", "properties": { "type": { "$ref": "#/components/schemas/PaymentOptionType" }, "bank_account": { "type": [ "string", "null" ] }, "bank_name": { "type": [ "string", "null" ] }, "routing_or_sort_number": { "type": [ "string", "null" ] }, "swift_bic_code": { "type": [ "string", "null" ] }, "fields": { "type": "array", "items": { "$ref": "#/components/schemas/LabelValue" } } }, "required": [ "type", "fields" ], "title": "PaymentOption" }, "#/components/schemas/PaymentOptionType": { "type": "string", "description": "`bank` carries the bank account fields; `other` carries free-form label/value `fields`.\n", "enum": [ "bank", "other" ], "title": "PaymentOptionType" }, "#/components/schemas/LabelValue": { "type": "object", "properties": { "label": { "type": "string" }, "value": { "type": "string" } }, "required": [ "label", "value" ], "title": "LabelValue" } } ``` --- # invoice.deleted > Sent when a finalized invoice is deleted. The payload contains only the id of the deleted invoice. Each event is attempted up to 3 times: the first delivery, then retries after 10 s and 100 s; only a 2xx response counts as success. The request times out after 10 seconds. ## Webhook event: POST invoice.deleted Sent when a finalized invoice is deleted. The payload contains only the id of the deleted invoice. Each event is attempted up to 3 times: the first delivery, then retries after 10 s and 100 s; only a 2xx response counts as success. The request times out after 10 seconds. ### Request and responses ```json { "servers": [ { "url": "https://app.fsaskaita.lt/api", "description": "Production" } ], "operation": { "tags": [ "Invoices" ], "operationId": "webhookInvoiceDeleted", "summary": "invoice.deleted", "description": "Sent when a finalized invoice is deleted. The payload contains only the id of the deleted invoice. Each event is attempted up to 3 times: the first delivery, then retries after 10 s and 100 s; only a 2xx response counts as success. The request times out after 10 seconds.", "parameters": [ { "$ref": "#/components/parameters/webhookSignature" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "event", "data" ], "properties": { "event": { "const": "invoice.deleted" }, "data": { "$ref": "#/components/schemas/DeletedResource" } } } } } }, "responses": { "2XX": { "description": "Return any 2xx status to acknowledge the delivery. Any other status or a timeout schedules a retry." } } }, "securitySchemes": { "bearerAuth": { "type": "http", "description": "Business token created in the app under Settings, Integrations, API. The token is scoped to exactly one business, has no expiry and is shown only once. Send it as `Authorization: Bearer ` together with `Accept: application/json`.", "scheme": "bearer" } } } ``` ### Referenced components ```json { "#/components/parameters/webhookSignature": { "name": "Signature", "in": "header", "required": true, "description": "Lowercase hex HMAC-SHA256 of the raw request body, keyed with the webhook's signing secret (`whsec_…`). Recompute it over the exact bytes received and compare with a constant-time function before trusting the payload. No timestamp or event-id header is sent.", "schema": { "type": "string", "pattern": "^[0-9a-f]{64}$" }, "example": "5f1c0d8f9a7e4b2c6d3e1f0a9b8c7d6e5f4a3b2c1d0e9f8a7b6c5d4e3f2a1b0c" }, "#/components/schemas/DeletedResource": { "type": "object", "description": "Identifies a resource that no longer exists.", "required": [ "id" ], "properties": { "id": { "type": "string", "format": "uuid" } } } } ``` --- # invoice.updated > Sent when an invoice is replaced, when its payment status changes (including a Stripe payment), or after any other save. Each event is attempted up to 3 times: the first delivery, then retries after 10 s and 100 s; only a 2xx response counts as success. The request times out after 10 seconds. ## Webhook event: POST invoice.updated Sent when an invoice is replaced, when its payment status changes (including a Stripe payment), or after any other save. Each event is attempted up to 3 times: the first delivery, then retries after 10 s and 100 s; only a 2xx response counts as success. The request times out after 10 seconds. ### Request and responses ```json { "servers": [ { "url": "https://app.fsaskaita.lt/api", "description": "Production" } ], "operation": { "tags": [ "Invoices" ], "operationId": "webhookInvoiceUpdated", "summary": "invoice.updated", "description": "Sent when an invoice is replaced, when its payment status changes (including a Stripe payment), or after any other save. Each event is attempted up to 3 times: the first delivery, then retries after 10 s and 100 s; only a 2xx response counts as success. The request times out after 10 seconds.", "parameters": [ { "$ref": "#/components/parameters/webhookSignature" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "event", "data" ], "properties": { "event": { "const": "invoice.updated" }, "data": { "$ref": "#/components/schemas/Invoice" } } } } } }, "responses": { "2XX": { "description": "Return any 2xx status to acknowledge the delivery. Any other status or a timeout schedules a retry." } } }, "securitySchemes": { "bearerAuth": { "type": "http", "description": "Business token created in the app under Settings, Integrations, API. The token is scoped to exactly one business, has no expiry and is shown only once. Send it as `Authorization: Bearer ` together with `Accept: application/json`.", "scheme": "bearer" } } } ``` ### Referenced components ```json { "#/components/parameters/webhookSignature": { "name": "Signature", "in": "header", "required": true, "description": "Lowercase hex HMAC-SHA256 of the raw request body, keyed with the webhook's signing secret (`whsec_…`). Recompute it over the exact bytes received and compare with a constant-time function before trusting the payload. No timestamp or event-id header is sent.", "schema": { "type": "string", "pattern": "^[0-9a-f]{64}$" }, "example": "5f1c0d8f9a7e4b2c6d3e1f0a9b8c7d6e5f4a3b2c1d0e9f8a7b6c5d4e3f2a1b0c" }, "#/components/schemas/Invoice": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "business_id": { "type": "string", "format": "uuid" }, "invoice_type": { "$ref": "#/components/schemas/InvoiceType" }, "series": { "type": "string" }, "invoice_number": { "type": "string", "description": "Zero-padded to three digits, e.g. `\"007\"`. Send it back padded or unpadded on update; both are accepted." }, "invoice_date": { "type": "string", "format": "date", "description": "Issue date, `Y-m-d`." }, "pay_until_date": { "type": [ "string", "null" ], "format": "date", "description": "Due date, `Y-m-d`." }, "language": { "$ref": "#/components/schemas/InvoiceLanguage" }, "subtotal": { "type": "number", "description": "Sum of the lines excluding VAT." }, "vat": { "type": "number" }, "total_incl_vat": { "type": "number" }, "currency": { "type": "string" }, "payment_status": { "$ref": "#/components/schemas/PaymentStatus" }, "notes": { "type": [ "string", "null" ] }, "share_link": { "type": "string", "format": "uri", "description": "Public link to the invoice; anyone with the link can view it." }, "seller": { "type": "object", "properties": { "business_type": { "$ref": "#/components/schemas/BusinessType" }, "first_name": { "type": [ "string", "null" ] }, "last_name": { "type": [ "string", "null" ] }, "company_name": { "type": [ "string", "null" ] }, "company_code": { "type": [ "string", "null" ] }, "individual_activity_id": { "type": [ "string", "null" ] }, "vat_code": { "type": [ "string", "null" ] }, "address": { "type": [ "string", "null" ] }, "email": { "type": [ "string", "null" ] }, "phone": { "type": [ "string", "null" ] }, "custom_fields": { "type": "array", "items": { "type": "object", "properties": { "label": { "type": "string" }, "value": { "type": "string" } }, "required": [ "label", "value" ] } } }, "required": [ "business_type", "first_name", "last_name", "company_name", "company_code", "individual_activity_id", "vat_code", "address", "email", "phone", "custom_fields" ] }, "buyer": { "type": "object", "properties": { "type": { "type": "string", "description": "`person` sent on input is returned as `individual`.", "enum": [ "company", "individual" ] }, "first_name": { "type": [ "string", "null" ] }, "last_name": { "type": [ "string", "null" ] }, "company_name": { "type": [ "string", "null" ] }, "company_code": { "type": [ "string", "null" ] }, "individual_activity_id": { "type": [ "string", "null" ] }, "vat_code": { "type": [ "string", "null" ] }, "address": { "type": [ "string", "null" ] }, "email": { "type": [ "string", "null" ] }, "phone": { "type": [ "string", "null" ] } }, "required": [ "type", "first_name", "last_name", "company_name", "company_code", "individual_activity_id", "vat_code", "address", "email", "phone" ] }, "items": { "type": "array", "items": { "$ref": "#/components/schemas/InvoiceItem" } }, "payment_options": { "type": "array", "items": { "$ref": "#/components/schemas/PaymentOption" } }, "created_at": { "type": "integer", "description": "Unix timestamp, seconds." }, "updated_at": { "type": "integer", "description": "Unix timestamp, seconds." } }, "required": [ "id", "business_id", "invoice_type", "series", "invoice_number", "invoice_date", "pay_until_date", "language", "subtotal", "vat", "total_incl_vat", "currency", "payment_status", "notes", "share_link", "seller", "buyer", "items", "payment_options", "created_at", "updated_at" ], "title": "Invoice" }, "#/components/schemas/InvoiceType": { "type": "string", "description": "The three `*vat_invoice` types require `vat_percentage` on every line and, when `seller` is sent, `seller.vat_code`.\n", "enum": [ "regular_invoice", "vat_invoice", "preliminary_invoice", "preliminary_vat_invoice", "credit_invoice", "credit_vat_invoice" ], "title": "InvoiceType" }, "#/components/schemas/InvoiceLanguage": { "type": "string", "description": "Language of the PDF and the public share page.\n", "enum": [ "en", "lt", "es", "de", "fr" ], "title": "InvoiceLanguage" }, "#/components/schemas/PaymentStatus": { "type": "string", "enum": [ "not_paid", "paid" ], "title": "PaymentStatus" }, "#/components/schemas/BusinessType": { "type": "string", "description": "Every type except `individual_activity` is a company.\n", "enum": [ "small_partnership", "individual_activity", "private_limited_liability_company", "sole_proprietorship", "public_institution", "association", "joint_stock_company" ], "title": "BusinessType" }, "#/components/schemas/InvoiceItem": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "name": { "type": "string" }, "price": { "type": "number" }, "vat_percentage": { "type": [ "number", "null" ] }, "quantity": { "type": "number" }, "units": { "type": "string" } }, "required": [ "id", "name", "price", "vat_percentage", "quantity", "units" ], "title": "InvoiceItem" }, "#/components/schemas/PaymentOption": { "type": "object", "properties": { "type": { "$ref": "#/components/schemas/PaymentOptionType" }, "bank_account": { "type": [ "string", "null" ] }, "bank_name": { "type": [ "string", "null" ] }, "routing_or_sort_number": { "type": [ "string", "null" ] }, "swift_bic_code": { "type": [ "string", "null" ] }, "fields": { "type": "array", "items": { "$ref": "#/components/schemas/LabelValue" } } }, "required": [ "type", "fields" ], "title": "PaymentOption" }, "#/components/schemas/PaymentOptionType": { "type": "string", "description": "`bank` carries the bank account fields; `other` carries free-form label/value `fields`.\n", "enum": [ "bank", "other" ], "title": "PaymentOptionType" }, "#/components/schemas/LabelValue": { "type": "object", "properties": { "label": { "type": "string" }, "value": { "type": "string" } }, "required": [ "label", "value" ], "title": "LabelValue" } } ``` --- # Get the business profile > Returns the business the token is scoped to. Companies include company_name and company_code; individual activities include first_name, last_name and individual_activity_id. ## GET /profile Returns the business the token is scoped to. Companies include `company_name` and `company_code`; individual activities include `first_name`, `last_name` and `individual_activity_id`. ### Request and responses ```json { "servers": [ { "url": "https://app.fsaskaita.lt/api", "description": "Production" } ], "security": [ { "bearerAuth": [] } ], "operation": { "operationId": "getProfile", "description": "Returns the business the token is scoped to. Companies include `company_name` and `company_code`;\nindividual activities include `first_name`, `last_name` and `individual_activity_id`.", "summary": "Get the business profile", "tags": [ "Profile" ], "responses": { "200": { "description": "`Profile`", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "$ref": "#/components/schemas/Profile" } }, "required": [ "data" ] } } } }, "401": { "$ref": "#/components/responses/AuthenticationException" }, "429": { "description": "Rate limit exceeded. The limit is 60 requests per minute per business, shared across all of its tokens. Wait `Retry-After` seconds before retrying.", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string" } }, "required": [ "message" ] } } }, "headers": { "Retry-After": { "description": "Seconds to wait before retrying.", "schema": { "type": "integer" } }, "X-RateLimit-Limit": { "description": "Requests allowed per minute.", "schema": { "type": "integer" } }, "X-RateLimit-Remaining": { "description": "Requests left in the current minute.", "schema": { "type": "integer" } }, "X-RateLimit-Reset": { "description": "Unix timestamp at which the window resets.", "schema": { "type": "integer" } } } } } }, "securitySchemes": { "bearerAuth": { "type": "http", "description": "Business token created in the app under Settings, Integrations, API. The token is scoped to exactly one business, has no expiry and is shown only once. Send it as `Authorization: Bearer ` together with `Accept: application/json`.", "scheme": "bearer" } } } ``` ### Referenced components ```json { "#/components/schemas/Profile": { "type": "object", "properties": { "business_id": { "type": "string", "format": "uuid" }, "business_title": { "type": "string" }, "business_type": { "$ref": "#/components/schemas/BusinessType" }, "address": { "type": [ "string", "null" ] }, "vat_code": { "type": [ "string", "null" ] }, "company_name": { "type": [ "string", "null" ], "description": "Present when the business is a company." }, "company_code": { "type": [ "string", "null" ], "description": "Present when the business is a company." }, "individual_activity_id": { "type": [ "string", "null" ], "description": "Present when `business_type` is `individual_activity`." }, "first_name": { "type": [ "string", "null" ], "description": "Present when `business_type` is `individual_activity`." }, "last_name": { "type": [ "string", "null" ], "description": "Present when `business_type` is `individual_activity`." } }, "required": [ "business_id", "business_title", "business_type", "address", "vat_code" ], "title": "Profile" }, "#/components/schemas/BusinessType": { "type": "string", "description": "Every type except `individual_activity` is a company.\n", "enum": [ "small_partnership", "individual_activity", "private_limited_liability_company", "sole_proprietorship", "public_institution", "association", "joint_stock_company" ], "title": "BusinessType" }, "#/components/responses/AuthenticationException": { "description": "Unauthenticated", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string", "description": "Error overview." } }, "required": [ "message" ] } } } } } ```