# E-Invoicing

## What is E-Invoicing?

E-invoicing is the electronic submission of invoices to a government tax authority for validation and record-keeping. In Spain, this is done through the **Verifactu** system, which is managed by the Spanish Tax Authority (AEAT). Starting in 2027, certain businesses operating in Spain are required to submit invoices electronically through Verifactu.

Lavanda's e-invoicing feature automates this process. When a workspace has e-invoicing enabled, invoices are automatically converted to the required format, submitted to the tax authority, and tracked through to acceptance or rejection.

## Key Terms

| Term          | Description                                                                                                                                                                                                     |
| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **AEAT**      | Agencia Estatal de Administracion Tributaria. The Spanish Tax Authority that receives and validates invoices                                                                                                    |
| **Verifactu** | The AEAT's electronic invoicing system. It validates invoice data, assigns a cryptographic hash, and returns a QR code as proof of submission                                                                   |
| **GOBL**      | Go Business Language. An open-source standard for representing financial documents (invoices, credit notes) in a structured, machine-readable JSON format. Invoices must be converted to GOBL before submission |
| **Invopop**   | A third-party e-invoicing platform that acts as the integration layer between Lavanda and Verifactu. It handles GOBL validation, Verifactu XML generation, and submission to AEAT                               |
| **Silo**      | Invopop's document storage. Invoices are uploaded to the Silo as GOBL documents before a workflow is triggered                                                                                                  |
| **Workflow**  | An Invopop processing pipeline. Once a document is in the Silo, a workflow job validates it, generates the Verifactu XML, submits it to AEAT, and reports the result                                            |

## How It Works

The e-invoicing flow has three main stages: conversion, submission, and confirmation.

### 1. Conversion

When an invoice is issued in a workspace with e-invoicing enabled, the system converts the invoice data into a GOBL document. This involves:

* Mapping invoice fields (supplier, recipient, line items, VAT rates) to GOBL's structured format
* Mapping the recipient's identity document (DNI, NIE, passport, etc.) to the correct GOBL tax identity or Verifactu identity code
* Applying Spain-specific tax regime configuration and Verifactu add-on fields

### 2. Submission

The GOBL document is sent to Invopop in two steps:

1. **Store** the document in Invopop's Silo (`PUT /silo/v1/entries/{id}`)
2. **Trigger a workflow** to submit it to Verifactu (`PUT /transform/v1/jobs/{job_id}`)

Both calls use UUID v7 identifiers. The Silo entry ID is tied to the invoice's UUID, so re-uploading the same invoice is idempotent.

### 3. Confirmation

Invopop processes the submission asynchronously. Once Verifactu responds, Invopop sends a webhook notification back to Lavanda. The webhook contains only the Silo entry ID, so the system fetches the full result from Invopop to extract:

* The **QR code URL** (a link customers can use to verify the invoice on AEAT's website)
* The **Verifactu hash** (cryptographic proof of submission)
* The **submission status** (accepted or rejected, with a reason if rejected)

Based on the result, the invoice is marked as either **Issued** (accepted) or **Rejected**.

## Document States

In workspaces without e-invoicing, an invoice moves directly from **Draft** to **Issued** when it is finalised. E-invoicing adds intermediate states to represent the asynchronous submission process.

```
  Draft
    │
    ├── (non-e-invoicing workspace) ──────────────► Issued
    │
    └── (e-invoicing workspace) ──► Issuing
                                        │
                                        ├── accepted ──► Issued
                                        │
                                        └── rejected ──► Rejected
                                                            │
                                                            └── re-submit ──► Issuing
```

| State        | Description                                                                                                                                              |
| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Draft**    | The invoice is being prepared. It can be edited or deleted                                                                                               |
| **Issuing**  | The invoice has been submitted to the tax authority and is awaiting a response. It is locked: no edits, credit actions, exports, or deletion are allowed |
| **Issued**   | The invoice has been accepted by the tax authority (or was issued in a non-e-invoicing workspace). It is finalised                                       |
| **Rejected** | The tax authority rejected the submission. The invoice can be corrected and re-submitted, which moves it back to Issuing with a new invoice number       |

> **Note:** When a rejected invoice is re-submitted, it receives a new invoice number. The original number is not reused.

## Architecture Overview

The e-invoicing feature spans two backend services:

| Service                   | Role                                                                                                                                                                                                                         |
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **LVDAM** (Ruby on Rails) | Source of truth for invoice data. Manages document states (draft, issuing, rejected, issued), invoice number allocation, and the RPC endpoints that the finance service calls to trigger state transitions                   |
| **Abacus** (Elixir)       | Finance and accounting engine. Receives invoice data via CDC, handles the e-invoicing decision logic (should this invoice go through Verifactu?), performs the GOBL conversion, calls Invopop, and processes webhook results |

### Data flow

```
LVDAM                          Abacus                         Invopop          AEAT
  │                              │                              │                │
  │ ── CDC (invoice data) ─────►│                              │                │
  │                              │                              │                │
  │ ◄── RPC: start issuing ─────│ (reserves invoice number)    │                │
  │                              │                              │                │
  │                              │── GOBL doc ────────────────► │                │
  │                              │── trigger workflow ────────► │──── submit ──► │
  │                              │                              │                │
  │                              │                              │◄─── result ────│
  │                              │◄── webhook ─────────────────│                │
  │                              │                              │                │
  │ ◄── RPC: mark as issued ────│ (on acceptance)              │                │
  │ ◄── RPC: mark as rejected ──│ (on rejection)               │                │
```

* **CDC** (Change Data Capture): LVDAM publishes invoice changes as events. Abacus consumes these to keep its internal representation of each document up to date.
* **RPC**: Abacus calls LVDAM's HTTP endpoints to trigger state transitions (e.g. moving a document from draft to issuing, or from issuing to rejected).

## Workspace Configuration

E-invoicing is enabled per workspace. Each workspace that uses e-invoicing stores:

* An encrypted **Invopop API token**
* A **workflow ID** (which Invopop processing pipeline to use)
* A **company ID** (the supplier's UUID in Invopop, representing the business entity submitting invoices)

When the system issues a document, it checks whether the workspace has e-invoicing configured. If not, the document follows the standard flow (draft to issued with no Verifactu submission).

> **Note:** There is no PMS UI to configure these settings yet. Configuration is currently done manually in staging only.

## Current Scope

| Supported                                                           | Not yet supported                     |
| ------------------------------------------------------------------- | ------------------------------------- |
| Regular invoices (F1)                                               | Credit notes via e-invoicing          |
| Spain / Verifactu                                                   | Other countries or tax systems        |
| Individual and company recipients                                   | Automatic retry of failed submissions |
| Spanish ID types (DNI, NIE) and foreign IDs (passport, national ID) | PMS UI for workspace configuration    |

### Credit Notes

The infrastructure for credit note references exists, and the GOBL conversion logic for credit notes has been prototyped. However, credit notes are not yet wired into the e-invoicing submission pipeline. This is tracked in the backlog.

### Corrective Invoices

Spanish corrective invoices (facturas rectificativas) are handled through the standard business process: issue a credit note to cancel the original invoice, then issue a new invoice as the corrected version. No special document type is needed.

## Related Resources

* [Reference](/finance-and-accounting/overview/reference.md) covers the full architecture, implementation details, known issues, and backlog
* [https://github.com/lavanda-uk/nimbus/blob/main/docs/finance-and-accounting/e-invoicing/invopop.md](https://github.com/lavanda-uk/nimbus/blob/main/docs/finance-and-accounting/e-invoicing/invopop.md "mention") documents the Invopop API, GOBL format examples, and common error scenarios
* [PLU-778](https://getlavanda.atlassian.net/browse/PLU-778) is the Jira epic tracking all e-invoicing work


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.lavanda.app/finance-and-accounting/overview.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
