TypeScript client for Parasut API v4. Handles auth, token refresh, rate limiting, and maps every endpoint in the spec.
npm install parasut-api-clientimport { ParasutClient } from 'parasut-api-client';
const client = new ParasutClient({
clientId: 'YOUR_CLIENT_ID',
clientSecret: 'YOUR_CLIENT_SECRET',
username: 'YOUR_EMAIL',
password: 'YOUR_PASSWORD',
companyId: 'YOUR_COMPANY_ID', // optional — defaults to first company
});
await client.initialize(); // authenticates + fetches user info & company list
const invoices = await client.salesInvoice.list();
const contact = await client.contacts.show('123');Uses OAuth2 password grant. Tokens are fetched on initialize() and refreshed automatically when they expire — tries refresh_token first, falls back to password grant.
Rate limiting is built in (10 req / 10s, matching the API's limit).
If you're running multiple processes or want to cache tokens (e.g. in Redis), use xid and onTokenReceived:
const client = new ParasutClient({
xid: 'my-app-instance',
// ...credentials
onTokenReceived(token, expiresAt, xid) {
redis.hset(`parasut:${xid}`, { token, expiresAt });
},
});Another instance can inject a cached token:
client.updateToken(cachedToken, cachedExpiresAt, 'my-app-instance');Every method is typed — returns ApiResponse<T> or ApiListResponse<T> instead of any.
| Module | What it covers |
|---|---|
salesInvoice |
CRUD, payments, cancel, recover, convert to invoice, PDF |
salesOffer |
CRUD, PDF |
purchaseBills |
CRUD, payments, cancel, recover |
contacts |
CRUD, debit/credit transactions, contact people |
products |
CRUD |
accounts |
CRUD, debit/credit transactions |
transactions |
Show, delete |
employees |
CRUD, archive/unarchive |
salaries |
CRUD, payments |
taxes |
CRUD, payments |
bankFees |
CRUD, payments |
tags |
CRUD |
itemCategories |
CRUD |
warehouses |
CRUD |
shipmentDocuments |
CRUD |
stockMovements |
List, show |
stockUpdates |
List |
inventoryLevels |
List |
eInvoice |
Create, show, PDF |
eArchive |
Create, show, PDF |
eSmm |
Create, show, PDF |
eInvoiceInboxes |
List |
webhooks |
CRUD |
trackableJobs |
Show |
sharings |
Create (send doc via email/link) |
companies |
List, show |
apiHome |
GET /me (user info) |
const invoice = await client.salesInvoice.create({
data: {
type: 'sales_invoices',
attributes: {
item_type: 'invoice',
issue_date: '2026-01-15',
currency: 'TRL',
},
relationships: {
contact: {
data: { id: '123', type: 'contacts' },
},
details: {
data: [
{
type: 'sales_invoice_details',
attributes: {
quantity: 1,
unit_price: 100.0,
vat_rate: 18,
description: 'Consulting',
},
},
],
},
},
},
});const page = await client.contacts.list({
page: 1,
per_page: 25,
filter: { name: 'Acme' },
sort: '-created_at',
include: 'contact_people',
});
// page.data — array of contacts
// page.meta — { current_page, total_pages, total_count, ... }API errors come back as ParasutApiError with the full response body:
import { ParasutApiError } from 'parasut-api-client';
try {
await client.contacts.show('nonexistent');
} catch (err) {
if (err instanceof ParasutApiError) {
console.log(err.status); // 404
console.log(err.statusText); // "Not Found"
console.log(err.body); // full JSON:API error body
}
}Accessing any module before initialize() throws a clear error:
const client = new ParasutClient({ /* ... */ });
client.contacts.list(); // throws: "Cannot access contacts.list before calling client.initialize()"npm run build # compile typescript
npm test # run tests (168 unit tests)
npm run test:watch # watch mode
npm run test:coverageSee CHANGELOG.md for the full list. The big ones:
- Removed methods that didn't actually exist in the API:
salesInvoice.listLines(),.print(),.sendEmail(),.approve(),transactions.update(),bankFees.list() salesOffer.getPdf()renamed tosalesOffer.createPdf()(it's a POST)salesInvoice.cancel()is now DELETE (was incorrectly PATCH)- API errors throw
ParasutApiErrorinstead of genericError - Must call
await client.initialize()before using modules
MIT