[{"data":1,"prerenderedAt":374},["ShallowReactive",2],{"switcher-blog-pareja":3,"art-verifactu-three-aeat-errors-en":6},{"en":4,"es":5},"\u002Fen\u002Fblog\u002Fverifactu-three-aeat-errors\u002F","\u002Fes\u002Fblog\u002Fverifactu-tres-errores-aeat\u002F",{"id":7,"title":8,"author":9,"body":10,"date":357,"description":358,"extension":359,"image":360,"meta":361,"navigation":362,"pareja":363,"path":364,"seo":365,"sin_cta":366,"stem":367,"tags":368,"__hash__":373},"blogEn\u002Fen\u002Fblog\u002Fverifactu-three-aeat-errors.md","VeriFactu against the Spanish tax agency: the three errors that stopped us, and the fixes","Paco Cubel",{"type":11,"value":12,"toc":346},"minimark",[13,18,27,30,37,41,44,93,96,100,103,114,124,128,131,142,157,160,169,173,176,191,194,228,233,237,240,305,309,312,332,343],[14,15,17],"h2",{"id":16},"why-were-writing-this","Why we're writing this",[19,20,21,22,26],"p",{},"VeriFactu is Spain's new invoicing regime, and it fits in one sentence: every invoice you\nissue leaves a ",[23,24,25],"strong",{},"SHA-256 hash chained to the previous one",", and the system issuing it has\nto identify itself to the tax agency. Sounds simple. The official documentation is several\nPDFs plus a validation catalogue, and the usual path is discovering the rules one at a\ntime, by getting your submissions rejected.",[19,28,29],{},"We implemented it from scratch for our ERP, in Dart, and submitted it to the AEAT\npre-production environment. This article is the list of what blocked us, with the error\nnumber up front, because that's what we wish someone had written down.",[19,31,32,33,36],{},"Honesty note: ",[23,34,35],{},"pre-production is not production",". It's the tax agency's test environment,\nwith no fiscal effect. Everything below was verified there.",[14,38,40],{"id":39},"the-setup-in-four-pieces","The setup, in four pieces",[19,42,43],{},"Before the errors, here's what you need in place:",[45,46,47,59,73,87],"ol",{},[48,49,50,53,54,58],"li",{},[23,51,52],{},"The record"," (",[55,56,57],"code",{},"RegistroAlta","): the invoice as XML, with its VAT breakdown.",[48,60,61,64,65,68,69,72],{},[23,62,63],{},"The hash",": SHA-256 as 64 hex characters ",[23,66,67],{},"in upper case",", computed over specific\nfields in a specific order, and ",[23,70,71],{},"chained"," to the previous invoice's hash. This is what\nmakes it impossible to delete an invoice from the middle without it showing.",[48,74,75,78,79,82,83,86],{},[23,76,77],{},"The submission",": SOAP over ",[23,80,81],{},"mTLS",". The certificate isn't just for encryption, it's\nyour identity. In VeriFactu mode there is ",[23,84,85],{},"no XAdES signature","; authentication comes\nfrom the submission certificate and integrity from the hash chain.",[48,88,89,92],{},[23,90,91],{},"The verification QR code",": the little square printed on the receipt that lets anyone\ncheck the invoice against the tax agency.",[19,94,95],{},"The hash is the scary-looking part and gave us the least trouble: you can validate it\nlocally against known test vectors before talking to anyone. Do that. Arriving with an\nalready-validated hash removes one variable once the rejections start.",[14,97,99],{"id":98},"error-4104-obligadoemisión-tax-id-not-identified","Error 4104 — \"ObligadoEmisión tax ID not identified\"",[19,101,102],{},"The first one, and the most baffling, because the tax ID was correct.",[19,104,105,106,109,110,113],{},"The rule is that the issuer's tax ID must be ",[23,107,108],{},"identified in the AEAT census",", and\nidentification ",[23,111,112],{},"goes together with the name",": sending the right number isn't enough, it\nhas to match the registered legal name for that ID.",[19,115,116,119,120,123],{},[23,117,118],{},"The fix:"," use exactly the name that appears in the certificate as ",[55,121,122],{},"NombreRazonEmisor",".\nThe certificate already carries the tax-ID-and-name pair as the agency knows it; any\nvariation of your own — an abbreviated company suffix, one accent too many — and it won't\nmatch.",[14,125,127],{"id":126},"error-1189-destinatarios-missing","Error 1189 — \"Destinatarios missing\"",[19,129,130],{},"This one is about cross-field rules, and it's the classic afternoon-burner.",[19,132,133,134,137,138,141],{},"The ",[55,135,136],{},"Destinatarios"," (recipients) block ",[23,139,140],{},"is not optional at your discretion",": it depends on\nthe invoice type.",[143,144,145,151],"ul",{},[48,146,147,150],{},[23,148,149],{},"F1, F3 and rectifying invoices R1–R4"," require at least one recipient.",[48,152,153,156],{},[23,154,155],{},"F2 (simplified) and R5"," must not carry it. Send it and you get rejected.",[19,158,159],{},"So the same field is mandatory or forbidden depending on a letter three levels up in the\nXML.",[19,161,162,164,165,168],{},[23,163,118],{}," for the test, issue as ",[23,166,167],{},"F2",", the simplified invoice — the everyday till\nreceipt, which carries no recipient. For named invoices you do have to send the block, and\nthat's where the next step appears: depending on the tax regime code, your customer's tax\nID also has to be identified in the census. In other words, the 4104 problem again, but now\nwith a tax ID you don't control.",[14,170,172],{"id":171},"error-1110-sistemainformatico-tax-id-not-identified","Error 1110 — \"SistemaInformatico tax ID not identified\"",[19,174,175],{},"The easiest one to misread, which is why it's worth the whole article.",[19,177,178,179,182,183,186,187,190],{},"The record contains a ",[55,180,181],{},"SistemaInformatico"," block that ",[23,184,185],{},"is not about your company or your\ncustomer's: it's about the software",". Who makes it. If you sell invoicing software, that\nblock carries ",[23,188,189],{},"your"," tax ID as the producer, not the shop's that is issuing the invoice.",[19,192,193],{},"And it has a handful of mandatory fields that are easy to miss:",[143,195,196,210,215,225],{},[48,197,198,201,202,205,206,209],{},[55,199,200],{},"IdSistemaInformatico",": exactly ",[23,203,204],{},"2 characters",", ",[55,207,208],{},"[A-Z0-9]",".",[48,211,212,209],{},[55,213,214],{},"NombreSistemaInformatico",[48,216,217,220,221,224],{},[55,218,219],{},"TipoUsoPosibleSoloVerifactu"," and ",[55,222,223],{},"TipoUsoPosibleMultiOT",": both mandatory.",[48,226,227],{},"The producer's tax ID, identified in the census — with its name, same as in 4104.",[19,229,230,232],{},[23,231,118],{}," the same as 4104. The name, exactly as it appears in the certificate.",[14,234,236],{"id":235},"the-rules-worth-reading-up-front","The rules worth reading up front",[19,238,239],{},"After the third rejection we stopped guessing and read the official AEAT validation\ncatalogue end to end. Best decision of the whole process: from that point on, the invoice\npassed every applicable validation first try. The ones easiest to break without noticing:",[143,241,242,251,274,283,289,295],{},[48,243,244,247,248,209],{},[23,245,246],{},"Issue date",": cannot be in the future, nor ",[23,249,250],{},"earlier than 28\u002F10\u002F2024",[48,252,253,256,257,260,261,260,264,260,267,260,270,273],{},[23,254,255],{},"Invoice series\u002Fnumber",": ASCII 32–126, and the characters ",[55,258,259],{},"\""," ",[55,262,263],{},"'",[55,265,266],{},"\u003C",[55,268,269],{},">",[55,271,272],{},"="," are\nforbidden.",[48,275,276,279,280,209],{},[23,277,278],{},"F2 simplified",": base plus tax cannot exceed ",[23,281,282],{},"€3,000",[48,284,285,288],{},[23,286,287],{},"VAT rate",": only the catalogue values are accepted (0, 2, 4, 5, 7.5, 10 and 21).",[48,290,291,294],{},[23,292,293],{},"Arithmetic",": the charged amount must be base × rate, the total tax the sum of the\ncharged amounts, and the invoice total the sum of everything. There's a cents-level\ntolerance, but it is checked.",[48,296,297,300,301,304],{},[23,298,299],{},"Record generation timestamp",": drifting into the future relative to the agency's clock\nis a ",[23,302,303],{},"warning",", not a rejection. Knowing which ones are warnings and which kill the\nsubmission is worth its own afternoon.",[14,306,308],{"id":307},"what-we-took-away","What we took away",[19,310,311],{},"Three conclusions, in case they help:",[45,313,314,320,326],{},[48,315,316,319],{},[23,317,318],{},"Almost every early rejection is about identity, not content."," The XML was fine; what\nfailed was who each party claimed to be. Start there.",[48,321,322,325],{},[23,323,324],{},"Validate the hash locally before submitting anything."," It's the only part you can\nconfirm without depending on the tax agency.",[48,327,328,331],{},[23,329,330],{},"Read the validation catalogue before round four, not after."," Fixing error by error is\nslow and gives you a false sense of progress.",[19,333,334,335,342],{},"We did all of this to bring it into ",[336,337,341],"a",{"href":338,"rel":339},"https:\u002F\u002Fatellum.com",[340],"nofollow","Atellum",", our management software\nfor small shops and workshops: the point is that whoever uses it never has to know any of\nthe above — which is exactly why we ate the three errors ourselves.",[19,344,345],{},"If you're in the same fight and get stuck on a specific code, drop us a line and we'll tell\nyou what it was in our case.",{"title":347,"searchDepth":348,"depth":348,"links":349},"",2,[350,351,352,353,354,355,356],{"id":16,"depth":348,"text":17},{"id":39,"depth":348,"text":40},{"id":98,"depth":348,"text":99},{"id":126,"depth":348,"text":127},{"id":171,"depth":348,"text":172},{"id":235,"depth":348,"text":236},{"id":307,"depth":348,"text":308},"2026-08-04","We implemented VeriFactu from scratch for our ERP and submitted it to the AEAT pre-production environment. We hit errors 4104, 1189 and 1110 back to back. Here's what each one means and what had to change.","md","\u002Fog\u002Fog-default.png",{},true,"verifactu-tres-errores-aeat","\u002Fen\u002Fblog\u002Fverifactu-three-aeat-errors",{"title":8,"description":358},false,"en\u002Fblog\u002Fverifactu-three-aeat-errors",[369,370,371,372],"VeriFactu","AEAT","Invoicing","Dart","5Oma8ji1AM6Sah1W7FkvZ5MuNf0dL3vCIlxBsBt-hbI",1787312492802]