Salta ai contenuti

Italia — E-INVOICE IT (Unified API)

In Italia, fiskaly supporta l’invio di fatture elettroniche B2B e B2C e la ricezione di fatture elettroniche B2B. Attualmente supportiamo la Fattura standard (Fattura, TD01) e la Nota di credito (Nota di credito, TD04). Il tipo di documento viene derivato dall’operazione della Unified API e non viene impostato direttamente. Le fatture di acconto (TD02) e le fatture differite (TD24, TD25) non vengono attualmente emesse. Il supporto per la Fattura semplificata (Fattura semplificata, TD07) sarà presto disponibile.

La fatturazione elettronica è obbligatoria e disciplinata dall’Agenzia delle Entrate. Tutte le fatture B2B devono essere scambiate tramite l’SDI (Sistema di Interscambio) nel formato XML FatturaPA (Fattura elettronica) e sono obbligatorie per legge dal gennaio 2019. Le fatture devono inoltre essere conservate a lungo termine tramite archiviazione certificata (conservazione a norma).

Questa pagina illustra i requisiti specifici per l’Italia che completano la Guida all’integrazione generale passo dopo passo per l’onboarding di un Taxpayer ai fini della fatturazione elettronica.

fiskaly gestisce entrambe le direzioni dello scambio con l’SDI, che però funzionano in modo diverso:

Oltre a gestire entrambe le direzioni, fiskaly archivia automaticamente ogni fattura che invii e ricevi. Questo garantisce la conservazione certificata a lungo termine (conservazione a norma) per i 10 anni previsti dalla legge, senza alcuna configurazione da parte tua.

Questi requisiti si applicano a qualsiasi Taxpayer di cui esegui l’onboarding per la fatturazione elettronica in Italia — sia che tu invii, riceva o faccia entrambe le cose. Assicurati di avere a disposizione le seguenti informazioni sul Taxpayer prima di procedere.

Dati di registrazione specifici per l’Italia — trasmessi in content.fiscalization.registration:

  • company_id — Numero Registro Imprese
  • office — sigla della provincia della Camera di Commercio che ha rilasciato il numero REA, es. MI, RM
  • entry — numero REA (6 o 7 cifre)
  • legal_form — forma giuridica dell’entità (es. LIMITED_LIABILITY_COMPANY, JOINT_STOCK_COMPANY)
  • capital — capitale sociale registrato in EUR (es. "10000.00")
  • shareholder_status — SOLE_SHAREHOLDER o MULTIPLE_SHAREHOLDERS
  • liquidation_status — IN_LIQUIDATION o NOT_IN_LIQUIDATION
  • tax_regime — facoltativo, ORDINARY (predefinito) o FLAT_RATE_SCHEME (Regime Forfettario)

Campi standard del Taxpayer — parte del Taxpayer stesso (condivisi con SIGN IT se lo utilizzi):

  • content.name — denominazione legale registrata dell’azienda o del soggetto
  • content.address — indirizzo legale registrato
  • content.address.region — Provincia (codice provincia, es. MI, RM); obbligatorio sul Taxpayer e validato al momento della messa in servizio

Invio di fatture elettroniche: requisiti del destinatario

Sezione intitolata “Invio di fatture elettroniche: requisiti del destinatario”

Per inviare una fattura elettronica indichi il destinatario e i suoi dati di routing direttamente nel Record della fattura. Quando crei la fattura (TRANSACTION::INVOICE) con createRecord, aggiungi il destinatario al suo array recipients. I campi da valorizzare dipendono da chi stai fatturando:

Ogni destinatario ha invoicing.type = SDI. Ciò che cambia tra i tre casi è l’identificazione, il codice destinatario e la presenza o meno di una PEC:

