Node.js SDK
The official Node.js SDK for accessing German company registry data through the Handelsregister.ai API.
Installation and authentication
npm install handelsregister
export HANDELSREGISTER_API_KEY=your-api-keyThe SDK sends credentials only as x-api-key or Authorization: Bearer … headers, never in URLs. API keys are the default; Bearer tokens provide fine-grained, expiring access and take precedence when both are available. Add gateway headers with extraHeaders or HANDELSREGISTER_EXTRA_HEADERS; SDK-managed authentication and User-Agent headers cannot be replaced.
const { Handelsregister, Company } = require('handelsregister');
const client = new Handelsregister({
apiKey: process.env.HANDELSREGISTER_API_KEY,
timeout: 60_000,
cacheEnabled: true,
rateLimit: 1,
});
// Bearer tokens take precedence over API keys.
const tokenClient = new Handelsregister({
bearerToken: process.env.HANDELSREGISTER_BEARER_TOKEN,
});Company, person, and search APIs
fetchOrganization() returns typed enrichment data. aiSearch accepts a boolean or "on-default"/"off"; realtimeMode accepts a boolean or "handelsregister-default". Company and Person wrappers add lazy loading and convenient properties.
const data = await client.fetchOrganization({
q: 'KONUX GmbH München',
features: ['related_persons', 'financial_kpi', 'mergers_and_acquisitions'],
aiSearch: true,
realtimeMode: false, // true triggers a live lookup (+10 credits)
});
const company = new Company('OroraTech GmbH München', process.env.HANDELSREGISTER_API_KEY);
console.log(await company.getName(), company.registerNumber);
console.log(data.representation_scheme?.current);searchOrganizations() supports all documented identity, industry, status, location/radius, register, employee, balance-sheet, and P&L filters. Query q is optional when filters are supplied. The SDK translates flat financial filters to the current nested wire format; it also maps company_size_category to emp_size_category. The request limit is 30; each lazy iterator page is separately billable.
const result = await client.searchOrganizations({
q: 'tech',
limit: 20,
filters: {
postal_code: '80331',
legal_form_code: ['GmbH', 'UG'],
active: true,
pl_revenue: { gte: 1_000_000, lte: 5_000_000 },
},
aiMode: false,
});
for await (const organization of client.iterateSearchOrganizations({
q: 'technology München', pageSize: 30, maxResults: 100,
})) {
console.log(organization.entity_id, organization.name);
}fetchPerson() always uses AI enrichment (15 base credits); shareholdings adds 5 credits only when returned. fetchDocument() accepts positional or object arguments and returns a Buffer or writes to a file. Use fetchDocumentWithMetadata() for Content-Type and server filename. Supported document types are shareholders_list, articles_of_association, AD, CD, and SI.
Signals
Signals provide cursor-paginated commercial-register changes. Catalog requests are free; successful list pages and detail requests cost 20 credits. Pages contain 20 entries.
const { SignalTopic } = require('handelsregister');
const filters = {
topics: [SignalTopic.CAPITAL_CHANGES, SignalTopic.TRANSFORMATIONS],
organizationIds: ['organization-id-one', 'organization-id-two'],
fromDate: '2026-07-01',
toDate: '2026-07-30',
};
const page = await client.listSignals(filters);
const catalog = await client.getSignalCatalog();
const detail = await client.getSignal(page.signals[0].event.id);
for await (const signal of client.iterateSignals({
topics: [SignalTopic.NEW_REGISTRATIONS], maxResults: 50,
})) {
console.log(signal.event.id, signal.organization?.entity_id);
}Preserve filters and pass pagination.next_cursor unchanged for manual pagination. Multiple organization IDs use OR semantics. The seven topics are NEW_REGISTRATIONS, MASTER_DATA_CHANGES, CLOSURES, ROLE_HOLDER_CHANGES, CAPITAL_CHANGES, INSOLVENCIES (Pro/Max), and TRANSFORMATIONS (Max). HTTP 403 PLAN_REQUIRED becomes SubscriptionRequiredError and costs zero credits.
Account and usage
Account requests are free. An API key or account:read Bearer token can read the profile, credits, usage, subscription, and masked API keys. Date ranges are limited to 366 days; transaction pages use opaque cursors. Creating or revoking API keys requires a dashboard-created Bearer token with account:keys; full key values are returned only once.
const account = await client.getAccount();
const credits = await client.getAccountCredits();
const subscription = await client.getAccountSubscription();
const keys = await client.listApiKeys();
for await (const transaction of client.iterateAccountUsageTransactions({
perPage: 100,
})) {
console.log(transaction.endpoint, transaction.credits);
}Monitoring and webhooks
Monitoring watches organizations and pushes normalized Signals to HTTPS endpoints. Reads and management requests are free; an activated monitor starts with the current 10-credit cycle floor. Check getMonitoringPricing() before creating or resuming a monitor. Monitor lifecycle operations require account:read plus monitoring:manage; webhook endpoint lifecycle requires account:read plus account:keys.
const admin = new Handelsregister({ bearerToken: process.env.ADMIN_TOKEN });
const createdEndpoint = await admin.createWebhookEndpoint({
name: 'Production receiver',
url: 'https://hooks.example.com/handelsregister',
headers: { 'x-tenant': 'customer-42' },
});
const endpointId = createdEndpoint.endpoint.id;
const signingSecret = createdEndpoint.signing_secret; // returned only once
await admin.verifyWebhookEndpoint(endpointId);
await admin.testWebhookEndpoint(endpointId);
const monitor = (await client.createMonitor({
entityId: 'organization-entity-id',
pollIntervalDays: 7,
endpointIds: [endpointId],
label: 'Important customer',
})).monitor;
await client.pauseMonitor(monitor.id);
await client.resumeMonitor(monitor.id);
await client.archiveMonitor(monitor.id);Store the one-time signing secret immediately. Monitoring mutations receive an automatically generated Idempotency-Key, reused across safe retries; provide idempotencyKey for durable retries across restarts and inspect client.lastIdempotencyStatus. HTTP 409 ambiguity is never retried. Verify raw bytes with constructEvent() before parsing JSON, answer verification challenges with verificationResponseHeaders(), and deduplicate at-least-once deliveries by event ID.
Tokens, enrichment, and CLI
Bearer-token management supports creating, listing, revoking one token, and revoking all tokens deliberately. Batch enrichment supports CSV, JSON, and XLSX snapshots. The bundled CLI covers lookups, filters-only search, documents, enrichment, monitoring, webhook endpoints, deliveries, and events.
const { token } = await client.createToken({
tokenName: 'ci-pipeline',
abilities: ['*'],
expiresAt: '2027-01-01 00:00:00',
});
const { tokens } = await client.listTokens();
await client.revokeToken(tokens[0].id);
await client.enrich({
filePath: 'companies.csv',
inputType: 'csv',
queryProperties: { company_name: 'name', city: 'location' },
snapshotDir: './snapshots',
params: { features: ['financial_kpi', 'related_persons'] },
});handelsregister fetch "KONUX GmbH München" --feature financial_kpi
handelsregister search --filters '{"legal_form_code":"GmbH"}' --limit 30
handelsregister document "KONUX GmbH" --type SI --output konux.xml
handelsregister enrich companies.csv --feature related_persons
handelsregister monitors pricing --interval 7
handelsregister webhooks eventsTypeScript, features, and errors
The package is written in TypeScript and ships full type definitions. Available features include related_persons, financial_kpi, balance_sheet_accounts, profit_and_loss_account, publications, annual_financial_statements, annual_financial_statements__html, insolvency_publications, shareholders, ubos, shareholdings, mergers_and_acquisitions, news, and website_content. Current responses use nested contact_data, representation_scheme, and feature structures; publications is returned as history.
import { Handelsregister, CompanyData, Feature } from 'handelsregister';
const features: Feature[] = ['financial_kpi', 'related_persons'];
const data: CompanyData = await client.fetchOrganization({
q: 'company name',
features,
});Errors expose response, statusCode, responseHeaders, and errorCode. Use the specific error classes for authentication, credits, subscriptions, idempotency conflicts, service availability, not found, timeouts, rate limits, and validation. Legacy base error classes remain compatible with instanceof checks. Never commit API keys, Bearer tokens, or webhook signing secrets.
For the complete API surface and runnable examples, see the Handelsregister Node.js SDK repository.