Ugrás a tartalomra
kassza
ÚJ11 kész recept: Stripe, IPN, Workers

A Számlázz.hu Agent XML-t vár. Te írj TypeScriptet.

A kassza nem hivatalos TypeScript wrapper a Számlázz.hu Számla Agenthez. A Számlázz.hu XML-t vár; te típusos objektumot adsz át, a kassza pedig elkészíti a helyes kérést.

npm i kassza

v0.9.0 · MIT licenc · nem hivatalos

szamla.ts
import { createKassza } from 'kassza'

const kassza = createKassza()

const szamla = await kassza.invoices.create({
  orderNumber: 'REND-1001',
  paid: true,
  paymentMethod: 'bankkártya',
  buyer: {
    name: 'Nagy Péter',
    zip: '1111',
    city: 'Budapest',
    address: 'Fő utca 1.',
    email: 'peter@example.hu',
  },
  items: [{
    name: 'Póló',
    quantity: 3,
    grossUnitPrice: 5_990,
    vat: 27,
  }],
})

console.log(szamla.grossTotal)

A számla összegeit a kassza hivatalos kerekítése adja, pont úgy, ahogy a Számlázz.hu ellenőrzi. Mutasd az XML-t

Egy számla útja, a kódodtól a vevő postafiókjáig.

A zöld doboz a kassza. Ami benne történik, azt a nyers Agent API mellett neked kellene megírnod, tesztelned és karbantartanod.

Egy számla útja a kódodtól a vevőigA kódod egy objektumot ad át a kasszának. A kassza validál, kerekít, az XSD sorrendjében felépíti az XML-t, és magyar idő szerint tölti ki a dátumokat, majd multipart POST kérésben, a session cookie-val együtt elküldi a Számla Agentnek. A Számlázz.hu kiállítja a számlát, és XML választ meg PDF-et küld vissza, amiből a kódod CreatedInvoice eredményt vagy SzamlazzError hibát kap. A vevő e-mailben megkapja a számlát. Fizetés után a Számlázz.hu IPN értesítést küld a szerverednek.IPN értesítés fizetéskorA kódodinvoices.create()objektumeredménykasszavalidációkerekítés tételenkéntXML az XSD sorrendjébendátum: Europe/BudapestPOST · XMLJSESSIONIDXML + PDFSzámlázz.huSzámla Agent: kiállítja a számláte-mailA vevőe-mailben megkapja a számlát
A szaggatott vonal később jön: amikor a vevő fizet, a Számlázz.hu értesíti a szerveredet, a kassza/ipn pedig feldolgozza.

Ugyanaz a számla, két nyelven.

