REST API for machine-to-machine integrations: fiscalisation platforms, POS, ERP, BI and scripts.
LlogariPro exposes a REST API through which external systems read and write a company's books without a user session. The company is determined by the API key, so URLs carry no company id.
All requests and responses are JSON (UTF-8). Dates are ISO 8601 (YYYY-MM-DD), amounts are returned as decimal strings (e.g. "1250.00") to preserve precision, and lists are paginated with page/per_page.
Base URL: https://books.konsulence.al/api/v1
Get a key under Integrations › API keys after signing in.
Every request carries the company key in the X-API-Key header or as Authorization: Bearer <key>. Keys are created by an admin or accountant under Integrations › API keys and are shown in full only once.
A key carries scopes. A read-only key cannot create anything; a fiscal-import key can only import invoices.
X-API-Key: lp_a1b2c3d4.dGhpc19pc19hX3NlY3JldF9rZXk… # or Authorization: Bearer lp_a1b2c3d4.dGhpc19pc19hX3NlY3JldF9rZXk…
| Scope | |
|---|---|
read | Reads everything: company, chart of accounts, partners, invoices, payments, journal, projects, dimensions, reports. |
write | Creates partners, invoices, payments and journal entries. Implies read and invoices:import. |
invoices:import | Only the fiscal invoice import at POST /import/invoices (fiscalisation platform keys). |
| Pagination | ?page=1&per_page=50 (max 200). Responses carry meta: {page, per_page, total, pages}. |
| Date filters | from / to for invoices, payments and journal; start / end for reports; as_of for balances. |
| Amounts | Decimal strings with two places ("1250.00"). Numbers are also accepted in requests. |
| Idempotency | external_id on invoices and journal entries prevents duplicates; partners are matched by NIPT or name. |
| Rate limit | Up to 120 requests per minute per key. 429 when exceeded. |
Errors return an HTTP status and a JSON body {"error": "message", "code": "code"}.
400 bad_request | Invalid JSON or wrong parameter |
401 unauthorized | Missing, invalid or revoked key |
403 insufficient_scope | The key lacks the required scope |
404 not_found | Resource does not exist in this company |
409 conflict | Conflict (e.g. company NIPT does not match the key) |
422 unprocessable | Invalid accounting data: unbalanced entry, missing account, mandatory dimension |
207 multi-status | Import partially succeeded; see results per invoice |
Verifies the key; returns the company, version and scopes.
{"ok": true, "version": "1.3", "company": "Demo Alfa shpk", "nipt": "L12345678A", "scopes": ["read", "write"]}
The key's company profile.
{"id": "…", "name": "Demo Alfa shpk", "nipt": "L12345678A", "currency": "ALL", "vat_registered": true}
List of accounts. with_balance=1 adds the balance (optionally as_of).
| Parameters | |
|---|---|
class | 1–9 |
active | 1 (default) | 0 |
with_balance | 1 to include balances |
as_of | YYYY-MM-DD |
{"data": [{"code": "411", "name": "Klientë", "class": "4", "normal_side": "debit", "balance": "125000.00"}], "meta": {"total": 96}}
Dated exchange rates (1 foreign = rate × ALL) as stored for the company: Bank of Albania feed (source boa), manual or revaluation.
| Parameters | |
|---|---|
currency | EUR, USD… |
from, to | YYYY-MM-DD |
{"home_currency": "ALL", "data": [{"currency": "EUR", "rate_date": "2026-09-04", "rate": "92.120000", "source": "boa"}], "meta": {…}}
VAT and other tax rates.
{"data": [{"id": "…", "code": "VAT20", "name": "TVSH 20%", "kind": "vat", "rate": "20.00"}]}
The three dimensions (cost centres, projects, business units) with their values and mode (off/optional/mandatory).
{"data": [{"kind": "cost_center", "name": "Qendra e kostos", "mode": "optional", "values": [{"id": "…", "code": "ADM", "name": "Administrata"}]}]}
Paginated list of partners.
| Parameters | |
|---|---|
type | customer | supplier |
q | search name/NIPT/email |
nipt | exact match |
page, per_page | pagination |
{"data": [{"id": "…", "name": "Klienti Sh.p.k.", "nipt": "L91234567B", "is_customer": true, "payment_terms_days": 30}], "meta": {"page": 1, "per_page": 50, "total": 1, "pages": 1}}
Partner card: details, receivable/payable figures (invoiced, paid, open, overdue) and 411/401 ledger balances.
{"id": "…", "name": "…", "receivable": {"invoiced": "90000.00", "paid": "60000.00", "open": "30000.00", "overdue": "0.00"}, "ledger_balances": {"411": "30000.00"}}
Creates a partner. Idempotent: if the NIPT or name exists, returns the existing partner (200) widening its role.
{"name": "Klienti Sh.p.k.", "nipt": "L91234567B", "is_customer": true, "is_supplier": false, "email": "info@klienti.al", "city": "Tiranë", "payment_terms_days": 30}
201 → {"id": "…", "name": "Klienti Sh.p.k.", "nipt": "L91234567B", …}
Paginated invoice list with filters.
| Parameters | |
|---|---|
direction | sale | purchase |
status | draft | issued | paid | cancelled |
state | open | overdue | partial | paid (derived from payments/due date) |
partner_id, number, external_id | exact filters |
from, to | issue date range |
{"data": [{"id": "…", "direction": "sale", "number": "45/2026", "issue_date": "2026-09-01", "due_date": "2026-10-01", "total": "60000.00", "amount_paid": "0.00", "balance_due": "60000.00", "status": "issued", "state": "open"}], "meta": {…}}
Invoice with lines, dimensions and payments.
{"id": "…", "number": "45/2026", "lines": [{"description": "…", "quantity": "1.000", "unit_price": "50000.0000", "vat_rate": "20.00", "account_code": "701", "line_total": "60000.00"}], "payments": []}
Creates and posts one invoice (status issued). The partner is matched by NIPT or created. Structure below.
(shiko strukturën e faturës / see invoice structure)
201 → fatura e plotë / the full invoice · 200 nëse external_id ekzistonte / if external_id already existed
Bulk import from fiscalisation platforms: {"source": "devsync", "company_nipt": "…", "invoices": [ … ]}. Each invoice is reported individually; 207 on partial errors.
{"source": "devsync", "company_nipt": "L12345678A", "invoices": [ {…}, {…} ]}
{"company": "…", "summary": {"created": 2, "skipped": 0, "error": 0}, "results": [{"external_id": "EIC-…", "number": "45/2026", "status": "created", "invoice_id": "…"}]}
Invoice receipts and payments.
| Parameters | |
|---|---|
partner_id | |
direction | sale (receipts) | purchase (payments) |
from, to | payment date range |
{"data": [{"id": "…", "invoice_id": "…", "invoice_number": "45/2026", "pay_date": "2026-09-15", "amount": "60000.00", "account_code": "512", "realized_fx": "0.00"}], "meta": {…}}
Records and books a (full or partial) payment against a posted invoice. account_code is the cash/bank account (class 5).
{"amount": 60000, "account_code": "512", "pay_date": "2026-09-15", "exchange_rate": null}
201 → {"id": "…", "amount": "60000.00", "journal_entry_id": "…"}
Expense accounts (class 6) plus the category mapping the company configured — to offer employees the right categories.
{"data": [{"code": "625", "name": "Udhëtime e dieta"}], "category_map": {"Udhëtime": {"account": "625"}}, "default_account": "601"}
Import approved expenses: {"expenses": [ … ]}. Reimbursables become a payable to the employee; company-paid ones settle from the account mapped for paid_with. Idempotent by external_id; the receipt (base64) is attached.
{"expenses": [{"external_id": "EXP-42", "date": "2026-09-05", "amount": 12000, "vat_amount": 2000, "category": "Udhëtime", "description": "Hotel 2 net", "employee": {"name": "Ardit Hoxha", "email": "ardit@firma.al"}, "merchant": {"name": "Hotel Tirana"}, "payment": "reimbursable", "receipt": {"filename": "hotel.pdf", "content_base64": "…"}}]}
{"company": "…", "summary": {"created": 1}, "results": [{"external_id": "expman:EXP-42", "number": "EXP-EXP-42", "status": "created", "invoice_id": "…"}], "receipts_attached": 1}
Journal entries; with_lines=1 includes the lines.
| Parameters | |
|---|---|
source | manual | invoice | bank | payroll | payment | revaluation | api |
from, to | |
with_lines | 1 |
{"data": [{"id": "…", "entry_no": "202609-0001", "entry_date": "2026-09-01", "memo": "Shitje - Klienti #45/2026", "source": "invoice", "total_debit": "60000.00"}], "meta": {…}}
The entry with its lines, partner and dimensions.
{"id": "…", "lines": [{"account_code": "411", "debit": "60000.00", "credit": "0.00", "partner_id": "…", "dimensions": [{"kind": "cost_center", "value": "Administrata"}]}]}
Posts a balanced manual entry. All rules apply: debit = credit, accounts must exist, mandatory dimensions on class 6/7.
{"entry_date": "2026-09-30", "memo": "Qira shtator", "external_id": "ERP-JE-1001", "lines": [{"account_code": "613", "debit": 50000, "description": "Qira", "dimension_ids": ["<cost-centre-value-id>"]}, {"account_code": "512", "credit": 50000}]}
201 → {"id": "…", "entry_no": "202609-0042", "posted": true, "lines": [ … ]}
Projects (grants/contracts); with_actuals=1 adds actuals.
| Parameters | |
|---|---|
status | planned | active | closed |
partner_id | |
with_actuals | 1 |
{"data": [{"id": "…", "code": "P-01", "name": "Granti UNDP 2026", "partner_name": "UNDP", "status": "active", "budget_expense": "1000000.00", "actuals": {"income": "500000.00", "expense": "300000.00", "expense_pct": "30.0"}}]}
Project with budget vs actual per account.
{"id": "…", "budget_vs_actual": [{"account_code": "601", "budget": "1000000.00", "actual": "300000.00", "variance": "700000.00", "pct": "30.0"}]}
Income statement for the period with SKK groupings; dimension_value_id filters to one cost centre, project or unit.
| Parameters | |
|---|---|
start, end | YYYY-MM-DD (default: current year) |
dimension_value_id |
{"period": {…}, "income": [ … ], "expense": [ … ], "total_income": "…", "total_expense": "…", "result_before_tax": "…", "profit_tax": "…", "result_after_tax": "…"}
Balance sheet as of a date.
| Parameters | |
|---|---|
as_of | YYYY-MM-DD (default: today) |
{"as_of": "2026-09-30", "assets": …, "liabilities": …, "equity": …}
Balances per partner on 411 (customers) or 401 (suppliers).
| Parameters | |
|---|---|
account | 411 (default) | 401 |
as_of |
{"account": "411", "data": [{"partner_id": "…", "partner": "Klienti Sh.p.k.", "nipt": "…", "debit": "…", "credit": "…", "balance": "30000.00"}]}
Verifies the office key (lpo_…). Company keys do not open these routes, and vice versa.
{"ok": true, "version": "1.4", "practice": "KONSULENCE.AL", "nipt": "L32327017S", "scopes": ["monitor", "offers"], "billing_company": {"id": "…", "name": "KONSULENCE.AL shpk", "nipt": "…", "currency": "ALL", "charges_vat": true}}
The companies the office keeps (archived too, with archived: true) and who has access to each.
{"data": [{"id": "…", "name": "Alfa shpk", "nipt": "L11111111A", "archived": false, "members": [{"user_id": "…", "role": "admin"}]}]}
The office team.
{"data": [{"id": "…", "email": "ana@zyra.al", "name": "Ana K.", "practice_role": "member"}]}
State of the books per active client: uncategorised bank lines, open/overdue documents, fiscalisation, period lock, tasks and last activity.
{"as_of": "2026-10-23", "data": [{"company_id": "…", "bank": {"pending_lines": 12, "oldest_pending_date": "2026-09-02"}, "books": {"last_entry_date": "2026-10-21", "lock_date": "2026-08-31"}, "invoices": {"overdue_sales": 3, "overdue_sales_amount": "48000.00"}, "fiscal": {"errors": 0, "certificate": "ok"}, "tasks": {"open": 2, "overdue": 0}}]}
Who worked where: one row per day × company × user, with active minutes and actions (manual / bulk). No user = API, cron, webhook.
| Parameters | |
|---|---|
from, to | YYYY-MM-DD (up to 93 days; default the last 30) |
{"from": "2026-10-01", "to": "2026-10-23", "users": [{"id": "…", "email": "ana@zyra.al", "name": "Ana K."}], "data": [{"date": "2026-10-20", "company_id": "…", "user_id": "…", "active_minutes": 95, "actions": 41, "manual_actions": 33, "bulk_actions": 8, "by_type": {"JournalEntry": 20}, "first_at": "…", "last_at": "…"}]}
Open Work tasks; with done_since also the ones completed since that date.
| Parameters | |
|---|---|
done_since | YYYY-MM-DD |
{"data": [{"id": "…", "title": "TVSH shtator", "company_id": "…", "status": "in_progress", "assigned_to": "…", "due_date": "2026-10-15"}]}
An offer for one of the office's clients (e.g. time worked, from the Client Portal), in the company that bills the clients (Office → Client Portal). The client becomes a partner by NIPT. Created not yet sent; the same external_id replaces it while it is unsent, then returns 409 offer_locked.
| Parameters | |
|---|---|
external_id, partner {nipt, name, email}, issue_date, valid_until, notes, lines [{description, quantity, unit_price, vat_rate}] | vat_rate defaults to 20; VAT only when the company charges it |
{"status": "created", "offer": {"id": "…", "external_id": "portal-offer-…", "number": "OF-2026-0007", "state": "draft", "subtotal": "6500.00", "vat_total": "1300.00", "total": "7800.00", "url": "https://books.konsulence.al/invoices/…", "invoice": null}}
The state of offers by external_id (sent, accepted, turned into an invoice with the invoice number).
| Parameters | |
|---|---|
external_id | comma-separated ids |
{"billing_company": {…}, "data": [{"external_id": "portal-offer-…", "number": "OF-2026-0007", "state": "converted", "invoice": {"number": "SH-2026-0042", "status": "draft"}}]}
{
"external_id": "EIC-2026-000123", // idempotency key (optional but recommended)
"direction": "sale", // sale | purchase
"number": "45/2026",
"issue_date": "2026-09-01",
"due_date": "2026-10-01",
"currency": "ALL", // ISO code; exchange_rate for foreign currency
"payment_method": "noncash", // cash | card | noncash
"tcr_code": "xh123abc45", // fiscal cash register (optional)
"nivf": "<UUID>", "nslf": "<32 hex>", // fiscal codes (optional): NIVF = FIC, NSLF = IIC
"qr": "…",
"partner": {"nipt": "L91234567B", "name": "Klienti Sh.p.k."},
"pdf_base64": "JVBERi0xLjQK…", "pdf_filename": "Fatura_45-2026.pdf", // optional: PDF attached to the invoice
"lines": [
{"description": "Shërbim konsulence", "quantity": 1, "unit_price": 50000,
"vat_rate": 20, "account_code": "701", "dimension_ids": ["<value-id>"]}
]
}
| Field | |
|---|---|
direction | sale or purchase — required |
partner | nipt and/or name; matched by NIPT, then name, otherwise created with the right role |
lines[] | description, quantity, unit_price (net of VAT), vat_rate (%), account_code (7xx sales, 6xx purchases; default 701/601), dimension_ids |
payment_method | cash/card book to the TCR cash account (TCR → cash mapping); noncash to 411/401 |
currency, exchange_rate | For foreign currency; without a rate the dated rate table is used |
external_id | Idempotency key: the same invoice is never imported twice (status skipped) |
curl -H "X-API-Key: lp_a1b2c3d4.…" https://books.konsulence.al/api/v1/ping
curl -H "X-API-Key: $KEY" "https://books.konsulence.al/api/v1/invoices?direction=sale&state=open&per_page=100"
curl -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
https://books.konsulence.al/api/v1/invoices \
-d '{"external_id":"ERP-45","direction":"sale","number":"45/2026","issue_date":"2026-09-01",
"partner":{"nipt":"L91234567B","name":"Klienti Sh.p.k."},
"lines":[{"description":"Konsulencë","quantity":1,"unit_price":50000,"vat_rate":20,"account_code":"701"}]}'curl -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
https://books.konsulence.al/api/v1/invoices/<id>/payments -d '{"amount":60000,"account_code":"512","pay_date":"2026-09-15"}'