Official JavaScript/TypeScript SDK for FirmAPI - Slovak Company Data API.
- Node.js 18 or higher
- Works in both Node.js and browser environments
npm install firmapi@^2
# or
yarn add firmapi@^2
# or
pnpm add firmapi@^2These docs cover v2.x. Upgrading from v1? See CHANGELOG.md for the breaking changes (fast-by-default, typed responses,
byIdremoved).
import FirmApi from 'firmapi';
const client = new FirmApi('your-api-key');
// Get company by IČO
const company = await client.companies.byIco('51636549');
console.log(company.data.name); // "Version Two s. r. o."
// Search companies
const results = await client.search.autocomplete('version');
results.results.forEach(result => {
console.log(`${result.text} (${result.ico})`);
});import FirmApi from 'firmapi';
// Basic initialization
const client = new FirmApi('your-api-key');
// With custom options (defaults shown)
const client = new FirmApi({
apiKey: 'your-api-key',
baseUrl: 'https://api.firmapi.sk/v1', // optional override
timeout: 30000, // per-request timeout (ms)
waitForFreshData: false, // block/re-poll until non-stale (opt-in)
maxStaleRetries: 3, // re-polls when waiting for fresh data
maxRetries: 2, // retries for transient 5xx/network errors
sandbox: false, // force sandbox; omit to auto-detect FIRMAPI_SANDBOX env
});Transient failures (HTTP 5xx and network errors) are retried automatically with
exponential backoff, up to maxRetries. HTTP 429 is not retried – it is
raised as a RateLimitException so you control pacing.
The sandbox needs no API key, returns demo data, and has no rate limits. Enable it any of three ways:
// 1. Explicit factory (or config flag)
const client = FirmApi.sandbox();
const client = new FirmApi({ apiKey: 'ignored', sandbox: true });
// 2. Environment variable (Node) – set before starting your app
// FIRMAPI_SANDBOX=true
const client = new FirmApi('ignored'); // auto-detected -> sandboxWhen sandbox is active the base URL and key are overridden with the built-in
sandbox endpoint automatically, so any key you pass is ignored. An explicit
sandbox: true | false in the config always wins over the env var.
FirmAPI serves precomputed company data immediately. When a background refresh
is queued, the response carries meta.stale = true – the data you received is
still valid; the flag only tells you a newer version is being prepared.
By default (since v2.0) the SDK returns that immediately-available data without
waiting. If you specifically need the post-refresh values and can tolerate the
extra latency and billed re-poll requests, opt in per query with fresh():
// Fast (default): resolves immediately, even if meta.stale is true
const company = await client.companies.byIco('51636549').get();
// Wait for a completed refresh (re-polls, bounded)
const fresh = await client.companies.byIco('51636549').fresh().get();// Get company by IČO (8-digit registration number).
// The query is thenable, so `await` resolves it directly; .get() is equivalent.
const company = await client.companies.byIco('51636549');
// Get company by ORSR ID
const company = await client.companies.byOrsrId('427482');Companies are always identified by IČO or ORSR ID – the SDK does not expose internal numeric database identifiers.
Request additional datasets with the fluent withX() helpers (each maps to an
API scope, subject to your plan's features), then resolve the query:
const company = await client.companies.byIco('51636549')
.withTax()
.withFinancials()
.withSanctions()
.get();
// Everything your plan is entitled to
const all = await client.companies.byIco('51636549').withAll().get();Available scope helpers: withTax, withBankAccounts, withContacts,
withFinancials, withDebtorStatus, withFinancialStatements,
withInsolvency, withCommercialBulletin, withPublicContracts,
withProcurement, withExecutionAuthorizations, withRpvs, withNbs,
withTaxReliability, withErasedVat, withReges, withSocialEnterprise,
withGleif, withSanctions, withTedTenders, withReplikAdministrator,
withSbs, withTransportLicence, withUtilityLicence,
withContractingAuthority, withDebarred, withUvoReferences,
withFsImports, withIllegalEmployment, withCourtDecisions,
withEmployerHeadcount, withSoiTravelAgency, withSvpsEstablishments,
withCrpProjects, withItms21, withTradeLicenseActivities, withAll.
with(...scopes: string[]) is an escape hatch for raw scope tokens, e.g.
.with('tax', 'sanctions').
Financial market entities supervised by Národná banka Slovenska, their licences and
agent → institution relations with history (requires the nbs feature):
// Every independent financial agent in the insurance sector
const page = await client.nbs.entities({
category: 'samostatný finančný agent',
sector: 'sektor poistenia alebo zaistenia',
limit: 50,
});
// Agents that used to work for an institution
const former = await client.nbs.agents('31361358', { status: 'ended' });
// One entity (also foreign ones without an IČO) with full licence history
const entity = await client.nbs.entity(page.data[0].entity_id);// Autocomplete (Select2-compatible format)
const results = await client.search.autocomplete('version', 10);
// Returns: { results: [{id, text, ico, city}], pagination: {more} }
// Search by name
const results = await client.search.byName('Version Two');
// Search by name (exact match)
const results = await client.search.byName('Version Two s. r. o.', { exact: true });
// Search by partial IČO
const results = await client.search.byIco('5163');
// Advanced search
const results = await client.search.advanced({
name: 'version',
city: 'Bratislava',
limit: 20,
});Batch operations require Starter plan or higher.
// Batch lookup by IČO
const results = await client.batch.byIco([
'51636549',
'12345678',
'87654321',
]);
// Batch lookup by names
const results = await client.batch.byNames([
'Version Two s. r. o.',
'Example Company',
]);
// Check batch job status
const status = await client.batch.status('batch-id-123');
// Get batch results
const results = await client.batch.results('batch-id-123');// Get current usage
const usage = await client.account.usage();
console.log(`Requests this month: ${usage.data.requests_month}`);
// Get remaining quota
const quota = await client.account.quota();
console.log(`Remaining: ${quota.data.remaining_daily} requests today`);
// Get usage history
const history = await client.account.history(30);The SDK is written in TypeScript and includes full type definitions:
import FirmApi, {
Company,
CompanyData,
SearchResult,
AutocompleteResponse,
BatchResponse,
} from 'firmapi';
const client = new FirmApi('your-api-key');
// Full type inference
const company: Company = await client.companies.byIco('51636549');
const data: CompanyData = company.data;
console.log(data.name);
console.log(data.shareholders?.[0]?.name);All API responses follow this structure:
interface ApiResponse<T> {
data: T;
meta?: {
synced_at?: string;
source?: string;
};
}Company data includes:
interface CompanyData {
id: number;
orsr_id: string;
ico: string;
name: string;
address: string;
registration_date?: string;
legal_form?: string;
business_activities?: string;
registered_capital?: string;
shareholders?: Shareholder[];
statutory_body?: StatutoryBody[];
// Additional fields based on plan:
tax?: TaxInfo; // Starter+
bank_accounts?: BankAccount[]; // Professional+
contacts?: Contacts; // Professional+
financials?: Financials; // Professional+
}import FirmApi, {
ApiException,
AuthenticationException,
RateLimitException,
ValidationException,
} from 'firmapi';
const client = new FirmApi('your-api-key');
try {
const company = await client.companies.byIco('51636549');
} catch (error) {
if (error instanceof AuthenticationException) {
// Invalid API key (401)
console.error(`Authentication failed: ${error.message}`);
} else if (error instanceof RateLimitException) {
// Too many requests (429)
console.error(`Rate limit exceeded. Retry after ${error.retryAfter} seconds`);
} else if (error instanceof ValidationException) {
// Invalid parameters (422)
console.error(`Validation error: ${error.message}`);
console.error(error.errors);
} else if (error instanceof ApiException) {
// Other API errors
console.error(`API error (${error.statusCode}): ${error.message}`);
}
}Rate limits depend on your subscription tier:
| Tier | Per Minute | Per Day | Per Month |
|---|---|---|---|
| Free | 5 | 10 | 100 |
| Starter | 10 | 100 | 1,000 |
| Professional | 30 | 500 | 10,000 |
| Enterprise | 100 | 5,000 | 100,000 |
The SDK uses the standard fetch API and works in modern browsers:
<script type="module">
import FirmApi from 'https://cdn.jsdelivr.net/npm/firmapi/dist/index.mjs';
const client = new FirmApi('your-api-key');
const company = await client.companies.byIco('51636549');
console.log(company);
</script>v2.0 is a behavior/API change:
- Fast by default. Lookups no longer block waiting for a background refresh.
If you relied on the old auto-wait, call
.fresh()per query, or setwaitForFreshData: truein the config. companies.byId(id)was removed. UsebyIco()orbyOrsrId().- Transient retries added. 5xx/network errors are retried (
maxRetries, default 2); 429 still raisesRateLimitException. - Malformed responses now throw
ApiExceptioninstead of resolving with a broken value.
MIT License. See LICENSE for details.
- Documentation: https://firmapi.sk/docs
- Email: support@firmapi.sk