Skip to content
futozsPublic

About

Számlázz.hu, TypeScriptben, egyszerűbben. Nem hivatalos TypeScript wrapper a Számlázz.hu Számla Agenthez. Mind a 11 Agent művelet, 0 függőség, nulla runtime kompromisszum.

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

109 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

kassza: Számlázz.hu, TypeScriptben. Telepítés: npm i kassza

Számlázz.hu, TypeScriptben, egyszerűbben.
Nem hivatalos TypeScript wrapper a Számlázz.hu Számla Agenthez. Mind a 11 Agent művelet, 0 függőség, nulla runtime kompromisszum.
English overview

npm verzió havi letöltés 0 futásidejű függőség MIT licenc
CI állapota Heti teljes ellenőrzés: CI, XSD, változásfigyelő, élő e2e Kiadás állapota OpenSSF Scorecard pontszám
Sor-lefedettség Ág-lefedettség Függvény-lefedettség Utasítás-lefedettség

npm i kassza
import { createKassza } from 'kassza'

const kassza = createKassza()

const szamla = await kassza.invoices.create({
  buyer: { name: 'Vevő Kft.', zip: '1111', city: 'Budapest', address: 'Fő utca 1.', email: 'vevo@ceg.hu' },
  items: [{ name: 'Webfejlesztés', quantity: 10, unit: 'óra', netUnitPrice: 15_000, vat: 27 }],
})

console.log(szamla.number, szamla.grossTotal)

Ennyi. A kerekítést, a magyar dátumot, az XML-t, a session cookie-t és a hibakezelést a kassza intézi, a vevő pedig e-mailben megkapja a számlát.

Dokumentáció: Telepítés Futtasd a sandboxban: Számla kiállítása

Miért kassza?

Számla Agent műveletek: a kassza mind a 11-et tudja, a többi csomag 2 vagy 3 műveletet

  • Mind a 11 Agent művelet. Számla, díjbekérő, nyugta, sztornó, befizetés, PDF és adószám, nem csak a számla kiállítása.
  • Pontos kerekítés. A tételek nettó, áfa és bruttó értékét a Számlázz.hu szabályai szerint számolja, mert egy forint eltérés is elég, hogy a számla ne készüljön el.
  • Nincs dupla számla. Számlát a kassza soha nem küld újra magától. A createOnce() kiállítás előtt megkeresi a bizonylatot, bizonytalan hiba után pedig visszakeresi.
  • Fizetésből bizonylat. Stripe, SimplePay, Barion, Revolut és PayPal webhookból pontosan egyszer nyugta vagy számla, visszatérítéskor sztornó.
  • NAV nyugta-adatszolgáltatás. Napi összesítő és egyeztetés a 2026. szeptember 1-jétől kötelező adatszolgáltatáshoz.
  • Egy hibatípus. A Számlázz.hu háromféle hibaformátumából egyetlen SzamlazzError lesz, magyar üzenettel és javítási tippel.
  • Serverless és edge. Node, Bun, Deno, Cloudflare Workers és Vercel Edge alatt is fut, a session cookie közös tárolóban is lehet.
Részletes összehasonlítás · 6 csomag, 12 szempont
kassza szamlazz.js @ribbery009/ szamlazz-ts @halftome/ szamlazz-client szamlazz.ts szamlazzhu-client
Számla, sztornó ✅ ✅ ✅ ✅ ✅ ✅
Számla adatainak lekérése ✅ ✅ ✅ ✅ ✅ ❌
Nyugta (létrehozás, sztornó, lekérdezés, kiküldés) ✅ ❌ ❌ ❌ ❌ ❌
Befizetés rögzítése ✅ ❌ ❌ ❌ ❌ ❌
PDF lekérése utólag ✅ ❌ ❌ ❌ ❌ ❌
Díjbekérő törlése ✅ ❌ ❌ ❌ ❌ ❌
Adószám lekérdezés (NAV) ✅ ❌ ❌ ❌ ❌ ❌
Runtime függőség 0 6 6 1 7 3
TypeScript típusok ✅ ❌ ✅ ✅ ✅ ✅
Edge (Workers, Vercel Edge) ✅ ❌ ❌ – ❌ ❌
Mock kliens teszteléshez ✅ ❌ ❌ ❌ ❌ ❌
IPN webhook, validátorok, PDF tárhely ✅ ❌ ❌ ❌ ❌ ❌

A műveleteket 2026 szeptemberében a publikált csomagok kódjában ellenőriztük (melyik Agent form mezőt küldik). Az Edge oszlopban ❌ az axios, tough-cookie vagy form-data függőség miatt szerepel, ezek nem futnak Workers alatt. A „–” azt jelenti, hogy nem teszteltük.

Dokumentáció: Mi a kassza?

Tartalom

Kezdés Műveletek Integrációk Kiegészítők
🌐 Weboldal, sandbox és receptek 📄 Számlák 💳 Fizetésből bizonylat 🗄️ PDF mentése tárhelyre
⚙️ Beállítás 🧾 Nyugták 📊 NAV nyugta-adatszolgáltatás ⚡ Serverless és edge
🚨 Hibakezelés 🏛️ Adószám lekérdezés 🤝 Megbízotti számlázás 🧪 Tesztelés
🎛️ Haladó beállítások 🔔 Fizetési értesítés (IPN) 🔗 Pénzügyi adatkapcsolat 🧮 Validátorok és pénzszámítás
🤖 AI-val kódolsz? 🔁 Tömeges számlázás 🟩 Node.js és Express 💻 Parancssor és MCP szerver
📒 Bizonylatnapló 📈 Megfigyelhetőség

Weboldal, sandbox és receptek

A teljes magyar dokumentáció, a sandbox és a receptek a kasszajs.hu oldalon vannak.

