npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@open-nav/evat

v0.3.0

Published

Client for NAV's eÁFA (eVAT) M2M VAT-return interface

Downloads

626

Readme

@open-nav/evat

Client for NAV's eÁFA (eVAT) M2M interface — Hungary's electronic VAT-return system (EAR 2.0), distinct from Online Számla.

npm install @open-nav/evat

Generated types and serialisation metadata come from the vendored schemas/EAR/2.0/ XSDs (see scripts/vendor_schemas.py); the schemas are vendored under NAV's evident org-wide MIT intent, though the upstream repository states no licence (see schemas/NOTICE.md).

Access

eÁFA reuses the Online Számla technical user — same login, password and signature key, no separate credentials. Grant that technical user two things in the NAV portals: "Hozzáférés e-ÁFA rendszer interfészhez" (interface access, in the User Manager) and, for the query operations, the "eÁFA M2M Lekérdezés" role. Authentication is the same crypto as Online Számla (SHA-512 password hash, SHA3-512 request signature).

import { EvatClient } from '@open-nav/evat';

const client = new EvatClient({
  environment: 'test', // or 'production'
  credentials: {
    login: process.env.NAV_LOGIN!,
    password: process.env.NAV_PASSWORD!,
    signKey: process.env.NAV_SIGN_KEY!,
    taxNumber: '12345678', // the 8-digit core
  },
  software: {
    softwareId: 'MYCOMPANY000000001',
    softwareName: 'my app',
    softwareOperation: 'LOCAL_SOFTWARE',
    softwareMainVersion: '1.0.0',
    softwareDevName: 'My Company',
    softwareDevContact: '[email protected]',
    softwareDevCountryCode: 'HU',
    softwareDevTaxNumber: '12345678',
  },
});

Reading VAT returns

import { decodeDownloadPayload } from '@open-nav/evat';

// Discovery — find the returns filed in a window (max 35 days per query).
const list = await client.queryDeclarationList({
  taxpointDateFrom: '2026-01-01',
  taxpointDateTo: '2026-01-31',
});

// Content — download and decode a return's compiled data, in one call.
import { readVatDeclaration } from '@open-nav/evat';
const xml = await readVatDeclaration(client, declarationProcessingId); // VatDeclarationData XML

readVatDeclaration wraps queryVatDeclarationData (a multipart/form-data download with a gzipped payload part) and decodeDownloadPayload (the gunzip). The whole read path — discovery and content — is verified against NAV's eÁFA test system.

declarationList vs statementList

queryDeclarationList returns two lists, and this trips people up: the analytics-based M2M declarations are in declarationList, while the traditional VAT returns (bevallás) — a taxpayer's regular monthly returns filed through ÖNYA/ÁNYK — are in statementList. If a query "returns nothing", you are probably reading the wrong one.

import { queryAllDeclarations, queryAllStatements } from '@open-nav/evat';

const declarations = await queryAllDeclarations(client, range); // declarationList
const statements = await queryAllStatements(client, range); //    statementList

queryDeclarationList caps a query window at 35 days; both helpers above walk the 35-day windows for you (and chunkTaxpointRange exposes the split).

Documents

queryDocumentList is asynchronous — it returns a queryId you resolve with queryDocumentListResult. queryAllDocuments does both, polling until the result is ready, across the 35-day windows:

import { queryAllDocuments } from '@open-nav/evat';

const lists = await queryAllDocuments(client, range); // one DocumentListType per window

Filing a declaration

const result = await client.submitDeclaration({
  declarationXml, // a VatDeclarationData document
  xsdVersion: 'eardata_2.0', // the current, live XSD version
  requestPeriodStart: '2026-01-01',
  requestPeriodEnd: '2026-01-31',
});
// poll queryDeclarationProcessingStatus(result.declarationProcessingId) to FINISHED,
// then manageDeclarationSubmission(...) to file.

submitDeclaration runs the upload lifecycle — manageDeclarationUpload (with the SHA3-512 content hash) → gzipped manageDeclarationPartition(s) → manageDeclarationFinalize. Polling and the final manageDeclarationSubmission are separate so you control the wait and the approval. The first analytics for a period must be version 1; attachment claimCheckIds in the XML must match those uploaded via manageAttachmentUpload. This lifecycle is verified live end to end.

buildVatAnalytics / buildVatAnalyticsItem bridge open-nav invoice data into the declaration's VAT-analytics ledger; classifying each line to a standard tax code is left to you (a VAT-law judgement), with TAX_CODES to draw on.

Testing without credentials

createEvatMock() returns a fetch to hand to EvatClient via transport.fetch, driving the whole lifecycle — upload, partitions, finalize, status polling, submission and the queries — in-process with no technical user.

import { createEvatMock, EvatClient } from '@open-nav/evat';

const mock = createEvatMock({ credentials });
const client = new EvatClient({ credentials, software, transport: { fetch: mock.fetch } });

Licence

MIT. Not affiliated with NAV.