You are viewing the documentation for API version 2026-06-01.
This guide is for customers who already have a working SIGN IT integration and want to add Italian e-invoicing (E-INVOICE IT) — B2B and B2C — on top of it. Both products run on the same Unified API and share the same Taxpayer and Location structure — only a few additions are needed.
E-INVOICE IT is only available on 2026-06-01, and the API version applies to your whole integration, not per product. Adding e-invoicing therefore means moving your existing SIGN IT integration to 2026-06-01 as well — your fiscal receipts cannot stay on 2025-08-12 while invoices run on 2026-06-01. Plan the version migration first; the steps below assume you are already on 2026-06-01.
E-INVOICE IT does not require SIGN IT. If you are starting without an existing SIGN IT integration, start from the Prerequisites on the Italy page instead — this guide assumes a commissioned SIGN IT Taxpayer throughout.
Coming from SIGN IT 2024-10-31 or 2025-08-12? Expand and read this first.
After version 2025-08-12, some resources were renamed and new ones were added for e-invoicing. The updated endpoints can be called with the same {id} already in use.
| Until version 2025-08-12 | After version 2025-08-12 | Notes |
|---|---|---|
ASSET — /assets | ORGANIZATION — /organizations | Just a rename — same ID as before. |
ENTITY (COMPANY/INDIVIDUAL) — /entities | TAXPAYER (COMPANY/INDIVIDUAL) — /taxpayers | Just a rename — same ID as before. |
ENTITY (LOCATION) — /entities | LOCATION — /locations | This resource is now split into two types:
|
SYSTEM referencing entity: {id} | SYSTEM referencing location: {id} | Just a rename — same ID as before. |
Before you continue:
- Update your
X-Api-Versionheader to the version shown in the banner above — for all your calls, receipts included. There is no way to run receipts on the old version alongside e-invoicing. - Make sure you’re pointing to the correct base URLs:
test.api.fiskaly.com(TEST) andlive.api.fiskaly.com(LIVE). - Add
fiscalization.credentials.tax_id_numberto your FISCONLINE credentials, if it isn’t already there. This field wasn’t required in 2024-10-31, was optional in 2025-08-12, but is now required. - Review the key record payload structure updates in the API doc — this FAQ may help along the way. For any questions, feel free to contact dev-support@fiskaly.com.
What your SIGN IT integration already covers
Section titled “What your SIGN IT integration already covers”Before starting, your integration is assumed to have:
- A Taxpayer created with Italian fiscalization data (
fiscalization.type=IT,tax_id_number,vat_id_number,credentials) - The Taxpayer commissioned (
state=COMMISSIONED,mode=OPERATIVE) - A
FISCAL_DEVICESystem commissioned on the Taxpayer’s Location - An
INTENTION::TRANSACTION→TRANSACTION::RECEIPT/TRANSACTION::CORRECTION/TRANSACTION::CANCELLATIONflow for fiscal receipts
None of this needs to change. The steps below add E-INVOICE IT alongside the existing setup.
Extend Taxpayer onboarding data
Add the extra company registration details that Italian e-invoicing requires.
Commission an additional System
Enable the e-invoicing service on your Taxpayer — this covers sending and, optionally, receiving.
Add the invoice transaction flow
Start issuing invoices and credit notes to businesses and consumers.
Step 1 — Extend Taxpayer onboarding data
Section titled “Step 1 — Extend Taxpayer onboarding data”E-INVOICE IT currently supports Taxpayers of type COMPANY. An INDIVIDUAL Taxpayer — a freelancer or sole trader issuing under their own codice fiscale rather than a company VAT ID — cannot be extended yet; support is coming soon.
Two additions are required on the Taxpayer that SIGN IT alone does not need:
-
address.region— the Italian Provincia code is mandatory for SDI submission: two uppercase letters, for exampleMIorRM. If it is not already set on the Taxpayer, add it via updateTaxpayer. -
fiscalization.registration— a new block carrying Registro delle Imprese / REA data.Required fields:
company_id,office,entry,legal_form,capital,shareholder_status,liquidation_status. Thetax_regimefield defaults toORDINARYif you don’t set it.SDI requires this block for registered entities, so provide it when you onboard the Taxpayer.
address and fiscalization can only be changed while the Taxpayer is ACQUIRED, or COMMISSIONED with mode SUSPENDED. On an operative Taxpayer, a PATCH is refused (HTTP 405). Each block you send replaces the stored one as a whole, so send it complete, including the existing values. See Can I update Taxpayer data? and How to update FISCONLINE credentials.
Example: three requests to add the registration data
1. Suspend the Taxpayer — PATCH /taxpayers/{taxpayer_id}
{ "content": { "mode": "SUSPENDED" }}2. Send the complete blocks — PATCH /taxpayers/{taxpayer_id}. Repeat your existing values and add registration (and region, if missing):
{ "content": { "address": { "line": { "type": "STREET_NUMBER", "street": "Via Milano", "number": "42" }, "code": "20121", "city": "Milano", "country": "IT", "region": "MI" }, "fiscalization": { "type": "IT", "tax_id_number": "12345678901", "vat_id_number": "12345678901", "credentials": { "type": "FISCONLINE", "tax_id_number": "RSSMRA85M01H501Z", "password": "<your-password>", "pin": "<your-pin>" }, "registration": { "company_id": "MI12345678901234567", "office": "MI", "entry": "1234567", "legal_form": "LIMITED_LIABILITY_COMPANY", "capital": "10000.00", "shareholder_status": "MULTIPLE_SHAREHOLDERS", "liquidation_status": "NOT_IN_LIQUIDATION" } } }}3. Set the Taxpayer back to operative — PATCH /taxpayers/{taxpayer_id}
{ "content": { "mode": "OPERATIVE" }}If the Taxpayer already has address.region, leave the address block out of the request. Only the blocks you send are replaced, and each must be complete: fiscalization always needs type, tax_id_number, vat_id_number and credentials next to the new registration.
Step 2 — Commission an additional System
Section titled “Step 2 — Commission an additional System”Commissioning the E_INVOICE_SERVICE System is what makes e-invoicing possible for this Taxpayer — it’s what builds the FatturaPA XML, transmits it to SDI, and (optionally) receives inbound invoices. But it is not the System you send invoice records to.
Because this Taxpayer already has a FISCAL_DEVICE commissioned, that System takes precedence for record creation: you create the same INTENTION::TRANSACTION → TRANSACTION::INVOICE chain you already use for receipts, on a FISCAL_DEVICE System (any one on the same Taxpayer) — not on E_INVOICE_SERVICE. fiskaly reads that data and turns it into the e-invoice behind the scenes.
Receiving is optional. If you want it, set fiskaly’s SDI recipient code JKKZDGR as your company’s SDI destination in your Agenzia delle Entrate (AdE) portal — any time, before or after commissioning. Without it the Taxpayer won’t receive invoices, even once the System is ready. Skip it if the Taxpayer will only send.
Use createSystem to create an E_INVOICE_SERVICE System on the Taxpayer’s HEAD_OFFICE Location, then commission it via updateSystem by setting its state to COMMISSIONED.
Only one E_INVOICE_SERVICE System can be commissioned per Taxpayer, on the HEAD_OFFICE Location (created automatically with the Taxpayer) — commissioning a second one fails. It stays separate from the FISCAL_DEVICE Systems used for receipt fiscalization, which remain unaffected no matter how many you have.
The commissioning response always shows TRANSMISSION_ONLY; call retrieveSystem afterwards to read the System’s actual compliance.state. If it stays TRANSMISSION_ONLY instead of transitioning to TRANSMISSION_RECEPTION, the Taxpayer’s registration didn’t complete — treat it as a stuck transition and contact the fiskaly support team at dev-support@fiskaly.com with the Taxpayer’s VAT ID so we can investigate.
For the full receiving flow, see Receiving e-invoices on the Italy page.
Step 3 — Add the invoice transaction flow
Section titled “Step 3 — Add the invoice transaction flow”SIGN IT uses TRANSACTION::RECEIPT / TRANSACTION::CORRECTION / TRANSACTION::CANCELLATION.
E-INVOICE IT uses different transaction types on the same INTENTION::TRANSACTION container:
- Invoice (B2B or B2C) → create a
TRANSACTION::INVOICEon aFISCAL_DEVICESystem (any one on the same Taxpayer) - Credit note → create a
TRANSACTION::CORRECTIONwithdata.type=INVOICEon the same System, referencing the original invoice viarecord.id
On a credit note, set entries[].type = RETURN on each credited line. Every line of a TRANSACTION::CORRECTION with data.type=INVOICE is credited, whatever its entry type, so a line sent with SALE is accepted and still credited. A credit note can’t also charge for new items; issue a separate invoice for those.
Both BUSINESS and CONSUMER recipients are supported. For a business recipient, the entry in the invoice’s recipients array needs an invoicing block of type SDI, plus the recipient’s Provincia:
recipients[].type=BUSINESSrecipients[].invoicing.type=SDIrecipients[].invoicing.destination_code— the recipient’s 7-character SDI inbox coderecipients[].invoicing.pec— (where required) the recipient’s PEC addressrecipients[].address.region— the recipient’s Provincia (e.g.MI,RM)
| Scenario | destination_code | pec |
|---|---|---|
| Recipient has a registered SDI inbox | their 7-character code, uppercase letters and digits (e.g. ABC1234) | optional |
| Recipient is not registered with SDI | "0000000" | required |
| Recipient is a business outside Italy | "XXXXXXX" | not used |
For a business outside Italy, send destination_code: "XXXXXXX" with the recipient’s foreign VAT number — see Business recipients outside Italy.
Set the recipient’s Provincia in recipients[].address.region. It isn’t marked required in the shared Unified API schema, but Italy requires it whenever the address is in Italy. A missing one doesn’t produce an error response: the record comes back COMPLETED with an ERROR entry in logs and no used_in, and no invoice is created. Send it as two uppercase letters, for example RM.
For a consumer recipient (B2C), the fields are different — no destination_code of your recipient’s choosing and no VAT number, but the codice fiscale is mandatory:
recipients[].type=CONSUMERrecipients[].identification.type=TAX, withnumberset to the consumer’s codice fiscalerecipients[].name—gender,forenameandsurnamerecipients[].address— the consumer’s residence address, includingregion(Provincia)recipients[].invoicing.destination_code="0000000", withpecoptional
gender is required by the Unified API, not by SDI — the FatturaPA invoice carries no such field. Send DIVERSE when you don’t have the data.
For the full recipient requirements, see Sending e-invoices on the Italy page.
When a customer needs an invoice instead of a receipt
Section titled “When a customer needs an invoice instead of a receipt”Your two flows report to different places — the receipt to the AdE, the invoice to SDI — and nothing links them automatically.
Capture the request before the sale is closed. When the customer tells you they need a fattura, issue a TRANSACTION::INVOICE on your FISCAL_DEVICE System in place of the receipt. That is the flow fiskaly supports end to end today, whether the customer asks before or during the sale.
Handling SDI responses
Section titled “Handling SDI responses”Asynchronous outcome
Section titled “Asynchronous outcome”Unlike receipt flows, the SDI outcome is asynchronous. After creating the TRANSACTION::INVOICE, poll the E_INVOICE::TRANSMISSION Record to learn whether SDI accepted it. There is no webhook.
SDI outcomes usually arrive within minutes, but SDI can take up to 5 days to return a rejection, so keep polling until the Record reaches mode=FINISHED. While the state is ACCEPTED and the mode PROCESSING, poll about every 15 seconds.
If the invoice is transmitted, all three Records reach their final state together:
| Record | Final state |
|---|---|
E_INVOICE::TRANSMISSION | COMPLETED or FAILED, mode=FINISHED |
TRANSACTION::INVOICE | COMPLETED or FAILED, mode=FINISHED |
INTENTION::TRANSACTION | COMPLETED or FAILED, mode=FINISHED |
On failure, read logs[].message: a failure before the invoice reaches SDI is logged on the TRANSACTION::INVOICE Record, an SDI rejection on the E_INVOICE::TRANSMISSION Record.
For more details, see How to check the status of an e-invoice on our Support page.
Sent and received e-invoices are automatically preserved long-term (conservazione a norma, at least 10 years), with a preservation receipt available from the Record’s archive-artifact. No setup is required. See Archiving on the Italy page for details.
The compliance artifact for Italian e-invoicing is the FatturaPA XML, accessible on the E_INVOICE::TRANSMISSION Record.
Error stages
Section titled “Error stages”Errors can occur at three distinct stages, each with different behavior:
| Stage | When | Behavior |
|---|---|---|
| UAPI validation (synchronous) | Invalid payload | 4xx returned immediately — no Record is created. Fix the payload and retry on the same INTENTION::TRANSACTION. |
| Field validation (asynchronous) | Invalid data in an accepted payload, e.g. a codice fiscale with a bad format or a wrong check digit, or a missing recipients[].address.region | The Record closes COMPLETED / FINISHED with an ERROR entry in content.logs and no content.used_in. Nothing is transmitted. Fix the data and start a new chain. |
| SDI rejection (asynchronous) | SDI returns NS | Full chain reaches state=FAILED — a new chain is required to retry. |
A COMPLETED / FINISHED Record with no invoice behind it looks exactly like a successful one if you read state and stop there. Always read content.logs for ERROR entries, and check that content.used_in is present, before you treat an invoice as issued.
Failures and resubmission
Section titled “Failures and resubmission”If SDI returns NS (Notifica di Scarto), the invoice is legally non-existent:
- Read
logs[].messageon theE_INVOICE::TRANSMISSIONRecord to get the SDI rejection reason - Create a new
INTENTION::TRANSACTIONand a newTRANSACTION::INVOICEwith corrected data - A new 5-day window starts with the
NSrejection. Within it, you can resend the invoice with the samedocument.number, as new Records with a new idempotency key - The failed chain remains
FAILEDpermanently — it is kept for audit purposes
Each resubmission starts a fresh transaction chain — UAPI treats it as an entirely new submission.
What does not change
Section titled “What does not change”The following remain completely untouched:
- Taxpayer commissioning flow and Fisconline credentials
- All
FISCAL_DEVICESystems andBRANCHLocations - Your existing
INTENTION::TRANSACTION→TRANSACTION::RECEIPT/TRANSACTION::CORRECTION/TRANSACTION::CANCELLATIONreceipt flow