A kassza sandbox: futtatható példák, TypeScript kód és a ténylegesen elküldött XML

  • 📖 Dokumentáció: 190 oldal magyarul. Minden Agent művelethez kérés, válasz és futtatható minta, a beállítások, a szabályok és az összes ismert hibakód.
  • ▶️ Sandbox: 28 példa, amit a böngészőben futtathatsz Agent kulcs nélkül, szimulált Számlázz.hu ellen, a ténylegesen elküldött XML-lel. A saját kódodat linkként meg is oszthatod.
  • 🍳 Receptek: 11 teljes, bemásolható integráció webshophoz, Stripe és IPN webhookhoz, díjbekérőhöz, pénztári nyugtához, PDF tárhelyhez, Cloudflare Workershez és tesztekhez.
  • 🤖 llms.txt: a dokumentáció tartalomjegyzéke AI asszisztenseknek, a teljes szöveg egy fájlban: llms-full.txt.
  • 📦 npm csomag · 🏛️ Hivatalos Számlázz.hu Agent dokumentáció
🍳 Mind a 11 recept
  • Közös kliens: Egyetlen szerveroldali kassza kliens alapbeállításokkal, hibanaplózással és közös munkamenettel, amelyet a többi recept importál.
  • Fizetett rendelés számlája: Idempotens számlázás rendelésszámmal.
  • Stripe webhook: Számla a Stripe Checkout checkout.session.completed eseményéből.
  • Nevezés díjbekérővel: Versenynevezés vagy rendezvényjelentkezés átutalásos fizetéssel.
  • IPN webhook: A Számlázz.hu fizetési értesítésének (IPN) fogadása Next.js route handlerben, IP-ellenőrzéssel, a számla állapotának visszaellenőrzésével és idempotens mentéssel.
  • Pénztári nyugta: Nyugta egy food truck pénztárprogramjából a receipts.createOnce metódussal, a dupla nyugta kezelésével és e-mail kiküldéssel, Next.js route handlerben.
  • PDF mentése S3-ba vagy R2-be: A számla PDF-jének mentése saját Amazon S3 vagy Cloudflare R2 tárhelyre AWS SDK nélkül, stabil kulccsal és rövid ideig érvényes letöltési linkkel.
  • Adószám alapú kitöltés: Számlázási űrlap, amely a beírt adószám alapján a NAV adataiból tölti ki a cégnevet és a székhely címét.
  • Devizás számla EU-s cégnek: Euróban kiállított, angol nyelvű számla másik tagállambeli cégnek, közösségi adószámmal, MNB árfolyammal és angol értesítő e-maillel.
  • Cloudflare Workers: Cloudflare Worker, amely a kasszával lekérdezi a számlákat, a munkamenetet KV-ben tartja, a számla PDF-eket pedig R2-ben gyorsítótárazza.
  • Egységtesztek: Vitest tesztek a receptek kódjához mock klienssel.
▶️ Mind a 28 sandbox példa

Számlák: Számla kiállítása · Webshop számla bruttó árakkal · Díjbekérő, majd számla · Előleg- és végszámla · Helyesbítő számla · Devizás számla EU-s vevőnek · Számlaelőnézet · Számla sztornózása · Befizetések rögzítése · PDF lekérése utólag · Számla adatainak lekérése · Díjbekérő törlése

Nyugták: Nyugta kiállítása · Pénztári nyugta, dupla gombnyomás · Nyugta sztornózása · Nyugta lekérdezése · Nyugta kiküldése e-mailben

NAV: Adószám lekérdezése

Hibakezelés: Idempotens számlázás hiba után · Validációs hibák · Agent kulcs ellenőrzése · Hookok és újrapróbálás

Eszközök: Közös session több kliens között · Mock kliens tesztekhez · Kerekítés és összegzés · Validátorok · IPN fizetési értesítés · PDF mentése tárhelyre

Beállítás

Az Agent kulcsot a Számlázz.hu felületén, a vezérlőpult alján generálhatod.

SZAMLAZZ_AGENT_KEY=a-te-agent-kulcsod
import { createKassza } from 'kassza'

export const kassza = createKassza()
Alapbeállítások és a kulcs ellenőrzése · defaults, verifyCredentials()

Az ismétlődő adatokat elég egyszer megadni:

export const kassza = createKassza({
  agentKey: process.env.SZAMLAZZ_AGENT_KEY,
  defaults: {
    invoice: {
      prefix: 'WEB',
      paymentDueInDays: 8,
      seller: { emailReplyTo: 'penzugy@ceg.hu', emailSubject: 'Elkészült a számlád' },
    },
    receipt: { prefix: 'NYGT', paymentMethod: 'bankkártya' },
  },
})

await kassza.verifyCredentials()

A verifyCredentials() visszatérési értéke true, ha a kulcs jó.

📖 Dokumentáció: Hitelesítés (Agent kulcs)  ·  ▶️ Sandbox: Agent kulcs ellenőrzése

Dokumentáció: Kliens beállítása Futtasd a sandboxban: Agent kulcs ellenőrzése Recept: Közös kliens

Számlák

Egyetlen metódus, az invoices.create() állít ki számlát, díjbekérőt, előleg-, vég- és helyesbítő számlát vagy szállítólevelet. Mellette ott a sztornó, a befizetés, a PDF és a lekérdezés.

Számla · invoices.create()
const szamla = await kassza.invoices.create({
  orderNumber: 'REND-1001',
  paymentMethod: 'bankkártya',
  paid: true,
  buyer: {
    name: 'Vevő Kft.',
    zip: '1111',
    city: 'Budapest',
    address: 'Fő utca 1.',
    email: 'vevo@ceg.hu',
    taxNumber: '12345676-2-42',
  },
  items: [
    { name: 'Póló', quantity: 2, grossUnitPrice: 5_990, vat: 27 },
    { name: 'Szállítás', grossUnitPrice: 1_490, vat: 27 },
  ],
})

szamla.number
szamla.netTotal
szamla.grossTotal
szamla.pdf
  • Az orderNumber a saját azonosítód, ezzel később vissza is keresheted a számlát.
  • A szamla.pdf egy Uint8Array.

📖 Dokumentáció: Számla létrehozás › Kérés  ·  ▶️ Sandbox: Számla kiállítása