BusinessConsumatore in ItaliaConsumatore all’estero
typeBUSINESSCONSUMERCONSUMER
identificationVAT — validataTAX — codice fiscale, validatoqualsiasi tipo; non validato
invoicing.destination_codeil codice di 7 caratteri del destinatario, oppure "0000000" o "XXXXXXX""0000000""XXXXXXX"
invoicing.pecobbligatoria con "0000000"facoltativanon utilizzata
address.regionobbligatoria quando l’indirizzo è in Italiaobbligatorianon obbligatoria
nameragione socialegender, forename, surnamegender, forename, surname

Ogni destinatario business è di tipo BUSINESS con il blocco invoicing compilato, come spiega l’integrazione generale passo a passo. Oltre ai dati standard richiesti da ogni fattura elettronica (nome del destinatario, indirizzo, identificazione fiscale, righe della fattura e così via), l’Italia aggiunge i campi di routing SDI indicati sopra.

I valori che destination_code e pec assumono dipendono dal destinatario:

Scenariodestination_codepec
Il destinatario ha una casella SDI registratail suo codice di 7 caratteri (es. ABC1234)facoltativo
Il destinatario non è registrato all’SDI"0000000"obbligatorio
Il destinatario è fuori dall’Italia"XXXXXXX"non utilizzato

Quando il tuo cliente è una persona fisica e non un’azienda, imposta recipients[].type su CONSUMER. La fattura passa dall’SDI come documento FatturaPA (TD01), come una fattura B2B.

I consumatori non hanno una casella SDI, quindi il routing funziona in modo diverso. Il modo in cui identifichi il consumatore dipende dalla sua residenza in Italia:

  • Residente in Italia — identificato dal codice fiscale, instradato con il codice destinatario "0000000".
  • Fuori dall’Italia — non esiste alcun codice fiscale, quindi al suo posto subentra un identificativo estero e la fattura viene instradata con "XXXXXXX".

Oltre ai campi della tabella qui sopra, un destinatario consumatore riporta sempre name.gender, name.forename e name.surname, insieme al suo indirizzo.

Invia il codice fiscale come identificazione di tipo TAX (16 caratteri), l’indirizzo di residenza inclusa la region (Provincia) e il codice destinatario "0000000". Una pec può essere aggiunta, ma non è obbligatoria.

Un consumatore non residente in Italia non ha un codice fiscale: invia al suo posto un identificativo estero, di norma un numero fiscale o di partita IVA estero.

CampoValore
recipients[].identificationobbligatoria; VAT, TAX, PASSPORT, DOCUMENT o OTHER, a seconda dell’identificativo di cui disponi
recipients[].address.countryil Paese del consumatore come codice ISO 3166-1 alpha-2
recipients[].address.code"00000" — FatturaPA accetta solo un CAP di 5 cifre
recipients[].invoicing.destination_code"XXXXXXX"

L’identificativo viene trasmesso all’SDI come IdCodice; né fiskaly né l’SDI ne verificano la validità quando il Paese dell’indirizzo non è l’Italia. La region non è obbligatoria per un indirizzo non italiano.

Per un consumatore residente in Italia, l’SDI deposita la fattura originale nella sua area riservata sul portale AdE (Fatture e Corrispettivi).

Quando il cliente ha bisogno della fattura invece del documento commerciale

Sezione intitolata “Quando il cliente ha bisogno della fattura invece del documento commerciale”

L’Italia trasmette i due documenti su canali separati — il documento commerciale tramite i corrispettivi, la fattura tramite l’SDI — e nulla li collega automaticamente.

Raccogli la richiesta prima che la vendita venga chiusa. Quando il cliente ti comunica che ha bisogno di una fattura, emetti una TRANSACTION::INVOICE al posto di una TRANSACTION::RECEIPT. È il flusso che fiskaly supporta oggi da un capo all’altro, sia che il cliente lo chieda prima sia durante la vendita.

A differenza di una chiamata API sincrona, l’esito dell’SDI è asincrono. Dopo aver creato la fattura (TRANSACTION::INVOICE) con createRecord, interroga il Record E_INVOICE::TRANSMISSION per sapere se l’SDI l’ha accettata. Non esiste un webhook.