Egyik oldalon az XML, amelyet a kassza a fenti hívásból ténylegesen előállít és elküld a Számla Agentnek, a másikon az, amit ehhez te írsz. A sorrendet, a dátumokat és a kerekített összegeket a kassza tölti ki.

  1. Beállítások

    Az Agent kulcs a SZAMLAZZ_AGENT_KEY környezeti változóból jön. Az e-számla, a PDF letöltés és a válaszverzió alapértéket kap.

    Amit a Számla Agent vár

    <beallitasok>
      <szamlaagentkulcs>a-te-agent-kulcsod</szamlaagentkulcs>
      <eszamla>false</eszamla>
      <szamlaLetoltes>true</szamlaLetoltes>
      <valaszVerzio>2</valaszVerzio>
    </beallitasok>

    Amit te írsz

    const kassza = createKassza()
  2. Fejléc

    A három dátum a mai nap, Europe/Budapest szerint. A toISOString() éjfél és hajnali kettő között még tegnapot adna, abból 352-es hiba lesz.

    Amit a Számla Agent vár

    <fejlec>
      <keltDatum>2026-09-19</keltDatum>
      <teljesitesDatum>2026-09-19</teljesitesDatum>
      <fizetesiHataridoDatum>2026-09-19</fizetesiHataridoDatum>
      <fizmod>bankkártya</fizmod>
      <penznem>HUF</penznem>
      <szamlaNyelve>hu</szamlaNyelve>
      <rendelesSzam>REND-1001</rendelesSzam>
      <fizetve>true</fizetve>
    </fejlec>

    Amit te írsz

    await kassza.invoices.create({
      orderNumber: 'REND-1001',
      paid: true,
      paymentMethod: 'bankkártya',
  3. Vevő

    A sendEmail azért true, mert a vevőnek van e-mail címe: a Számlázz.hu el is küldi neki a számlát.

    Amit a Számla Agent vár

    <vevo>
      <nev>Nagy Péter</nev>
      <irsz>1111</irsz>
      <telepules>Budapest</telepules>
      <cim>Fő utca 1.</cim>
      <email>peter@example.hu</email>
      <sendEmail>true</sendEmail>
    </vevo>

    Amit te írsz

      buyer: {
        name: 'Nagy Péter',
        zip: '1111',
        city: 'Budapest',
        address: 'Fő utca 1.',
        email: 'peter@example.hu',
      },
  4. Tételek

    A kiemelt négy számot a kassza számolta ki a bruttó egységárból, a hivatalos bruttó alapú kerekítéssel. A nyers API-nál ez a te dolgod.

    Amit a Számla Agent vár

    <tetelek>
      <tetel>
        <megnevezes>Póló</megnevezes>
        <mennyiseg>3</mennyiseg>
        <mennyisegiEgyseg>db</mennyisegiEgyseg>
        <nettoEgysegar>4716.67</nettoEgysegar>
        <afakulcs>27</afakulcs>
        <nettoErtek>14150</nettoErtek>
        <afaErtek>3820</afaErtek>
        <bruttoErtek>17970</bruttoErtek>
      </tetel>
    </tetelek>

    Amit te írsz

      items: [
        {
          name: 'Póló',
          quantity: 3,
          grossUnitPrice: 5_990,
          vat: 27,
        },
      ],
    })

Négy buktató, amit a kassza helyetted kezel.

Mindegyikbe belefut, aki a nyers Agent API-t hívja. A lenti összegeket és hibakódokat nem kézzel írtuk be: a kassza számolta ki és olvasta ki őket, amikor ez az oldal elkészült.

Egy forint eltérés, és a számla nem készül el.

Forintos számlán a tétel nettó értéke, áfája és bruttó értéke is egész szám, és a Számlázz.hu ellenőrzi, hogy összeillenek-e. Ha a visszaszámolt nettóból számolod az áfát, 3 darab 5990 Ft-os pólónál 17 971 Ft jön ki 17 970 helyett, és a válasz a 259–264-es hibakódok egyike. A kassza a hivatalos nettó vagy bruttó alapú szabállyal számol, tételenként.

3 × 5990 Ft bruttó, 27% áfa: 17 971 Ft kézzel, 17 970 Ft a kasszávalHa a nettót a bruttóból számolod vissza és abból az áfát, 14 150 Ft nettó és 3821 Ft áfa jön ki, összesen 17 971 Ft. A hivatalos bruttó alapú kerekítéssel az áfa 3820 Ft, a nettó 14 150 Ft, összesen 17 970 Ft, pontosan annyi, amennyit a vevő fizet.Nettóból visszaszámolvanettóáfa17 971 Ft14 150 + 3821Bruttó alapú, hivatalos szabálynettóáfa17 970 Ft14 150 + 3820a bruttó vége, nagyítva+1 Ftkasszakézi17 96817 96917 97017 97117 972

Számold ki te is

Ez ugyanaz a kassza/money kód, amely a számla tételeit kerekíti. Írd át az árat, a mennyiséget vagy az áfakulcsot.

Bizonylat
Az ár alapja
Pénznem
Nettó egységár
4716,67 Ft
Nettó érték
14 150 Ft
Áfa
3820 Ft
Bruttó érték
17 970 Ft
calculateInvoiceItem({ quantity: 3, grossUnitPrice: 5990, vat: 27 })

Időtúllépés után sem lesz két számla.

Hálózati hiba vagy időtúllépés után nem tudod, elkészült-e a számla. Ha újraküldöd, kettő lehet belőle, ciklusban próbálkozva pedig a Számlázz.hu ki is tilthat.