Nettó vagy bruttó ár, áfakulcsok · netUnitPrice, grossUnitPrice, vat

Az ár megadható nettóban vagy bruttóban, a kerekítés a hivatalos szabályok szerint történik:

{ name: 'Tanácsadás', netUnitPrice: 20_000, vat: 27 }
{ name: 'Belépő', grossUnitPrice: 4_990, vat: 27 }
{ name: 'Könyv', grossUnitPrice: 3_500, vat: 5 }
{ name: 'Oktatás', netUnitPrice: 50_000, vat: 'AAM' }

A nettó ár a B2B számlákhoz, a bruttó ár a B2C számlákhoz való. Az 'AAM' alanyi adómentes tételt jelöl, a többi áfakódot a Áfakulcsok oldal sorolja fel.

📖 Dokumentáció: Kerekítés  ·  ▶️ Sandbox: Webshop számla bruttó árakkal

Díjbekérő, majd számla · type: 'proforma'
const dijbekero = await kassza.invoices.create({
  type: 'proforma',
  orderNumber: 'NEV-42',
  buyer,
  items,
})

const szamla = await kassza.invoices.create({
  proformaNumber: dijbekero.number,
  orderNumber: 'NEV-42',
  paid: true,
  buyer,
  items,
})

📖 Dokumentáció: Bizonylattípusok  ·  ▶️ Sandbox: Díjbekérő, majd számla

Díjbekérő törlése · invoices.deleteProforma()
await kassza.invoices.deleteProforma({ orderNumber: 'NEV-42' })

📖 Dokumentáció: Díjbekérő törlése  ·  ▶️ Sandbox: Díjbekérő törlése

Előleg- és végszámla · type: 'advance', 'final'
const eloleg = await kassza.invoices.create({
  type: 'advance',
  orderNumber: 'PROJ-7',
  buyer,
  items: [{ name: 'Előleg', netUnitPrice: 300_000, vat: 27 }],
})

await kassza.invoices.create({
  type: 'final',
  advanceInvoiceNumber: eloleg.number,
  orderNumber: 'PROJ-7',
  buyer,
  items: [
    { name: 'Weboldal', netUnitPrice: 1_000_000, vat: 27 },
    { name: 'Előleg levonása', quantity: -1, netUnitPrice: 300_000, vat: 27 },
  ],
})

📖 Dokumentáció: Bizonylattípusok  ·  ▶️ Sandbox: Előleg- és végszámla

Helyesbítő számla · type: 'corrective'
await kassza.invoices.create({
  type: 'corrective',
  correctedInvoiceNumber: 'E-WEB-2026-12',
  buyer,
  items: [{ name: 'Póló visszáru', quantity: -1, grossUnitPrice: 5_990, vat: 27 }],
})

📖 Dokumentáció: Bizonylattípusok  ·  ▶️ Sandbox: Helyesbítő számla

Szállítólevél · type: 'deliveryNote'
await kassza.invoices.create({ type: 'deliveryNote', buyer, items })

📖 Dokumentáció: Bizonylattípusok

Devizás számla, külföldi vevő · currency, language
await kassza.invoices.create({
  currency: 'EUR',
  language: 'en',
  buyer: {
    name: 'Acme GmbH',
    country: 'Germany',
    zip: '10115',
    city: 'Berlin',
    address: 'Hauptstr. 1',
    euTaxNumber: 'DE123456789',
    taxpayerType: 'euBusiness',
  },
  items: [{ name: 'Consulting', quantity: 8, unit: 'hour', netUnitPrice: 95, vat: 'EUFAD37' }],
})

Az árfolyam, ha nem adod meg, automatikusan az MNB aktuális árfolyama. Kész minta: Devizás számla EU-s cégnek.

📖 Dokumentáció: Támogatott devizanemek  ·  ▶️ Sandbox: Devizás számla EU-s vevőnek

Előnézet, számla kiállítása nélkül · invoices.preview()
const { pdf, grossTotal } = await kassza.invoices.preview({ buyer, items })

📖 Dokumentáció: Előnézet  ·  ▶️ Sandbox: Számlaelőnézet

Melléklet az e-mailhez · attachments
await kassza.invoices.create({
  buyer,
  items,
  attachments: [{ filename: 'aszf.pdf', content: aszfPdfBytes, contentType: 'application/pdf' }],
})

Legfeljebb 5 melléklet adható meg, darabonként 2 MB.

📖 Dokumentáció: Számlaértesítő küldés

Sztornó · invoices.reverse()
const sztorno = await kassza.invoices.reverse('E-WEB-2026-12')

📖 Dokumentáció: Számla sztornó  ·  ▶️ Sandbox: Számla sztornózása

Befizetés rögzítése · invoices.registerPayment()
await kassza.invoices.registerPayment({ invoiceNumber: 'E-WEB-2026-12', amount: 12_700 })

await kassza.invoices.registerPayment({
  invoiceNumber: 'E-WEB-2026-13',
  payments: [
    { method: 'készpénz', amount: 5_000, date: '2026-09-01' },
    { method: 'átutalás', amount: 7_700 },
  ],
})

await kassza.invoices.clearPayments('E-WEB-2026-12')

A registerPayment egyetlen befizetést és több részletet is fogad. A clearPayments az összes befizetést törli a számláról.

Ha ugyanaz a befizetés több helyről is érkezhet (banki értesítés, webhook), a registerPaymentOnce({ invoiceNumber, key, amount }) egy stabil kulccsal pontosan egyszer rögzíti: a kulcsot jelölőként a befizetés leírásába teszi, és rögzítés előtt megkeresi.

📖 Dokumentáció: Befizetés rögzítése  ·  ▶️ Sandbox: Befizetések rögzítése

PDF letöltése utólag · invoices.getPdf()
import { writeFile } from 'node:fs/promises'

const { pdf } = await kassza.invoices.getPdf('E-WEB-2026-12')
await writeFile('szamla.pdf', pdf)