Tutti e tre i Record raggiungono il loro stato finale insieme:

RecordStato finale
E_INVOICE::TRANSMISSIONCOMPLETED o FAILED, mode=FINISHED
TRANSACTION::INVOICECOMPLETED o FAILED, mode=FINISHED
INTENTION::TRANSACTIONCOMPLETED o FAILED, mode=FINISHED

In caso di errore, il motivo del rifiuto dell’SDI è disponibile in logs[].message su tutti e tre i Record. Per maggiori dettagli, consulta How to check the status of an e-invoice sulla nostra pagina di supporto.

state indica a che punto si trova una fattura, logs[] indica il perché. Leggili insieme e agisci in base a ciò che trovi:

Cosa vediCosa significaCosa fare
4xx da createRecord, nessun Record creatoIl payload è stato rifiutato. Nulla è stato creato e nulla è stato inviato.Correggi il payload e riprova sullo stesso INTENTION::TRANSACTION.
state=ACCEPTEDAncora in corso.Interroga il Record E_INVOICE::TRANSMISSION. Gli esiti arrivano in genere entro pochi minuti.
state=FAILEDConclusa, e la fattura non è giuridicamente valida. È stata bloccata prima di raggiungere l’SDI oppure rifiutata dall’SDI con NS.Leggi logs[].message per conoscere il motivo, correggi i dati e avvia una nuova catena — vedi Errori e nuovo invio.
state=COMPLETED con una voce ERROR in logs[]Qualcosa è andato storto lungo il percorso senza bloccare la fattura.Leggi logs[].message prima di considerare la fattura come inviata.
state=COMPLETED, nessuna voce ERRORL’SDI ha accettato la fattura.Nulla di ulteriore.

Ogni voce in logs[] è un ERROR o un WARNING. Un WARNING è informativo e non blocca mai una fattura — lo ricevi quando qualcosa nel tuo payload è stato adattato o non tornava, per esempio se hai inviato più pagamenti in sospeso ed è stato usato solo il primo, oppure se i totali IVA nel tuo payload differiscono dai totali calcolati dalle righe della fattura.

Non ogni rifiuto ha l’aspetto di un rifiuto. I dati della fattura vengono controllati in tre punti diversi, e ciascuno fallisce in una forma differente:

Dove fallisceEsempioCosa vedi
Vincoli di schemaidentification.number fuori da AlphaNumerical28; document.number fuori da ^[0-9A-Z_/\-\.]{1,20}$400 da createRecord. Non viene creato nulla.
Validazione di campoUn codice fiscale con formato errato o cifra di controllo sbagliatacreateRecord va a buon fine. Il Record si chiude in COMPLETED / FINISHED, ma content.used_in è assente e non viene trasmesso nulla. Il motivo compare solo come voce di content.logs con severità ERROR.
A valleUn recipients[].address.region mancantecreateRecord va a buon fine e la catena passa poi a FAILED.

Se l’SDI restituisce NS (Notifica di Scarto), la fattura è giuridicamente inesistente:

  1. Leggi logs[].message su uno qualsiasi dei tre Record per ottenere il motivo del rifiuto dell’SDI
  2. Crea una nuova INTENTION::TRANSACTION e una nuova TRANSACTION::INVOICE con i dati corretti
  3. Lo stesso document.number può essere riutilizzato entro 5 giorni dal rifiuto NS
  4. La catena fallita rimane FAILED in modo permanente — viene conservata a fini di audit

Un System E_INVOICE_SERVICE può sia inviare che ricevere fatture elettroniche. La ricezione è facoltativa — un Taxpayer che si limita a inviare può saltare questa sezione.

Sono coinvolte due cose distinte e indipendenti:

  • Predisposizione alla ricezione — fiskaly la configura automaticamente quando metti in servizio il System.
  • Registrazione del codice destinatario SDI (manuale, a tua cura) — nel tuo portale dell’Agenzia delle Entrate (AdE), imposta il codice destinatario SDI di fiskaly JKKZDGR come destinazione SDI della tua azienda, in modo che l’SDI instradi le tue fatture in entrata verso fiskaly.

