Adószám alapú kitöltés Céges vásárlásnál a vevő beírja az adószámát, és a pénztár oldal kitölti helyette a cégnevet és a székhely címét. Kevesebb elgépelés, és a számlán a NAV-nál nyilvántartott adatok szerepelnek. A lekérdezést a kassza taxpayer.query() metódusa végzi a Számla Agenten keresztül.
A recept egy szerveroldali route handlerből áll, amely az Agent kulccsal lekérdez, és egy kliens komponensből, amely a formátumot már a böngészőben ellenőrzi. A kettő egy közös típuson osztozik.
Közös típus#
A CegAdatok az űrlap és a végpont közös adatszerkezete, a cegesVevo() pedig a mentett adatokból a számla vevőjét készíti el.
lib/ceges-vevo.ts import type { InvoiceBuyer } from 'kassza'
export interface CegAdatok {
readonly nev : string
readonly adoszam : string
readonly iranyitoszam : string
readonly varos : string
readonly cim : string
}
export function cegesVevo (adatok : CegAdatok , email : string ) : InvoiceBuyer {
return {
name : adatok .nev ,
zip : adatok .iranyitoszam ,
city : adatok .varos ,
address : adatok .cim ,
email ,
taxNumber : adatok .adoszam ,
taxpayerType : 'hungarianTaxNumber' ,
}
}
Route handler#
app/api/adoszam/route.ts import { isSzamlazzError } from 'kassza'
import { parseHungarianTaxNumber } from 'kassza/validators'
import { bejelentkezettVevo } from '@/lib/auth'
import type { CegAdatok } from '@/lib/ceges-vevo'
import { kassza } from '@/lib/kassza'
export async function POST (request : Request ) {
if ( ! ( await bejelentkezettVevo (request))) return new Response ( 'Jelentkezz be' , { status : 401 })
const { adoszam } = ( await request .json () .catch (() => ({}))) as { adoszam ?: unknown }
const ervenyes = typeof adoszam === 'string' ? parseHungarianTaxNumber (adoszam) : undefined
if ( ! ervenyes) return Response .json ({ hiba : 'Érvénytelen adószám.' } , { status : 400 })
try {
const ceg = await kassza . taxpayer .query ( ervenyes .formatted)
if ( ! ceg .valid || ! ceg .address) {
return Response .json ({ hiba : 'A NAV nem ismer ilyen érvényes adószámot.' } , { status : 404 })
}
const adatok : CegAdatok = {
nev : ceg .name ?? '' ,
adoszam : ceg . taxNumber ?.formatted ?? ervenyes .formatted ,
iranyitoszam : ceg . address .postalCode ,
varos : ceg . address .city ,
cim : ceg . address . formatted .split ( ', ' ) .slice ( 1 ) .join ( ', ' ) ,
}
return Response .json (adatok)
} catch (error) {
if ( isSzamlazzError (error) && error .retryable) {
return Response .json ({ hiba : 'A NAV lekérdezés most nem elérhető.' } , { status : 503 })
}
throw error
}
}
A formatted cím így néz ki: 1134 Budapest, Váci út 10.. Az első vessző előtti rész az irányítószám és a település, a többi az utca és a házszám.
Kód Elküldött XML Válasz
adoszam.ts import { createKassza , type InvoiceBuyer } from 'kassza'
import { parseHungarianTaxNumber } from 'kassza/validators'
const kassza = createKassza ()
const bevitt = '12345676-2-41'
if ( ! parseHungarianTaxNumber ( bevitt )) throw new Error ( 'Érvénytelen adószám' )
const ceg = await kassza . taxpayer . query ( bevitt )
if ( ceg . valid && ceg . address ) {
const vevo : InvoiceBuyer = {
name : ceg . shortName ?? ceg . name ?? '' ,
zip : ceg . address . postalCode ,
city : ceg . address . city ,
address : ceg . address . formatted . split ( ', ' ) . slice ( 1 ) . join ( ', ' ) ,
taxNumber : ceg . taxNumber ?. formatted ,
}
await kassza . invoices . create ({
buyer : vevo ,
items : [{ name : 'Tanácsadás' , netUnitPrice : 40_000 , vat : 27 }] ,
})
}
await kassza . taxpayer . query ( '87654321' ) 1. Adószám lekérdezés · action-szamla_agent_taxpayer <? xml version = "1.0" encoding = "UTF-8" ?>
< xmltaxpayer xmlns = "http://www.szamlazz.hu/xmltaxpayer" xmlns : xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi : schemaLocation = "http://www.szamlazz.hu/xmltaxpayer http://www.szamlazz.hu/docs/xsds/agent/xmltaxpayer.xsd" >
< beallitasok >
< szamlaagentkulcs >••••••••</ szamlaagentkulcs >
</ beallitasok >
< torzsszam >12345676</ torzsszam >
</ xmltaxpayer >
2. Számla létrehozás · action-xmlagentxmlfile <? xml version = "1.0" encoding = "UTF-8" ?>
< xmlszamla xmlns = "http://www.szamlazz.hu/xmlszamla" xmlns : xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi : schemaLocation = "http://www.szamlazz.hu/xmlszamla https://www.szamlazz.hu/szamla/docs/xsds/agent/xmlszamla.xsd" >
< beallitasok >
< szamlaagentkulcs >••••••••</ szamlaagentkulcs >
< eszamla >false</ eszamla >
< szamlaLetoltes >true</ szamlaLetoltes >
< valaszVerzio >2</ valaszVerzio >
</ beallitasok >
< fejlec >
< keltDatum >2026-10-02</ keltDatum >
< teljesitesDatum >2026-10-02</ teljesitesDatum >
< fizetesiHataridoDatum >2026-10-02</ fizetesiHataridoDatum >
< fizmod >Átutalás</ fizmod >
< penznem >HUF</ penznem >
< szamlaNyelve >hu</ szamlaNyelve >
</ fejlec >
< elado ></ elado >
< vevo >
< nev >MINTA KERESKEDELMI KFT.</ nev >
< irsz >1111</ irsz >
< telepules >Budapest</ telepules >
< cim >Minta utca 1.</ cim >
< sendEmail >false</ sendEmail >
< adoszam >12345676-2-41</ adoszam >
</ vevo >
< tetelek >
< tetel >
< megnevezes >Tanácsadás</ megnevezes >
< mennyiseg >1</ mennyiseg >
< mennyisegiEgyseg >db</ mennyisegiEgyseg >
< nettoEgysegar >40000</ nettoEgysegar >
< afakulcs >27</ afakulcs >
< nettoErtek >40000</ nettoErtek >
< afaErtek >10800</ afaErtek >
< bruttoErtek >50800</ bruttoErtek >
</ tetel >
</ tetelek >
</ xmlszamla >
3. Adószám lekérdezés · action-szamla_agent_taxpayer <? xml version = "1.0" encoding = "UTF-8" ?>
< xmltaxpayer xmlns = "http://www.szamlazz.hu/xmltaxpayer" xmlns : xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi : schemaLocation = "http://www.szamlazz.hu/xmltaxpayer http://www.szamlazz.hu/docs/xsds/agent/xmltaxpayer.xsd" >
< beallitasok >
< szamlaagentkulcs >••••••••</ szamlaagentkulcs >
</ beallitasok >
< torzsszam >87654321</ torzsszam >
</ xmltaxpayer >
1. Adószám lekérdezés · válasz, HTTP 200 content-type: application/xml; charset=UTF-8
set-cookie: JSESSIONID=89F993A08905A5318851946E; Path=/szamla; Secure; HttpOnly
<? xml version = "1.0" encoding = "UTF-8" ?>
< QueryTaxpayerResponse xmlns = "http://schemas.nav.gov.hu/OSA/3.0/api" xmlns : common = "http://schemas.nav.gov.hu/NTCA/1.0/common" xmlns : base = "http://schemas.nav.gov.hu/OSA/3.0/base" >
< common : header >
< common : requestId >KASSZAMUQM27IC</ common : requestId >
< common : timestamp >2026-10-02T06:57:35.364Z</ common : timestamp >
< common : requestVersion >3.0</ common : requestVersion >
< common : headerVersion >1.0</ common : headerVersion >
</ common : header >
< common : result >
< common : funcCode >OK</ common : funcCode >
</ common : result >
< infoDate >2026-10-02T06:57:35.364Z</ infoDate >
< taxpayerValidity >true</ taxpayerValidity >
< taxpayerData >
< taxpayerName >MINTA KERESKEDELMI KORLÁTOLT FELELŐSSÉGŰ TÁRSASÁG</ taxpayerName >
< taxpayerShortName >MINTA KERESKEDELMI KFT.</ taxpayerShortName >
< taxNumberDetail >< base : taxpayerId >12345676</ base : taxpayerId >< base : vatCode >2</ base : vatCode >< base : countyCode >41</ base : countyCode ></ taxNumberDetail >
< incorporation >ORGANIZATION</ incorporation >
< taxpayerAddressList >
< taxpayerAddressItem >
< taxpayerAddressType >HQ</ taxpayerAddressType >
< taxpayerAddress >< base : countryCode >HU</ base : countryCode >< base : postalCode >1111</ base : postalCode >< base : city >BUDAPEST</ base : city >< base : streetName >MINTA</ base : streetName >< base : publicPlaceCategory >UTCA</ base : publicPlaceCategory >< base : number >1</ base : number ></ taxpayerAddress >
</ taxpayerAddressItem >
</ taxpayerAddressList >
</ taxpayerData >
</ QueryTaxpayerResponse >
2. Számla létrehozás · válasz, HTTP 200 content-type: application/xml; charset=UTF-8
szlahu_szamlaszam: KASSZA-2026-1
szlahu_nettovegosszeg: 40000
szlahu_bruttovegosszeg: 50800
szlahu_kintlevoseg: 50800
<? xml version = "1.0" encoding = "UTF-8" ?>
< xmlszamlavalasz xmlns = "http://www.szamlazz.hu/xmlszamlavalasz" >
< sikeres >true</ sikeres >
< szamlaszam >KASSZA-2026-1</ szamlaszam >
< szamlanetto >40000</ szamlanetto >
< szamlabrutto >50800</ szamlabrutto >
< kintlevoseg >50800</ kintlevoseg >
< pdf >JVBERi0xLjQKJeLjz9MKMSAwIG9iago8PCAvVHlwZSAvQ2F0YWxvZyAvUGFnZXMgMiAwIFIgPj4KZW5k… (base64 PDF, rövidítve)</ pdf >
</ xmlszamlavalasz >
3. Adószám lekérdezés · válasz, HTTP 200 content-type: application/xml; charset=UTF-8
<? xml version = "1.0" encoding = "UTF-8" ?>
< QueryTaxpayerResponse xmlns = "http://schemas.nav.gov.hu/OSA/3.0/api" xmlns : common = "http://schemas.nav.gov.hu/NTCA/1.0/common" xmlns : base = "http://schemas.nav.gov.hu/OSA/3.0/base" >
< common : header >
< common : requestId >KASSZAMUQM27IG</ common : requestId >
< common : timestamp >2026-10-02T06:57:35.368Z</ common : timestamp >
< common : requestVersion >3.0</ common : requestVersion >
< common : headerVersion >1.0</ common : headerVersion >
</ common : header >
< common : result >
< common : funcCode >OK</ common : funcCode >
</ common : result >
< infoDate >2026-10-02T06:57:35.368Z</ infoDate >
< taxpayerValidity >false</ taxpayerValidity >
</ QueryTaxpayerResponse >
Kliens komponens#
A kassza/validators modul tiszta függvényekből áll, hálózatot és kulcsot nem használ, ezért a böngészőben is importálható. A kassza fő modult viszont soha ne importáld kliens komponensből.
app/penztar/szamlazasi-adatok.tsx 'use client'
import { isValidHungarianTaxNumber } from 'kassza/validators'
import { type ChangeEvent , useState } from 'react'
import type { CegAdatok } from '@/lib/ceges-vevo'
const URES : CegAdatok = { nev : '' , adoszam : '' , iranyitoszam : '' , varos : '' , cim : '' }
type Eredmeny = CegAdatok | { readonly hiba : string }
async function cegLekerdezese (adoszam : string ) : Promise < Eredmeny > {
try {
const valasz = await fetch ( '/api/adoszam' , {
method : 'POST' ,
headers : { 'content-type' : 'application/json' } ,
body : JSON .stringify ({ adoszam }) ,
})
return ( await valasz .json ()) as Eredmeny
} catch {
return { hiba : 'A lekérdezés nem sikerült.' }
}
}
export function SzamlazasiAdatok () {
const [ adatok , setAdatok ] = useState < CegAdatok >( URES )
const [ uzenet , setUzenet ] = useState ( '' )
const [ tolt , setTolt ] = useState ( false )
const mezo = (nev : keyof CegAdatok ) => ({
name : nev ,
value : adatok[nev] ,
onChange : (esemeny : ChangeEvent < HTMLInputElement >) =>
setAdatok ((elozo) => ({ ... elozo , [nev] : esemeny . target .value })) ,
})
async function kitoltes () {
if ( ! isValidHungarianTaxNumber ( adatok .adoszam)) {
setUzenet ( 'Az adószám formátuma: 12345678-1-42' )
return
}
setTolt ( true )
setUzenet ( '' )
try {
const eredmeny = await cegLekerdezese ( adatok .adoszam)
if ( 'hiba' in eredmeny) {
setUzenet ( ` ${ eredmeny .hiba } Töltsd ki kézzel az adatokat.` )
return
}
setAdatok (eredmeny)
setUzenet ( 'Az adatokat a NAV nyilvántartásából töltöttük ki. Ellenőrizd őket.' )
} finally {
setTolt ( false )
}
}
return (
< fieldset >
< legend >Számlázási adatok</ legend >
< label >
Adószám
< input { ... mezo ( 'adoszam' )} inputMode = "numeric" autoComplete = "off" />
</ label >
< button type = "button" onClick = {kitoltes} disabled = {tolt}>
{tolt ? 'Lekérdezés…' : 'Kitöltés a NAV adataiból' }
</ button >
< p aria-live = "polite" >{uzenet}</ p >
< label >
Cégnév
< input { ... mezo ( 'nev' )} autoComplete = "organization" />
</ label >
< label >
Irányítószám
< input { ... mezo ( 'iranyitoszam' )} autoComplete = "postal-code" />
</ label >
< label >
Település
< input { ... mezo ( 'varos' )} autoComplete = "address-level2" />
</ label >
< label >
Cím
< input { ... mezo ( 'cim' )} autoComplete = "street-address" />
</ label >
</ fieldset >
)
}
A kitöltött mezők szerkeszthetők maradnak. A NAV adatai a székhelyre vonatkoznak, de a vevő kérheti, hogy a számlán más cím szerepeljen.
Buktatók#
Ne legyen nyílt végpont
Minden lekérdezés a te Agent kulcsoddal fut. Védelem nélkül a végpontot bárki használhatná
ingyenes NAV lekérdezőként, és a sok kérés a fiókodra hullik vissza. Csak bejelentkezett vevőnek
engedd, és korlátozd a kérések számát.
Az érvénytelen adószám nem hiba
Ha a NAV nem ismeri az adószámot, vagy az nem érvényes, a query() nem dob hibát, hanem
valid: false értéket ad vissza üres címlistával. Ezt mindig ellenőrizd a mezők használata előtt.
A cégnév nagybetűs lehet
A kassza a település és az utca nevét olvashatóvá alakítja, de a cégnevet úgy adja vissza, ahogy
a NAV tárolja, ez gyakran csupa nagybetű. Ha rövidebb nevet szeretnél, a shortName mező a cég
rövid nevét tartalmazza.
Csak formátumellenőrzés a böngészőben
Az isValidHungarianTaxNumber() a CDV ellenőrzőszámot, az áfakódot és a megyekódot vizsgálja.
Azt, hogy a cég létezik és működik, csak a NAV lekérdezés mondja meg. A query() a 8 jegyű
törzsszámot is elfogadja, a számlára viszont a teljes, 11 jegyű adószám kell.
Csoportos adóalanyok
Ha az adószám áfakódja 4, a cég áfacsoport tagja. Ezt az isHungarianVatGroupMemberTaxNumber()
jelzi. A csoportazonosítót a buyer.groupTaxNumber mezőben adhatod át; hogy kell-e, azt a
könyvelőddel egyeztesd. A részletek a Validátorok oldalon vannak.
Kapcsolódó#