Rendelésszám vagy külső azonosító alapján is működik: getPdf({ orderNumber: 'REND-1001' }), getPdf({ externalId: 'a1b2' }).

📖 Dokumentáció: Bizonylat lekérése PDF-ben  ·  ▶️ Sandbox: PDF lekérése utólag

Számla adatainak lekérése · invoices.get(), invoices.find()
const adatok = await kassza.invoices.get({ orderNumber: 'REND-1001' })
adatok.header.issueDate
adatok.buyer.name
adatok.items
adatok.payments

const talan = await kassza.invoices.find({ orderNumber: 'REND-9999' })

A find null-t ad, ha nincs ilyen számla, a get ilyenkor hibát dob.

📖 Dokumentáció: Számla adatainak lekérése  ·  ▶️ Sandbox: Számla adatainak lekérése

Dokumentáció: Számla létrehozás Futtasd a sandboxban: Számla kiállítása Recept: Fizetett rendelés számlája

Nyugták

Nyugta kiállítása, kiküldése e-mailben, lekérdezése és sztornózása, forintos kerekítéssel és a dupla nyugta elleni hívásazonosítóval. A Számla Agent nyugtája számítógéppel előállított nyugta, online pénztárgépet nem pótol: csak nem pénztárgép-köteles tevékenységhez adható, például webshopban vagy food truckban. Részletek: Nyugta vagy számla?.

Nyugta · receipts.create()
const nyugta = await kassza.receipts.create({
  prefix: 'NYGT',
  paymentMethod: 'készpénz',
  callId: 'KASSZA-2026-0001',
  items: [
    { name: 'Kávé', quantity: 2, grossUnitPrice: 890, vat: 27 },
    { name: 'Kifli', grossUnitPrice: 250, vat: 5 },
  ],
})

nyugta.number
nyugta.totals.grossAmount
nyugta.pdf

A callId véd a dupla nyugta ellen.

📖 Dokumentáció: Nyugta létrehozás  ·  ▶️ Sandbox: Nyugta kiállítása

Kiküldés e-mailben · receipts.send()
await kassza.receipts.send({ receiptNumber: nyugta.number, emails: 'vevo@ceg.hu' })

📖 Dokumentáció: Nyugta kiküldés  ·  ▶️ Sandbox: Nyugta kiküldése e-mailben

Lekérdezés · receipts.get(), receipts.find()
const ugyanaz = await kassza.receipts.get(nyugta.number)
const rendelesbol = await kassza.receipts.find({ orderNumber: 'REND-1001' })

📖 Dokumentáció: Nyugta lekérdezés  ·  ▶️ Sandbox: Nyugta lekérdezése

Sztornó · receipts.reverse()
await kassza.receipts.reverse(nyugta.number)

📖 Dokumentáció: Nyugta sztornó  ·  ▶️ Sandbox: Nyugta sztornózása

Nyugta vagy számla? · chooseDocument(), receipts.convertToInvoice()
import { chooseDocument } from 'kassza'

const dontes = chooseDocument({ grossTotal: 18_990, invoiceRequested: false })

dontes.type
dontes.reasons

Nyugta csak akkor adható, ha a vevő nem adóalany és nem jogi személy, az összeg 900 000 Ft alatti, a teljesítésig kifizetik, és a vevő nem kér számlát. Ha a vevő utólag kér számlát, a convertToInvoice() sztornózza a nyugtát, és számlát állít ki helyette, pontosan egyszer:

const atalakitas = await kassza.receipts.convertToInvoice({
  receiptNumber: nyugta.number,
  buyer: { name: 'Példa Kft.', zip: '1111', city: 'Budapest', address: 'Fő utca 1.', taxNumber: '12345676-2-42' },
})

atalakitas.invoice.number

📖 Dokumentáció: Nyugta vagy számla?

Dokumentáció: Nyugta létrehozás Futtasd a sandboxban: Nyugta kiállítása Recept: Pénztári nyugta

Adószám lekérdezés

Egy adószámból megkapod a cég nevét és székhelyét, így a vevő adatait nem kell kézzel begépelni.

Cégadatok adószám alapján · taxpayer.query()
const ceg = await kassza.taxpayer.query('13421739')

if (ceg.valid) {
  ceg.name
  ceg.taxNumber?.formatted
  ceg.address?.formatted
}

A cégadatok a NAV-tól jönnek, a cím formázva, például 1031 Budapest, Záhony utca 7. Űrlapokhoz a taxpayerCache: { store } beállítás közös tárolóban megjegyzi az eredményt, így ugyanaz az adószám csak egyszer megy ki.

📖 Dokumentáció: Adószám lekérdezés  ·  ▶️ Sandbox: Adószám lekérdezése

Dokumentáció: Adószám lekérdezés Futtasd a sandboxban: Adószám lekérdezése Recept: Adószám alapú kitöltés

Hibakezelés

Minden hiba SzamlazzError, magyar üzenettel és javítási tippel.

Duplikált rendelésszám és validációs hiba · isSzamlazzError()
import { isSzamlazzError } from 'kassza'

try {
  await kassza.invoices.create(input)
} catch (error) {
  if (!isSzamlazzError(error)) throw error

  if (error.isDuplicate) return kassza.invoices.find({ orderNumber: input.orderNumber! })
  if (error.category === 'validation') console.error(error.message, error.hint)
  throw error
}
  • error.code: a Számlázz.hu hibakódja, például 57.
  • error.hint: magyar javítási tipp.

📖 Dokumentáció: Hibakezelés, hibakódok  ·  ▶️ Sandbox: Idempotens számlázás hiba után

