Tax reports
Generate Modelo 303, 347 and 130, choose the right output format, and tell the file you submit apart from the workbook you review.
A tax report is a filing computed from your own invoicing data for a fiscal period and materialised as a file. Factuarea covers the three Spanish models that a company issuing invoices files on its own behalf, produces each one in three formats, and keeps every generation in a history you can list, audit and download again.
All endpoints live under https://api.factuarea.com/v1. Generating uses
tax_reports:write; previewing, listing and downloading use tax_reports:read.
The three models
| Model | What it declares | Period | Endpoint |
|---|---|---|---|
| Modelo 303 | Quarterly IVA: output VAT, equivalence surcharge, intra-EU acquisitions, reverse charge, deductible input VAT and the resulting balance. | Year + quarter | POST /v1/tax_reports/303 |
| Modelo 347 | Annual operations with third parties above 3,005.06 € per counterparty and year, split into the four quarters. | Year only | POST /v1/tax_reports/347 |
| Modelo 130 | Quarterly IRPF instalment for the self-employed under direct estimation. The calculation is cumulative from 1 January to the end of the quarter. | Year + quarter | POST /v1/tax_reports/130 |
year and format are required on all three. quarter is required by 303 and
130, and ignored by 347 — the 347 is annual, and there is no such thing as a
quarterly one. Supported fiscal years start at 2024.
curl -X POST https://api.factuarea.com/v1/tax_reports/303 \
-H "Authorization: Bearer $FACTUAREA_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "year": 2026, "quarter": 1, "format": "txt_aeat" }'Modelo 131 (objective estimation, the "módulos" regime) is out of scope. A
company on that regime asking for a 130 gets 422 with a message pointing at
the 131 instead of a file it could not file.
Three formats, one calculation
Every model produces the same three outputs, and all three are built from the same domain calculation. They differ in what they are for, not in what they say.
format | What it is | Can you file it? |
|---|---|---|
txt_aeat | The official positional file that follows the AEAT record layout of the model's ministerial order. | Yes — this is the one you submit. |
pdf | A readable rendering of the filing, for archiving and for sending to a client or an advisor. | No. |
excel | A working workbook (.xlsx) for reviewing and reconciling the figures before filing. | No. |
Only txt_aeat is filed with the AEAT. The PDF and the spreadsheet are
review material: they are never uploaded to the Sede Electrónica and never
replace the official file in any procedure.
That said — and this is the other half of the rule — the figures in the PDF and in the workbook are trustworthy. They are not recomputed for the presentation layer: they come from the very same calculation that produces the official file, so reconciling against them is reconciling against what you will file. A number that differed between two formats of the same filing is impossible by construction.
The Excel workbook
The workbook has exactly two sheets — Resumen (summary) and Detalle
(detail) — and both open with the same context label: model, fiscal period and
the declaring company with its NIF. A sheet gets copied into another workbook or
printed on its own, and none of the surrounding application context travels
with it.
The first rows of Resumen, before any data, carry the notice in Spanish:
AVISO: este libro es material de trabajo y NO es presentable ante la AEAT.
La presentación se realiza con el fichero oficial en formato TXT que genera
la propia aplicación.The warning lives inside the file on purpose. The workbook is downloaded, attached to an email and opened on a different computer — which is exactly where someone might try to file it. A warning that only existed on the screen that triggered the download would not be there at that moment.
What each model puts in each sheet:
| Model | Resumen | Detalle |
|---|---|---|
| 347 | Declared clients and suppliers, total declared amount, and how many counterparties cleared the 3,005.06 € threshold. | One row per counterparty: type, NIF, name, province, country, annual base and the four quarters. Clients first, then suppliers — the same order as the official file's records. |
| 303 | Accrued base and tax, surcharge, intra-EU, reverse charge, corrective entries, deductible input VAT, carried-forward credit and the resulting balance. | Accrued VAT and surcharge broken down by tax rate, plus eleven fixed blocks that are always emitted, zeros included. |
| 130 | The derived boxes: the chain that ends in the amount payable. | The starting boxes that feed them, so the result is traceable without redoing the arithmetic. |
Two properties worth relying on:
- Amounts are numbers, not formatted text. A column of amounts can be summed
in the sheet with no conversion, and a zero is written as
0rather than left blank — in a financial report an empty cell reads as "no data", not as "zero". - In every 347 row, the four quarters add up to the annual base. The
Tipocolumn is what tells a purchase from a sale once you sort the sheet.
A year with no counterparty above the threshold still produces a workbook: the detail sheet comes back empty and the summary says so, quoting the threshold. That is the ordinary case for a small company, not an error — you should not have to guess whether the calculation ran.
Generate, download, keep the history
A generation is a persisted resource. The three model endpoints return 201
with the report and its id; the file itself is fetched separately, as many
times as you need.
# 1. Generate — returns 201 with the report id
curl -X POST https://api.factuarea.com/v1/tax_reports/347 \
-H "Authorization: Bearer $FACTUAREA_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "year": 2025, "format": "excel" }'
# 2. Download the file it produced
curl -G https://api.factuarea.com/v1/tax_reports/01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a0b/download \
-H "Authorization: Bearer $FACTUAREA_API_KEY" \
--output modelo-347-2025.xlsxGET /v1/tax_reports/{tax_report}/download streams the file with the content
type of the format it was generated in — positional text, PDF or spreadsheet —
and adds an X-Tax-Report-Hash header so you can verify that the bytes you
archived are the bytes that were generated.
The rest of the domain reads that same history:
| Endpoint | What it gives you |
|---|---|
GET /v1/tax_reports/history | Every generation of the company, newest first, filterable by type and year, with cursor pagination. |
POST /v1/tax_reports/find-by-period | The most recent generation for a type + year (+ quarter), or 404 if the period has never been generated. |
GET /v1/tax_reports/stats | Aggregate KPIs: totals by model and by format, accumulated file size and the current fiscal period. |
GET /v1/tax_reports/{tax_report}/activities | The activity timeline of one generation — when it was generated and by whom. |
To see the numbers before committing to a file, use
POST /v1/tax_reports/preview with type, year and quarter: it computes the
same breakdown, persists nothing and writes no file. It is the call to make
behind a "review before filing" screen.
Errors you should expect
| Status | code | When |
|---|---|---|
422 | invalid_period | Year outside the supported range, or a missing/invalid quarter for a model that needs one. |
422 | insufficient_data_for_report | The period has nothing to file, or an invoice in it lacks a field the model requires. |
422 | unsupported_format | The model does not produce that format for that fiscal year. |
422 | report_format_invalid | format outside txt_aeat, pdf, excel. |
422 | tax_report_type_invalid | type outside modelo_303, modelo_347, modelo_130. |
404 | tax_report_not_found | The id does not resolve to a report of your company. |
Full reference in All error codes.
From an agent
The same nine operations are exposed as MCP tools —
generate_tax_report_303, generate_tax_report_347 and
generate_tax_report_130 under tax_reports:write, and preview, find-by-period,
history, stats, activities and download under tax_reports:read. See the
tool catalog.
Next steps
end-to-end recipes for Spanish filings.
the regimes that shape what these models declare.
request and response schemas.