@jars-lt/jars-app-sdk
v0.2.0
Published
Official TypeScript SDK for the JARS Apskaita accounting API
Readme
@jars-lt/jars-app-sdk
Official TypeScript SDK for the JARS Apskaita accounting API — Lithuanian cloud accounting. Covers partners, products, invoices, journal entries and reports, plus cash registers & orders, bank transactions & statements, fixed assets & depreciation, employees & payroll, business trips, price lists, projects, professions, per-diem rates, numberings and exchange rates.
Install
pnpm add @jars-lt/jars-app-sdk
# or
npm install @jars-lt/jars-app-sdk
# or
yarn add @jars-lt/jars-app-sdkQuick start
import { JarsClient } from '@jars-lt/jars-app-sdk'
const jars = new JarsClient({ apiKey: process.env.JARS_API_KEY! })
// List partners with a search and a limit.
const partners = await jars.partners.list({ search: 'UAB', limit: 20 })
// Create a sales invoice (see the integration guide for the full line shape).
const invoice = (await jars.invoices.create({
type: 'SALES',
partnerId: partners[0]._id,
date: '2026-02-22',
lines: [/* ... */],
})) as { _id: string }
// Post it — this creates the journal entry and assigns the document number.
await jars.invoices.post(invoice._id)The facade methods return loosely-typed payloads (
unknown/unknown[]) by default. Pass a type argument —jars.partners.list<Partner[]>()— or cast the result to your own interface. Useclient.raw(below) for fully-typed, schema-checked access.
Authentication
- Log in to JARS → Settings → API Keys.
- Click Generate, give the key a name, and copy it — it is shown only once.
- Provide it as
apiKeywhen constructing the client.
Each API key is bound to a single company. All operations run in that company's context — there is no per-request tenant selection. The key is sent on every request as an Authorization: Bearer <key> header.
Configuration
new JarsClient(config: JarsClientConfig)| Option | Type | Required | Default | Description |
| --------- | --------------- | -------- | ------------------------ | ----------------------------------------------------------------- |
| apiKey | string | yes | — | Your company-scoped API key. Throws if missing. |
| baseUrl | string | no | https://app.jars.lt | Override for staging/local. Trailing slashes are stripped. |
| fetch | typeof fetch | no | global fetch | Custom fetch implementation (e.g. a polyfill or instrumented one).|
const jars = new JarsClient({
apiKey: process.env.JARS_API_KEY!,
baseUrl: 'http://localhost:3233', // local API
})Resources
Every resource is reachable as a property on the client (jars.partners, jars.invoices, …).
| Resource | Methods |
| ----------------- | ------------------------------------------------------------------------------------------------------------ |
| jars.partners | list · get · create · update · remove |
| jars.products | list · get · create · update · remove |
| jars.invoices | list · get · create · update · remove · post · unpost · cancel · setExternalStatus |
| jars.journal | list · get · create |
| jars.reports | trialBalance · generalLedger · partnerBalance · cashBook · isafExport |
| jars.auditLogs | list · get |
| jars.lookups | accounts · vatCodes · units · templates (list-only) |
| jars.cashRegisters | list · create · update · remove |
| jars.cashOrders | list · get · create · update · remove · post · unpost · fiscalize · setExternalStatus |
| jars.bankTransactions | list · get · create · update · post · unpost · setExternalStatus |
| jars.bankStatements | list · remove · detect · import (file upload) |
| jars.fixedAssets | list · get · create · update · remove · dispose |
| jars.depreciation | list · preview · post · unpost |
| jars.employees | list · get · create · update · remove · nextCode · verifyPin |
| jars.payroll | list · preview · post · unpost |
| jars.businessTrips | list · create · update · remove · postAdvance · postSettlement · unpost |
| jars.priceLists | list · get · create · update · remove |
| jars.projects | list · get · create · update · remove |
| jars.professions | list · get · create · update · remove |
| jars.perDiemRates | list · create · update · remove |
| jars.numberings | list · update (by prefix) |
| jars.exchangeRates | list (read-only euro FX rates) |
Method signatures
// CRUD resources (partners, products)
list<T = unknown[]>(params?: ListParams): Promise<T>
get<T = unknown>(id: string): Promise<T>
create<T = unknown>(body: Record<string, unknown>): Promise<T>
update<T = unknown>(id: string, body: Record<string, unknown>): Promise<T>
remove<T = unknown>(id: string): Promise<T>
// invoices additionally
post<T = unknown>(id: string): Promise<T>
unpost<T = unknown>(id: string): Promise<T>
cancel<T = unknown>(id: string): Promise<T>
setExternalStatus<T = unknown>(id: string, externalStatus: string | null): Promise<T>
// journal: list, get, create only
// reports: each method takes optional query params
trialBalance<T = unknown>(params?: ReportParams): Promise<T>
// lookups: list-only, e.g.
accounts<T = unknown[]>(params?: ListParams): Promise<T>
// document-lifecycle actions (cashOrders, bankTransactions, businessTrips, …)
post<T = unknown>(id: string): Promise<T>
unpost<T = unknown>(id: string): Promise<T>
// batch runs (payroll, depreciation)
preview<T = unknown>(body: Record<string, unknown>): Promise<T>
post<T = unknown>(body: Record<string, unknown>): Promise<T>
// bankStatements: multipart file upload (Blob/File)
detect<T = unknown>(file: Blob | File, filename?: string): Promise<T>
import<T = unknown>(file: Blob | File, fields?: Record<string, string>, filename?: string): Promise<T>Not in the facade yet
A few endpoints exist on the API but are not (yet) wrapped by a dedicated method:
- Invoice PDF generation and email (
POST /invoices/:id/pdf, etc.) - Reference-data writes — lookups expose list only; create/update/delete of accounts, VAT codes, units, and templates.
These are still reachable through the typed escape hatch below.
Raw escape hatch
client.raw is the underlying openapi-fetch client, fully typed against the API's OpenAPI schema. Use it for endpoints the facade doesn't wrap, or when you want compile-time-checked paths and payloads:
const { data, error } = await jars.raw.GET('/api/accounts', {
params: { query: { search: '24' } },
})The exported paths and components types describe the full schema:
import type { paths, components } from '@jars-lt/jars-app-sdk'Errors
Any non-2xx response (and network/abort failures, reported as status: 0) throws a JarsApiError:
import { JarsClient, JarsApiError } from '@jars-lt/jars-app-sdk'
try {
await jars.invoices.post(id)
} catch (e) {
if (e instanceof JarsApiError) {
console.error(e.status) // HTTP status (0 on network failure)
console.error(e.code) // stable error code, when the API provides one
console.error(e.details) // optional extra detail (e.g. validation issues)
console.error(e.message) // human-readable message
}
}Money convention
- Line-level values (
unitPrice,lineSubtotal,lineTotal,vatAmount) are EUR with up to 4 decimal places, e.g.unitPrice: 99.00. - Document-level values (
subtotal,vatTotal,total,amountDue, andvatSummary[]amounts) are integer cents, e.g.subtotal: 9900for €99.00.
Localized names are objects of the form { lt, en?, ru? } (lt required; en/ru optional).
See the Integration Guide for the full invoice/VAT calculation rules and a complete worked example.
Lists & filtering
Every list(params?) returns an array. The params object accepts the documented common keys plus arbitrary field filters that are passed straight through as query parameters:
interface ListParams {
search?: string
sort?: string // field name; prefix with '-' for descending, e.g. '-date'
limit?: number // default 200, max 1000
[filter: string]: string | number | boolean | undefined
}// arbitrary field filters
await jars.invoices.list({ status: 'POSTED', type: 'SALES', sort: '-date', limit: 50 })
await jars.partners.list({ externalCode: 'CRM-12345' })Versioning
The SDK follows semantic versioning independently of the API version:
- A new, additive API field → minor SDK release.
- A removed or renamed field, or a breaking method signature change → major SDK release.
Releasing
Publishing is automated by the Publish SDK GitHub Actions workflow, run manually from the Actions tab:
- Open Actions → Publish SDK → Run workflow.
- Choose a version bump:
none(publish the currentpackage.jsonversion as-is),patch,minor, ormajor. - Run it.
The workflow verifies the generated types are in sync with the API, runs the SDK tests, builds the package, publishes it to npm, and — when a bump was chosen — commits the new version back to main (sdk v<version>).
Requires the NPM_TOKEN repository secret: an npm automation token with publish rights to the @jars-lt scope.
License
MIT