Hibakategóriák · error.category
error.category Jelentés
validation Hibás adat, a kérés el sem ment, vagy a Számlázz.hu elutasította
duplicate Ez a rendelésszám vagy callId már létezik
partial_success A számla elkészült, csak az e-mail nem ment ki. Ne állítsd ki újra!
not_found Nincs ilyen bizonylat
auth / account Rossz kulcs, lejárt előfizetés
network / timeout / maintenance Átmeneti hiba
rate_limit A tesztfiókban túl sok bizonylat készült rövid idő alatt (167)
attempt_limit Ezt a kérést már ötször sikertelenül küldték el, ezért a kassza el sem küldi
in_progress Egy másik folyamat éppen ugyanezt a bizonylatot állítja ki (a createOnce zárja)
store_unavailable Egy kötelezőnek beállított tároló (zár, napló) nem érhető el, a kérés el sem ment

Minden ismert hibakódnak saját oldala van; a hiba docsUrl mezője oda mutat, így a naplóból egy kattintás.

📖 Dokumentáció: Hibakezelés, hibakódok  ·  ▶️ Sandbox: Validációs hibák

Pontosan egyszer · invoices.createOnce(), receipts.createOnce()
const { number, created } = await kassza.invoices.createOnce({
  orderNumber: 'REND-1001',
  paid: true,
  buyer,
  items,
})

Kiállítás előtt megkeresi a számlát, hálózati hiba, időtúllépés vagy 56-os hiba után pedig visszakeresi. Ha a webhook kétszer fut le, a második hívás created: false eredménnyel a meglévő számlát adja. Az egyszerre érkező, azonos rendelésre szóló hívásokat a kassza összevonja; több szerver vagy serverless példány között a createOnceLock közös tároló zárja véd a dupla számla ellen:

import { upstashRedisStore } from 'kassza/stores'

const store = upstashRedisStore(Redis.fromEnv())
const kassza = createKassza({ cookieStore: store, attemptLedger: store, createOnceLock: store })

Az attemptLedger a folyamatok között is betartja az öt próbálkozásos korlátot, atomikus számlálóval.

📖 Dokumentáció: Pontosan egyszer  ·  ▶️ Sandbox: Pénztári nyugta, dupla gombnyomás

Számlát a kassza soha nem küld újra. Újraküldés csak ott történik magától, ahol biztonságos: lekérdezéseknél, hálózati hibánál, legfeljebb 5-ször. A Számlázz.hu kitiltja azt, aki ciklusban próbálkozik. Bizonytalan hiba után a find({ orderNumber }) megmondja, elkészült-e a számla, a createOnce() pedig ezt el is végzi helyetted.

Dokumentáció: Hibakezelés, hibakódok Futtasd a sandboxban: Idempotens számlázás hiba után Recept: Fizetett rendelés számlája

Fizetési értesítés (IPN)

A Számlázz.hu értesít, ha egy számlát kifizettek.

Next.js route handler · readIpnNotification()
import { ipnOkResponse, readIpnNotification } from 'kassza/ipn'

export async function POST(request: Request) {
  const ipn = await readIpnNotification(request)

  if (ipn.isFullyPaid) await rendelesFizetve(ipn.orderNumber, ipn.paidAmount)

  return ipnOkResponse()
}

📖 Dokumentáció: IPN fizetési értesítés  ·  ▶️ Sandbox: IPN fizetési értesítés

Csak a Számlázz.hu IP-címeiről · isSzamlazzIp()

Csak a Számlázz.hu IP-címeiről jövő kérést érdemes elfogadni:

import { isSzamlazzIp } from 'kassza/ipn'

isSzamlazzIp(request.headers.get('x-forwarded-for'))

Az x-forwarded-for fejlécből a jobb szélső címet vizsgálja, vagyis azt, amit a hozzád legközelebbi proxy látott, mert a fejléc bal oldalát a kliens is írhatja. Ha több megbízható proxy van előtted, add meg a számukat: isSzamlazzIp(fejlec, { trustedProxies: 1 }).

📖 Dokumentáció: IPN fizetési értesítés

Dokumentáció: IPN fizetési értesítés Futtasd a sandboxban: IPN fizetési értesítés Recept: IPN webhook

Fizetésből bizonylat

Stripe, SimplePay, Barion, Revolut vagy PayPal fizetésből nyugta vagy számla, a szolgáltató SDK-ja nélkül. A webhookkezelő ellenőrzi az aláírást, az issueForPayment() pedig eldönti, hogy nyugta vagy számla jár, és pontosan egyszer kiállítja.

Stripe webhook · stripeWebhook(), issueForPayment()
import { stripeWebhook } from 'kassza/payments/stripe'

export const POST = stripeWebhook({
  secret: process.env.STRIPE_WEBHOOK_SECRET!,
  apiKey: process.env.STRIPE_SECRET_KEY,
  onPayment: (payment) => kassza.issueForPayment(payment, { vat: 27 }),
})
  • Az újraküldött webhook nem állít ki második bizonylatot; a dedupe: store opcióval a már feldolgozott eseményt a Számla Agent hívása nélkül nyugtázza.
  • Teljes visszatérítéskor a kassza sztornózza a bizonylatot.
  • Részleges visszatérítéskor számlánál visszatérítésenként egy helyesbítő számlát állít ki, a visszatérített összeget tételenként pontosan szétosztva; több áfakulcsnál és nyugtánál javaslatot ad.
  • Ugyanígy működik a simplePayWebhook, a barionWebhook, a revolutWebhook és a payPalWebhook.

📖 Dokumentáció: Fizetésből bizonylat

Dokumentáció: Fizetésből bizonylat Recept: Stripe webhook

NAV nyugta-adatszolgáltatás

  1. szeptember 1-jétől a számítógéppel előállított nyugtákról is napi összesítőt kell küldeni a NAV-nak. A Számlázz.hu a nála kiállított nyugtákat a NAV összekötés után maga jelenti, a kassza abban segít, hogy ellenőrizd: minden napod megérkezett.
Napi összesítő és egyeztetés · navDailyReports(), reconcileNavReports()
import { createNavReceiptClient, reconcileNavReports } from 'kassza/nav'
import { navDailyReports } from 'kassza/reports'

const nav = createNavReceiptClient({
  environment: 'production',
  login: process.env.NAV_LOGIN!,
  password: process.env.NAV_PASSWORD!,
  signatureKey: process.env.NAV_SIGNATURE_KEY!,
  taxNumber: process.env.NAV_TAX_NUMBER!,
})