A kassza ezért csak a lekérdezéseket próbálja újra magától: alapból háromszor, 1 és 2 másodperc várakozással. Számlát soha nem küld újra. Te a rendelésszámmal megnézed, megvan-e, és csak akkor állítod ki, ha nincs.

Újrapróbálás: lekérdezést igen, számlát sohaEgy lekérdezés, például az invoices.getPdf(), hálózati hiba után 1, majd 2 másodperc várakozással újra próbálkozik, a harmadik próbára megjön a PDF. Az invoices.create() időtúllépés után nem küldi újra a kérést, hanem SzamlazzError hibát dob timeout kategóriával. Ezután az invoices.find a rendelésszámmal megmondja, elkészült-e a számla: ha megvan, nem állítod ki újra, ha null, most már kiállíthatod.Lekérdezés: magától újrapróbáljainvoices.getPdf()vár 1 svár 2 s1. próbahálózati hiba2. próbahálózati hiba3. próbamegjött a PDFSzámla kiállítása: soha nem küldi újrainvoices.create()időtúllépéselkészült?SzamlazzError · 'timeout'invoices.find({ orderNumber })megvannem állítod ki újranullmost már kiállíthatod

Háromféle hibaformátum helyett egy.

A Számla Agent a hibát hol HTTP fejlécben, hol XML-ben, hol [ERR] kezdetű szövegben adja vissza. A kasszában mindből SzamlazzError lesz, a Számlázz.hu hibakódjával, kategóriával és magyar javítási tippel.

Három hibaformátum, egy SzamlazzErrorA Számla Agent a hibát HTTP fejlécben (szlahu_error_code), XML válaszban (hibakod elem) vagy [ERR] kezdetű szövegben adja vissza. A kassza mindhármat ugyanarra a SzamlazzError típusra alakítja.HTTP fejlécszlahu_error_code: 57XML válasz<hibakod>57</hibakod>szöveges válasz[ERR] 57 XML beolvasási…SzamlazzErroregyetlen típus
Az 57-es hiba, ahogy a kódod megkapja:
error.code
57
error.category
'validation'
error.message
'[57] XML beolvasási hiba.'
error.hint
'A küldött XML nem felel meg az XSD-nek. A részleteket a hibaüzenet tartalmazza.'

Session cookie, serverlessen is.

A Számla Agent session cookie-val gyorsít: ha nem küldöd vissza, minden kérés újra végigmegy a hitelesítésen. A kassza eltárolja és visszaküldi, serverless környezetben pedig Redisben vagy Cloudflare KV-ben osztja meg a példányok között. A Számlázz.hu 90 perc tétlenség után törli, a következő kérés ilyenkor újat nyit.

Session cookie újrahasznosításaAz első kérés új sessiont nyit, a kassza a cookie-t eltárolja memóriában, Redisben vagy Cloudflare KV-ben. A következő kérések visszaküldik, így nincs új hitelesítés. 90 perc tétlenség után a Számlázz.hu törli a sessiont, ekkor a következő kérés újat nyit.cookieStore memóriában, Redisben vagy KV-ben90 perc tétlenség1. kérésúj sessioncookie visszaküldvenincs új hitelesítéslejárt: új sessiona kassza intézi

Négy lépés, és élesben számlázol.