La risposta alla messa in servizio mostra compliance.state come TRANSMISSION_ONLY. Passa poi automaticamente a TRANSMISSION_RECEPTION una volta completata la registrazione del Taxpayer — cosa che normalmente avviene, indipendentemente dal fatto che tu abbia effettuato la registrazione presso l’AdE o intenda ricevere.

Chiama retrieveSystem in qualsiasi momento per leggere lo stato attuale di compliance.state, che riflette solo la predisposizione — non la registrazione presso l’AdE:

  • TRANSMISSION_RECEPTION — fiskaly ha configurato il System per la ricezione.
  • TRANSMISSION_ONLY — quella configurazione non è stata completata.

Non c’è nulla di aggiuntivo da configurare per l’instradamento: fiskaly abbina automaticamente ogni fattura in arrivo al Taxpayer corretto utilizzando il suo codice fiscale — motivo per cui ogni codice fiscale deve appartenere a un solo Taxpayer registrato. Non è necessario configurare o memorizzare un codice di instradamento separato.

Quando ti viene inviata una fattura tramite l’SDI, fiskaly la riceve automaticamente:

  • la consegna in entrata viene elaborata automaticamente dalla nostra parte
  • viene creato un record di ricezione per la fattura
  • l’XML firmato, il PDF e i metadati vengono archiviati insieme al record
  • le consegne duplicate vengono deduplicate

In pratica, la prima fattura che ti raggiunge in questo modo è anche la conferma che la ricezione è configurata correttamente.

Ogni fattura indirizzata al tuo Taxpayer viene ricevuta, validata e archiviata automaticamente come Record — non esiste un webhook, quindi devi interrogare l’API per individuare quelle nuove:

  1. Chiama listRecords e filtra per E_INVOICE::RECEPTION.
  2. Per ogni nuovo Record, chiama retrieveRecord con compliance-artifact per ottenere l’XML firmato.

listRecords restituisce i Record più recenti (limit predefinito a 10, dal più recente), quindi tieni traccia di quelli che hai già elaborato.

La legge italiana richiede che le fatture elettroniche siano conservate a lungo termine tramite archiviazione digitale certificata (conservazione a norma): devono essere conservate per almeno 10 anni e memorizzate in modo che rimangano immutabili, autentiche e facilmente recuperabili, con firme digitali e marche temporali (marca temporale). Conservare una propria copia dell’XML non è sufficiente — fiskaly se ne occupa per te.

Per l’Italia, l’archiviazione è automatica e sempre attiva: ogni fattura che invii e ogni fattura che ricevi tramite l’SDI viene conservata legalmente, senza alcuna configurazione aggiuntiva o chiamata API da parte tua. Si basa unicamente sul codice fiscale italiano del Taxpayer, che fa già parte dell’onboarding. Ogni fattura conservata riceve una ricevuta di conservazione come prova della conservazione a norma. La conservazione è basata su eventi e si completa di solito in pochi secondi; la ricevuta stessa può richiedere fino a circa sei minuti per essere emessa, dopodiché fiskaly la allega automaticamente — non è richiesto nulla da parte tua.

Recupera gli artefatti di una fattura elettronica dal suo record con retrieveRecord, selezionando l’artefatto tramite un parametro di query:

  • compliance-artifact — il documento con valore legale. Per l’Italia, l’XML FatturaPA validato dall’SDI.
  • archive-artifact — la ricevuta di conservazione che attesta la conservazione legale (conservazione a norma), restituita come XML firmato.

Entrambi gli artefatti rispettano l’header di richiesta Accept, che determina la forma della risposta:

AcceptCosa ottieni
application/xmlL’artefatto stesso: l’XML FatturaPA oppure l’XML della ricevuta di conservazione.
application/jsonIl Record in JSON, con l’artefatto codificato in Base64 nel consueto campo content.

compliance-artifact e archive-artifact non esistono per tutta la vita di un Record. Nessuno dei due viene prodotto alla creazione del Record: entrambi vengono scritti una volta completata la trasmissione, cioè dopo la risposta dell’SDI, che la specifica SDI consente di attendere fino a 48 ore. Si fissano nello stesso momento, perché il passaggio di conservazione avviene prima del cambio di stato del Record.

Ne deriva una regola basata unicamente sullo stato, senza nulla da cronometrare:

Stato del RecordCosa dice sugli artefatti
state: ACCEPTED, mode: PROCESSINGNon terminale. Gli artefatti possono ancora mancare, e mancante significa non ancora: stanno arrivando.
state: COMPLETED / FAILED / REJECTED, mode: FINISHEDTerminale. Ciò che è presente è tutto ciò che ci sarà; un artefatto assente non comparirà più.

La ricevuta di conservazione appartiene al Record E_INVOICE::TRANSMISSION e non alla TRANSACTION::INVOICE. Prendi content.used_in.id dal Record della fattura, poi:

GET /records/{transmissionId}?archive-artifact

La ricevuta viene restituita codificata in Base64 in content.compliance.archive.data. Le fatture che invii e le fatture che ricevi hanno ciascuna la propria ricevuta. Finché l’artefatto non è disponibile, il campo è assente dalla risposta anziché presente e vuoto.

La legge italiana richiede un’imposta di bollo di 2,00 € sulle fatture le cui righe esenti da IVA superano complessivamente 77,47 €. fiskaly la applica automaticamente: quando il totale delle righe esenti da IVA rilevanti supera tale soglia, l’imposta di bollo viene aggiunta alla FatturaPA trasmessa.

Non esiste un campo per l’imposta di bollo né nella richiesta né nella risposta — non c’è nulla da impostare quando crei la fattura e nulla viene restituito sul Record. L’unico punto in cui compare il valore applicato è l’elemento DatiBollo dell’XML FatturaPA, che puoi leggere dal documento trasmesso:

GET /records/{transmissionId}?compliance-artifact

L’XML arriva codificato in Base64, quindi decodificalo prima di cercare DatiBollo.

I 2,00 € vengono aggiunti dopo il calcolo dei totali della fattura: su ogni fattura che supera la soglia, quindi, i totali trasmessi sono più alti di 2,00 € rispetto a quelli che hai inviato. Il Record registra questa differenza come due voci WARNING in content.logs, per esempio:

provided '100.00000000', calculated '102.00'

È un comportamento previsto ed è il segnale che l’imposta di bollo è stata applicata. Continua a inviare i tuoi totali al netto dell’imposta: non esiste un payload che includa l’imposta di bollo ed eviti allo stesso tempo gli avvisi. Tratta queste due voci WARNING come puramente informative e non far fallire la tua integrazione a causa loro.

Stornare una fattura emessa al di fuori di fiskaly

Sezione intitolata “Stornare una fattura emessa al di fuori di fiskaly”

In Italia il tipo di documento è l’identificativo di tipo FatturaPA: una CORRECTION viene trasmessa come TD04 (Nota di credito), una INVOICE come TD01 (Fattura). Poiché il tipo deriva dall’operazione, una fattura non trasmessa da fiskaly non può essere stornata: emettere una TD01 che referenzia la fattura precedente aumenta l’importo dovuto invece di azzerarlo. Vedi Nota di credito per la regola generale.

Per casi una tantum, l’SdI garantisce a tutti gli esercenti l’accesso al portale, dove è possibile emettere manualmente una nota di credito. Non è scalabile e non è un pattern di integrazione: trattalo come ripiego per la migrazione e mantieni disponibile il precedente sistema di fatturazione elettronica finché tutto ciò che ha emesso non è stato saldato o stornato.