const helyi = navDailyReports(nyugtak)
const nalNav = await nav.listAllReports({ from: '2026-09-01', to: '2026-09-30' })
const { missing, mismatched } = reconcileNavReports(helyi, nalNav)

A NAV kliens alapból csak olvas: a Számlázz.hu által jelentett nyugtákat ne küldd be te is, mert az kettős adatszolgáltatás. Beküldeni csak a kézi tartalék nyugtatömb összesítőjét kell (paperReceiptReport()).

📖 Dokumentáció: NAV nyugta-adatszolgáltatás

Dokumentáció: NAV nyugta-adatszolgáltatás

Bizonylatnapló

A NAV napi összesítő és a napi zárás a saját nyilvántartásodból számol, mert a Számla Agent nem listáz nyugtákat dátum szerint. A kassza/journal ezt a nyilvántartást adja.

Napló a NAV összesítőhöz · createJournal(), kvJournal()
import { createJournal, kvJournal } from 'kassza/journal'
import { navDailyReports } from 'kassza/reports'

const journal = createJournal(kvJournal(store))
const kassza = createKassza({
  hooks: { onDocument: (event) => journal.record(event), onDocumentError: 'throw' },
})

const jelentesek = navDailyReports(await journal.receipts({ from: '2026-10-01', to: '2026-10-31' }))
  • A trackReceipt() és a trackInvoice() a kiállítás előtt befejezetlen tételt rögzít; ha a folyamat közben leáll, a settle() később visszakeresi és lezárja.
  • A reconcile() az adatkapcsolat napi nyugtaarchívumával egyeztet, és pótolja a hiányzó tételeket.

📖 Dokumentáció: Bizonylatnapló

Dokumentáció: Mi a teendő december 31. előtt?

Megbízotti számlázás

Platformoknak, amelyek sok cég nevében állítanak ki bizonylatot, a cégek saját Számlázz.hu fiókjában.

Csatlakozás és kliens megbízónként · connectPrincipal(), createKasszaPool()
import { connectPrincipal, createKasszaPool } from 'kassza/delegation'

const { status } = await connectPrincipal({
  principal: {
    name: 'Példa Kft.',
    taxNumber: '12345676-2-42',
    invoicePrefix: 'PLDA',
    zip: '1111',
    city: 'Budapest',
    address: 'Fő utca 1.',
    email: 'penzugy@pelda.hu',
  },
  user: { email: 'kassza+pelda@platform.hu', password: process.env.DELEGATE_PASSWORD!, firstName: 'Platform' },
})

const pool = createKasszaPool({ resolve: (megbizoId) => megbizoAdatai(megbizoId) })
const kliens = await pool.get('pelda')
await kliens.invoices.createOnce({ orderNumber: 'FOGLALAS-881', buyer, items })

A megbízó e-mailt kap, és a fiók birtokba vétele vagy a csatlakozási kérelem elfogadása után lehet a nevében kiállítani.

📖 Dokumentáció: Megbízotti számlázás

Dokumentáció: Megbízotti számlázás

Pénzügyi adatkapcsolat

Könyvelő- és ERP-rendszereknek: a Számlázz.hu átküldi a kiállított és befogadott számlákat, a banki tranzakciókat és a nyugtákat.

Fogadó végpont · dataLinkHandler()
import { dataLinkHandler } from 'kassza/data-link'

export const POST = dataLinkHandler({
  verifyKey: async (kulcs) => (await ugyfelKulcsai()).includes(kulcs),
  onPush: async (push) => {
    const iktatoszam = await bizonylatMentese(push)
    return { registrationNumber: iktatoszam }
  },
})

A kulcs ellenőrzése kötelező, mert az üzeneteknek nincs aláírása. A Számlázz.hu által elvárt válasz XML-t a kezelő készíti el.

📖 Dokumentáció: Pénzügyi adatkapcsolat

Dokumentáció: Pénzügyi adatkapcsolat

PDF mentése tárhelyre

S3, Cloudflare R2, MinIO vagy Backblaze esetén nem kell az AWS SDK.

S3 és Cloudflare R2 · s3FetchStorage(), storePdf()
import { invoicePdfKey, s3FetchStorage, storePdf } from 'kassza/storage'

const tarhely = s3FetchStorage({
  bucket: 'szamlak',
  region: 'auto',
  endpoint: 'https://<account-id>.r2.cloudflarestorage.com',
  accessKeyId: process.env.R2_ACCESS_KEY_ID!,
  secretAccessKey: process.env.R2_SECRET_ACCESS_KEY!,
})

const szamla = await kassza.invoices.create(input)
const fajl = await storePdf(tarhely, invoicePdfKey({ number: szamla.number }), szamla.pdf!)

fajl.key

A kulcs például szamlak/2026/09/E-WEB-2026-12.pdf lesz.

📖 Dokumentáció: PDF tárhely  ·  ▶️ Sandbox: PDF mentése tárhelyre

Fájlrendszer (Node) · fsStorage()
import { fsStorage } from 'kassza/storage/fs'

const tarhely = fsStorage({ directory: './szamlak' })

📖 Dokumentáció: PDF tárhely

További adapterek: s3Storage (AWS SDK), r2BindingStorage, vercelBlobStorage, uploadthingStorage, supabaseStorage, memoryStorage.

Dokumentáció: PDF tárhely Futtasd a sandboxban: PDF mentése tárhelyre Recept: PDF mentése S3-ba vagy R2-be

Serverless és edge

A session cookie újrahasznosítása gyorsítja a hívásokat. Serverless környezetben tedd közös tárolóba.

Upstash Redis · upstashRedisStore()
import { Redis } from '@upstash/redis'
import { upstashRedisStore } from 'kassza/stores'

const kassza = createKassza({ cookieStore: upstashRedisStore(Redis.fromEnv()) })