Telepítés, Agent kulcs, első számla, hibakezelés. Minden lépés mellett ott a kód, amit be is másolhatsz.

  1. 1. lépés: Telepítsd

    Egyetlen csomag, futásidejű függőség nélkül. Node.js 22 vagy újabb kell hozzá, de Bunon, Denón, Cloudflare Workersen és Vercel Edge-en is ugyanígy fut.

    Telepítés részletesen
    npm i kassza
  2. 2. lépés: Add meg az Agent kulcsot

    A kulcsot a Számlázz.hu felületén, a vezérlőpult alján hozod létre. Titok, csak kisbetűs lehet, és csak a szerveren a helye. A verifyCredentials() egy ártalmatlan lekérdezéssel ellenőrzi.

    Hitelesítés
    .env
    SZAMLAZZ_AGENT_KEY=a-te-agent-kulcsod
    kassza.ts
    import { createKassza } from 'kassza'
    
    export const kassza = createKassza()
    
    const ervenyes = await kassza.verifyCredentials()
  3. 3. lépés: Állítsd ki az első számlát

    Nettó egységár B2B-hez, bruttó B2C-hez. Az orderNumber a saját azonosítód, ezzel később visszakeresed a számlát. A szamla.grossTotal itt 190 500 Ft lesz.

    Számla létrehozása
    szamla.ts
    const szamla = await kassza.invoices.create({
      orderNumber: 'REND-1002',
      buyer: {
        name: 'Vevő Kft.',
        zip: '1111',
        city: 'Budapest',
        address: 'Fő utca 1.',
        email: 'vevo@example.hu',
        taxNumber: '12345678-2-42',
      },
      items: [
        { name: 'Webfejlesztés', quantity: 10, unit: 'óra', netUnitPrice: 15_000, vat: 27 },
      ],
    })
    
    szamla.number
    szamla.grossTotal
    szamla.pdf
  4. 4. lépés: Kezeld a hibát és a fizetést

    Bizonytalan hiba után (hálózat, időtúllépés, részleges siker, már létező rendelésszám) a find megmondja, elkészült-e a számla. Ha a vevő fizet, a Számlázz.hu IPN értesítést küld, amit a kassza/ipn egy route handlerben feldolgoz.

    Hibakezelés
    szamlazas.ts
    import { isSzamlazzError } from 'kassza'
    
    const bizonytalan = ['network', 'timeout', 'partial_success', 'duplicate']
    
    try {
      await kassza.invoices.create({ orderNumber: 'REND-1002', buyer, items })
    } catch (error) {
      if (!isSzamlazzError(error)) throw error
      if (!bizonytalan.includes(error.category)) throw error
    
      const meglevo = await kassza.invoices.find({ orderNumber: 'REND-1002' })
      if (!meglevo) throw error
    }
    app/api/szamlazz-ipn/route.ts
    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()
    }

Mind a 11 Agent művelet, egy csomagban.

Számla, díjbekérő, előleg- és végszámla, helyesbítő számla, szállítólevél, nyugta, sztornó, befizetés, PDF, számlaadatok és adószám a NAV-tól. Minden műveletnél megvan a kérés, a válasz és egy minta a kóddal meg a ténylegesen elküldött XML-lel.

Számla Agent műveletek, 11-ből
  • kassza11/11
  • szamlazz.js3/11
  • @ribbery009/szamlazz-ts3/11
  • @halftome/szamlazz-client3/11
  • szamlazz.ts3/11
  • szamlazzhu-client2/11

A publikált csomagok kódjában ellenőrizve, 2026 szeptemberében: melyik Agent műveletet küldik valóban.

Egy csomag, nulla függőség, 5 futtatókörnyezet.

Ugyanaz a kód fut a szervereden, a serverless függvényedben és az edge-en. Amire nincs mindig szükség, az külön modulban van.

Hol fut?

  • Node.js22 vagy újabb
  • Bun
  • Deno
  • Cloudflare Workerssession: KV
  • Vercel Edge Runtimesession: Upstash Redis

Nincs futásidejű függősége, csak szabványos webes API-kat használ: fetch, FormData, Blob, TextEncoder és crypto.

Kiegészítő modulok

Külön importálhatók, és csak akkor kerülnek a bundle-be, ha használod őket.

kassza

  • kassza/testing

    Mock kliens unit tesztekhez, valódi validációval és kerekítéssel.

  • kassza/ipn

    A Számlázz.hu fizetési értesítésének (IPN) feldolgozása.

  • kassza/storage

    PDF mentése S3-ra, R2-re, Vercel Blobra, UploadThingre vagy Supabase-re.

  • kassza/cookie-stores

    Közös session tároló Redishez és Cloudflare KV-hez.

  • kassza/validators

    Adószám, bankszámla, IBAN, EU adószám és magyar cím ellenőrzése.

  • kassza/money

    Ugyanaz a kerekítés és összegzés, külön is használható.

Próbáld ki kulcs nélkül, a böngészőben.

A sandbox egy szimulált Számlázz.hu ellen futtatja a példákat, és megmutatja a pontosan elküldött XML-t. Ha meggyőzött, egy npm i kassza, és jöhet az éles Agent kulcs.