Building Autofatturala: Italian Self-Invoicing Is Crazy, Rails + RubyLLM Made It Simple

2026年8月11日2 次浏览来源:Dev.to阅读原文

Here is a fun fact about doing business in Italy: when you buy something from a foreign company, you often have to write an invoice to yourself.

Not a note.

Not a line in a spreadsheet.

A real electronic invoice, in a specific XML format, with a specific document type code, sent to a government system called SDI (Sistema di Interscambio), by a specific deadline.

If you get one field wrong, the government system rejects the file.

I built a product to make this bearable: Autofatturala.

In this article I want to tell you the story of the journey: how absurd the problem is, and how surprisingly easy it was to build the solution with Rails and RubyLLM.

I will show some real code, but not everything.

Some parts of the product stay in the kitchen.

The problem, for non-Italian readers Say your Italian company pays for a SaaS subscription from a US provider, or buys goods from a German supplier.

The foreign supplier does not charge Italian VAT, obviously.

But VAT is still due in Italy.

So Italian law says that the buyer must "integrate" the invoice.

In practice, you issue a new electronic document where you are both the receiver and, fiscally speaking, the issuer.

This is the autofattura, the self-invoice, part of the reverse charge mechanism.

Sounds manageable so far.

Then you sit down to actually do it, and you discover how many things you need to get right.

First, the document type.

TD17 is for services from abroad, TD18 for intra-EU goods, TD19 for goods that are already in Italy but sold by a non-resident.

Three codes for what a normal person would describe as "I bought something from a foreign company".

Then there is the Natura code, which you must use, except when you must not.

If the operation is taxable, you apply 22% VAT and leave the Natura field empty.

If it is not taxable, you put 0% and a Natura code like N2.1 or N3.4.

If you fill both, SDI rejects the file (checks 00400 and 00401).

And there is a whole group of codes, N6.x, that literally means "reverse charge" and still must never be used here, because it is reserved for the domestic reverse charge.

Yes, really.

If the invoice is in dollars or any other currency, you also need to convert it to EUR using the official ECB reference rate for the right date.

Except the rate does not exist on weekends and holidays, so you take the last available one.

For EU suppliers you should also verify the counterpart on VIES, the EU-wide VAT registry, which is famously moody about being online.

And all of this has a deadline: the 15th of the month following the one when you received the invoice.

Every Italian company that buys anything from abroad, which today means every company, has to do this dance for every single foreign invoice.

Most of them forward PDFs to their accountant and hope.

That is the product opportunity.

What Autofatturala does The idea is simple.

You upload the foreign supplier's PDF, or forward it to a dedicated email address, and a pipeline of small AI agents does the boring part.

It extracts the data from the PDF, checks the VAT number on VIES, applies the ECB exchange rate, proposes the right document type and VAT treatment, validates everything, and prepares the self-invoice.

You review it, press approve, and it goes to your invoicing system and then to SDI.

Every step is shown live in the UI with its own explanation, so the user always sees why the AI made a choice.

Nothing is sent anywhere without human approval.

The stack Nothing exotic, and that is the point.

Rails 8.1 and Ruby 3.3.

RubyLLM for everything LLM related.

Hotwire for the live pipeline timeline, which means the whole app has about 200 lines of JavaScript.

Solid Queue for background jobs, Action Mailbox for the "forward your invoice by email" feature, Nokogiri for the FatturaPA XML (validated locally against the official XSD), and Kamal to deploy everything on a single server.

The whole app, pipeline included, is around 9,000 lines of Ruby, with roughly the same amount of test code.

One person, a f

分享
Baike.dev

baike.dev helps you discover great languages, frameworks, databases, DevOps and cloud-native tools.

Quick links

About

Contribute

Found a great developer tool? Share it with the community.

Submit a tool
© 2026 baike.dev Developer EncyclopediaUpdated daily · Discover great developer tools