📖 Dokumentáció: Munkamenet (session cookie)  ·  ▶️ Sandbox: Közös session több kliens között

Cloudflare Workers · cloudflareKvStore(), durableObjectStore()
import { cloudflareKvStore } from 'kassza/stores'

const kassza = createKassza({ agentKey: env.SZAMLAZZ_AGENT_KEY, cookieStore: cloudflareKvStore(env.KASSZA_KV) })

A KV munkamenetnek jó, de nincs benne atomikus írás: a createOnce zárjához és a naplóhoz Workers alatt a durableObjectStore() kell.

📖 Dokumentáció: Serverless és edge

Van még ioredisStore, nodeRedisStore és customStore is (a régi kassza/cookie-stores nevek is működnek). A diagnoseStore(store) megmondja, mire alkalmas egy tároló. Ha a tároló elérhetetlen, a számlázás attól még működik.

A csomag minden futtatókörnyezetben ugyanazt adja: a CI a buildelt csomagot Node.js, Bun, Deno és Cloudflare workerd alatt is lefuttatja.

Dokumentáció: Serverless és edge Futtasd a sandboxban: Közös session több kliens között Recept: Cloudflare Workers

Tesztelés

A mock kliens valódi API-hívás nélkül működik, de ugyanazt a validációt és kerekítést futtatja, mint az éles kliens.

Vitest példa · createMockKassza()
import { createMockKassza } from 'kassza/testing'

test('fizetés után számlát állít ki', async () => {
  const kassza = createMockKassza()

  await fizetesKezelo(rendeles, kassza)

  expect(kassza.calls.map((call) => call.method)).toEqual(['invoices.create'])
  expect([...kassza.invoiceRecords.values()][0]?.details.totals.grossAmount).toBe(12_700)
})

test('hálózati hibánál nem számláz kétszer', async () => {
  const kassza = createMockKassza()
  kassza.failNext('invoices.create')

  await expect(fizetesKezelo(rendeles, kassza)).rejects.toThrow()
})

📖 Dokumentáció: Tesztelés  ·  ▶️ Sandbox: Mock kliens tesztekhez

Hamis Számla Agent · createFakeAgentFetch()
import { createFakeAgentFetch } from 'kassza/testing'

const agent = createFakeAgentFetch()
const kassza = createKassza({ agentKey: 'teszt-kulcs', fetch: agent.fetch, retryDelayMs: 0 })

agent.fail('ghostSuccess', { action: 'createInvoice' })
const eredmeny = await kassza.invoices.createOnce({ orderNumber: 'WEB-1', buyer, items })

eredmeny.created
agent.invoices.size

A valódi kliens fut, csak a Számlázz.hu helyett egy memóriában futó hamis Agent válaszol. Elveszett választ, karbantartást, részleges sikert és a Számlázz.hu hibakódjait is szimulálja.

📖 Dokumentáció: Hamis Számla Agent

Dokumentáció: Tesztelés Futtasd a sandboxban: Mock kliens tesztekhez Recept: Egységtesztek

Validátorok és pénzszámítás

Magyar adószám, bankszámla, IBAN, EU adószám és cím ellenőrzése űrlapokhoz, és ugyanaz a kerekítés, amit a számlák is használnak.

Validátorok · kassza/validators
import {
  isValidHungarianBankAccount,
  isValidHungarianTaxNumber,
  parseHungarianAddress,
} from 'kassza/validators'

isValidHungarianTaxNumber('13421739-2-41')
isValidHungarianBankAccount('11773016-11111018')
parseHungarianAddress('1031 Budapest, Záhony utca 7.')

A parseHungarianAddress eredménye { zip: '1031', city: 'Budapest', address: 'Záhony utca 7.' }. Ezen kívül van isValidHungarianIban, isValidHungarianZipCode, isValidEuVatNumber és isValidEmail is.

📖 Dokumentáció: Validátorok  ·  ▶️ Sandbox: Validátorok

Pénzszámítás · kassza/money
import { calculateInvoiceItem, calculateReceiptItem } from 'kassza/money'

calculateInvoiceItem({ quantity: 3, grossUnitPrice: 500, vat: 27 })
calculateReceiptItem({ grossUnitPrice: 1_000, vat: 27 })

Az első eredménye { netAmount: 1181, vatAmount: 319, grossAmount: 1500, ... }, a másodiké { netAmount: 787.4, vatAmount: 212.6, grossAmount: 1000, ... }.

📖 Dokumentáció: Pénzszámítás  ·  ▶️ Sandbox: Kerekítés és összegzés

Dokumentáció: Kiegészítők Futtasd a sandboxban: Validátorok

Haladó beállítások

Időkorlát, újrapróbálás a lekérdezéseknél, naplózás hookokkal és megszakítás AbortSignal-lal.

Időkorlát, újrapróbálás és hookok · timeoutMs, maxAttempts, hooks
const kassza = createKassza({
  timeoutMs: 30_000,
  maxAttempts: 3,
  hooks: {
    onResponse: ({ action, status, durationMs }) => logger.info({ action, status, durationMs }),
    onError: ({ action, error, willRetry }) => logger.warn({ action, code: error.code, willRetry }),
  },
})

await kassza.invoices.getPdf('E-WEB-2026-12', { signal: AbortSignal.timeout(5_000) })
  • A maxAttempts csak a lekérdezésekre vonatkozik, és legfeljebb 5 lehet.
  • A hookok soha nem kapják meg az Agent kulcsot.
  • Minden metódus fogad AbortSignal-t.

📖 Dokumentáció: Hálózat és biztonság  ·  ▶️ Sandbox: Hookok és újrapróbálás

Új session kérése · resetSession()

A resetSession() új sessiont kér. Hívd meg, ha a Számlázz.hu fiókban megváltoztak a cégadatok:

await kassza.resetSession()

📖 Dokumentáció: Munkamenet (session cookie)  ·  ▶️ Sandbox: Közös session több kliens között

Bizonylat-események és karbantartási szünet · onDocument, maintenanceCooldownMs
const kassza = createKassza({
  maintenanceCooldownMs: 60_000,
  hooks: {
    onDocument: async (esemeny) => {
      await auditNaplo(esemeny.kind, esemeny.action, esemeny.number)
    },
  },
})
  • Az onDocument minden kiállított és sztornózott bizonylat, valamint rögzített befizetés után lefut. Ha hibát dob, a bizonylat attól még elkészült; az onDocumentError: 'throw' beállítással ilyenkor DocumentHookError jön, benne a bizonylattal.
  • Az onWarning megkapja a korábban csendben elnyelt hibákat (tároló, hook, zár).
  • A maintenanceCooldownMs karbantartási hiba után ennyi ideig nem küld kérést, hanem azonnal maintenance hibát ad, így átválthatsz tartalék folyamatra.

📖 Dokumentáció: Pontosan egyszer

Dokumentáció: Hálózat és biztonság Futtasd a sandboxban: Hookok és újrapróbálás

Megfigyelhetőség

A kassza nem küld haza semmit. A saját rendszeredben a kassza/observe ad strukturált naplót, OpenTelemetry-kompatibilis tracinget és Prometheus metrikákat, függőség nélkül és titokmentesen.

Napló, tracing, metrikák · observe(), createMetricsRegistry()
import { combineHooks, createMetricsRegistry, observe } from 'kassza/observe'

const metrics = createMetricsRegistry()
const kassza = createKassza({ hooks: combineHooks(observe({ logger: console, metrics }), sajatHookok) })

metrics.renderPrometheus()

📖 Dokumentáció: Megfigyelhetőség

Tömeges és ismétlődő számlázás

Havidíj, tagdíj, bérleti díj: a kassza/batch idempotens kulcsokkal, sebességkorláttal és próbafuttatással állítja ki a bizonylatokat, és a Számlázz.hu korlátjánál megáll.

Havi számlázás · runBatch(), billingPeriodAt()
import { billingPeriodAt, runBatch } from 'kassza/batch'

const idoszak = billingPeriodAt({ interval: 'month', anchor: '2026-01-31' }, new Date())
const eredmeny = await runBatch(kassza, {
  items: elofizetesek.map((elofizetes) => ({
    key: `SUB-${elofizetes.id}-${idoszak.start}`,
    document: () => ({ kind: 'invoice', input: szamlaElofizetesbol(elofizetes, idoszak) }),
  })),
  dryRun: false,
})

Egy megszakadt futás újraindítva nem állít ki duplát. A hónap végi kezdőnapot csúszás nélkül kezeli.

📖 Dokumentáció: Tömeges és ismétlődő számlázás

Node.js és Express

A webhook-kezelők Web-szabványos (Request) => Response függvények. Express, NestJS és Fastify alá a kassza/node köti be őket, a nyers törzs (aláírás!) megőrzésével.

Express · toNodeHandler()
import { toNodeHandler } from 'kassza/node'
import { stripeWebhook } from 'kassza/payments/stripe'

app.post('/webhooks/stripe', toNodeHandler(stripeWebhook({ secret, onPayment })))
app.use(express.json())

A webhook útvonal az express.json() elé kerüljön; ha egy middleware már feldolgozta a törzset, a kassza érthető hibát ad.

📖 Dokumentáció: Node.js, Express, NestJS

Parancssor és MCP szerver

Parancssor · npx kassza
npx kassza doctor
npx kassza xml preview szamla.json
npx kassza invoice get --order REND-1001

A doctor ellenőrzi a Node.js-t, az Agent kulcsot, a gép óráját és a munkamenetet; a --capabilities az e-számla engedélyt, a --report titokmentes Markdown jelentést ad hibajegyhez. Az xml preview kiírja a küldendő XML-t az Agent kulcs nélkül, így supportjegyhez is csatolható.

📖 Dokumentáció: Parancssor

MCP szerver · npx kassza mcp
{
  "mcpServers": {
    "kassza": {
      "command": "npx",
      "args": ["-y", "kassza", "mcp"],
      "env": { "SZAMLAZZ_AGENT_KEY": "..." }
    }
  }
}

Claude, Cursor és más MCP kliensek számára. Alapból csak olvas. Az --allow-write kapcsolóval kiállíthat és sztornózhat is, de minden íráshoz kell a megfelelő előnézeti eszköz megerősítő kódja.

📖 Dokumentáció: MCP szerver

Dokumentáció: Parancssor

AI-val kódolsz?

A csomagban van egy agents/ mappa. Ebből a Claude Code, a Cursor, a Copilot és a többi asszisztens megtudja, hogyan kell jól használni a kasszát, és mik a buktatók. Szólj rá az AI-ra:

Használd a kassza csomagot, és előbb olvasd el a node_modules/kassza/agents/README.md-t.

Claude Code-hoz kész skill is van: másold a node_modules/kassza/agents/skills/kassza mappát a projekted .claude/skills/ mappájába.

A weboldal is AI-barát: az llms.txt a dokumentáció tartalomjegyzéke, az llms-full.txt a teljes dokumentáció egy fájlban, és minden oldal Markdownként is elérhető, ha az URL végére .md kerül.

Dokumentáció: AI asszisztensek

Ki használja?

A kassza nem küld semmilyen használati adatot, ezért csak az derül ki, ki használja, aki maga jelzi. Ha éles vagy kísérleti projektben használod, írd meg egy issue-ban, és felkerülsz ide.

Projekt Mire használja
Légy te az első.

Weboldal · Dokumentáció · Sandbox · Receptek · npm · Változásnapló

Nem hivatalos csomag, nem kapcsolódik a KBOSS.hu Kft.-hez (Számlázz.hu). A hivatalos dokumentáció a docs.szamlazz.hu oldalon érhető el. MIT licenc.

About

Számlázz.hu, TypeScriptben, egyszerűbben. Nem hivatalos TypeScript wrapper a Számlázz.hu Számla Agenthez. Mind a 11 Agent művelet, 0 függőség, nulla runtime kompromisszum.

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages