Set up your taxpayer profile¶
A profile holds the facts about one taxpayer that every aeat app command reads
and updates. Set one up before you import transactions, calculate a modelo,
or export a filing.
A profile is local. Creating, editing, showing, exporting, or importing a profile never submits anything to the Agencia Estatal de Administración Tributaria (AEAT). Cadrumo builds and verifies your filing on your machine; you upload it yourself.
If you haven’t installed Cadrumo and run the aeat command yet, start with the
quickstart, then come back here.
What the active profile means¶
The active profile is the taxpayer context for aeat app commands. While a
profile is active, commands such as ledger import, transaction classification,
modelo calculation, export, and local filing history read and update that
profile’s data.
Keep one profile per taxpayer. Add a second profile when you prepare filings for another taxpayer, separate a test profile from a real one, or restore a copy under a different name. To understand why the tool is local-first and human-gated, see the explanation guides.
List your profiles with aeat config profile list and see which one is active.
Create each additional taxpayer interactively so its passphrase is chosen at
the terminal, then switch by exact name. The executable example checks the
current active-profile composition without fabricating another taxpayer:
aeat --format json config profile listaeat --format json config profile list{ "active_profile": "docs-sequence-sandbox", "command": "config.profile.list", "notices": [], "result": { "active_profile": "docs-sequence-sandbox", "profiles": [ { "active": true, "bucket_id": "<bucket-id>", "name": "docs-sequence-sandbox" } ] }, "schema_version": "2", "status": "success" }
Confirm the profile list identifies the active taxpayer exactly.
Logging in changes which local ledger, modelo drafts, and filing markers aeat app commands use. The login verb is aeat config login, not aeat config profile login.
Name the profile exactly. aeat config login accepts a profile UUID or the
exact label, and nothing else: a partial name, a different capitalisation, or a
shortened form is refused rather than guessed at. Omit the name to log in to
the profile already selected. The refusal is deliberate - guessing which
taxpayer you meant is how filings end up under the wrong one.
Log out with aeat config logout when you finish. Logout closes the storage
session but keeps the profile selected for the next exact login; it deletes
nothing.
Decide your facts before you start¶
Profile setup asks a series of questions. Most are conditional: the answers you give early decide which later questions appear. Decide these facts first, and the rest of setup follows:
Who the taxpayer is. A natural person (an individual), a legal entity (a company such as an SL or SA), or an attribution entity (a co-ownership such as a comunidad de bienes, where income passes through to its members).
Which tax identifier applies. Spanish citizens use their DNI as their tax identifier (NIF). Foreign individuals use their NIE. Companies use a NIF or CIF.
What the taxpayer does. The economic activity and which kinds of income apply: business or professional activity, salaried work, rental income, investment income, capital gains, or a pension.
Which VAT regime applies. Value Added Tax (IVA) determines whether the taxpayer charges and declares it, and how. The general regime files IVA through Modelo 303.
Where the taxpayer is resident. The autonomous community for a Spanish resident, or the country of residence for a non-resident.
Which output language you want. The language
cadrumouses for its output.
You don’t need to memorize flag names. The guided wizard walks you through these
decisions. For the complete, current list of flags and their accepted values,
run aeat config profile create --help and aeat config profile edit --help:
aeat config profile create --helpaeat config profile create --helpUsage: aeat config profile create [OPTIONS] [profile_name]
Create a profile protected by a passphrase. At a terminal it then offers an
optional recovery code; skip it, or add it later with 'aeat config profile
recovery enable'.
Arguments:
profile_name Profile name to write the answers into
Options:
--quiet Run non-interactively using only the
supplied flag values; required flags left
unset cause an error. Sufficient on its own;
combine with --accept-defaults to fill the
rest from descriptor defaults.
--accept-defaults Fill every unsupplied flag from the
descriptor defaults, without prompting. Use
alongside --quiet, or on its own for an all-
defaults create.
--output-language <es|en|ca|hu>
CLI output language for this profile
--entity-type <str> Natural person, legal entity, or attribution
entity
--legal-entity-form <str> Recognised legal form when the entity type
is a legal entity
--tax-id <str> Tax identifier (NIF/CIF/DNI/NIE) for the
active profile
--name <str> Display name shown in local reviews
--surnames <str> Surnames or company name for export headers
--legal-name <str> Legal or company name for legal-entity
export headers
--fiscal-residency <str> Fiscal residency category: resident_irpf
(habitual resident in Spain) or
non_resident_irnr (non-resident, IRNR
taxation RDLeg 5/2004).
--country-of-fiscal-residence <str>
ISO 3166-1 alpha-2 code of the country of
fiscal residence (e.g. GB, DE, FR). Required
when fiscal-residency is non_resident_irnr.
--representante-fiscal-nif <str>
NIF/NIE of the fiscal representative in
Spain. Required for non-EU/EEA non-residents
(Art. 47 LGT + Art. 10 TRLIRNR RDLeg
5/2004).
--representante-fiscal-nombre <str>
Full name of the fiscal representative in
Spain.
--tax-residence-jurisdiction-scope <str>
Declared territorial regime: common
territory or the not-yet-supported foral
territory.
--tax-residence-ccaa <str> Tax-residence autonomous community, under
the common regime. If the value is not
recognised, the error lists the accepted
communities.
--address-postcode <str> Tax address postcode
--irpf-income-categories <str> IRPF income category; pass --irpf-income-
categories once per category
--activity <str> Business activity as plain text, or the IAE
heading if you know it
--activity-start-date <str> Censo registration / start-of-activity date
(YYYY-MM-DD). Optional; when set,
obligations for periods before this date are
not shown.
--incn-prior-12-months <str> Net turnover (importe neto de la cifra de
negocios) over the prior 12 months, in
euros. Above 6,000,000 EUR Modelo 202
mandates the Art. 40.3 LIS modality; below
it both modalities are available. Optional.
--new-entity-first-two-profit-periods / --no-new-entity-first-two-profit-periods
Mark this when a newly-created legal entity
is in one of its first two profit-making tax
periods (LIS Art. 29) to opt into the 15
percent reduced rate. Optional; unset leaves
the entity on its otherwise-applicable rate.
--ley-49-2002-option-declared / --no-ley-49-2002-option-declared
Record whether Modelo 036 casilla 651
declares the Ley 49/2002 Title II option.
--ley-49-2002-option-date <str>
Record the Modelo 036 casilla 653 date for
the Ley 49/2002 Title II option.
--ley-49-2002-renunciation-declared / --no-ley-49-2002-renunciation-declared
Record whether Modelo 036 casilla 652
declares renunciation of the Ley 49/2002
Title II regime.
--ley-49-2002-renunciation-date <str>
Record the Modelo 036 casilla 654 date for
the Ley 49/2002 Title II renunciation.
--iva-regime <str> IVA regime
--iva-m303-regime-composition <str>
Modelo 303 regime composition: general,
simplified, or mixed.
--iva-roi-enrolled / --no-iva-roi-enrolled
Enrolled in ROI
--iva-oss-enrolled / --no-iva-oss-enrolled
Enrolled in OSS
--iva-group-member-enrolled / --no-iva-group-member-enrolled
Enrolled as a member entity of an IVA group
--iva-group-dominant-entity-enrolled / --no-iva-group-dominant-entity-enrolled
Enrolled as the dominant entity of an IVA
group
--iva-sii-enrolled / --no-iva-sii-enrolled
Whether the taxpayer is enrolled in the SII
--iva-redeme-enrolled / --no-iva-redeme-enrolled
Whether the taxpayer is registered in REDEME
--iva-intracommunity-operations-exceed-50000-eur / --no-iva-intracommunity-operations-exceed-50000-eur
Intra-community operations exceed 50,000 EUR
--iva-cash-accounting-regime-enrolled / --no-iva-cash-accounting-regime-enrolled
Declare enrolment in the special IVA cash-
accounting regime.
--iva-voluntary-sii-enrolled / --no-iva-voluntary-sii-enrolled
Declare voluntary SII enrolment separately
from mandatory inclusion triggers.
--iva-hydrocarbon-deposit-advance-payment-deduction-entitled / --no-iva-hydrocarbon-deposit-advance-payment-deduction-entitled
Declare entitlement to deduct advance
payments under the hydrocarbon tax-deposit
regime.
--enrollment-large-company / --no-enrollment-large-company
Large-company enrollment
--enrollment-public-administration-budget-gt-6000000 / --no-enrollment-public-administration-budget-gt-6000000
Public administration budget over 6,000,000
--taxation-type <str> Income-tax return type: 1 = individual, 2 =
joint (family unit).
--taxpayer-sex <str> First taxpayer sex: H = male, M = female.
--taxpayer-marital-status <1|2|3|4|5>
First taxpayer marital status: 1 = single, 2
= married, 3 = widowed, 4 = separated or
divorced, 5 = registered civil partnership.
--situacion-familiar <casado|pareja_hecho_registrada|pareja_hecho_no_registrada|soltero|separado_divorciado>
Family situation under Art. 82 LIRPF:
determines whether joint taxation is
available and which family unit variant
applies.
--taxpayer-marriage-date <str> Start date of the current marriage (YYYY-MM-
DD). Only when marital status = 2 (married).
Derives casillas 0245/0246/0247 (matrimonio
sobrevenido, Art. 82 LIRPF).
--taxpayer-birth-date <str> First taxpayer birth date
--taxpayer-disability-grade <str>
First taxpayer disability grade: 1 =
33%-64%, 2 = 65% or higher, 3 = judicial
incapacity, 4 = third-party assistance or
reduced mobility.
--taxpayer-death-date <str> First taxpayer death date
--spouse-tax-id <str> Spouse NIF/NIE
--spouse-name <str> Spouse given name
--spouse-surnames <str> Spouse surnames
--spouse-birth-date <str> Spouse birth date
--spouse-sex <str> Spouse sex: H = male, M = female.
--spouse-disability-grade <str>
Spouse disability grade (if applicable): 1 =
33%-64%, 2 = 65% or higher, 3 = judicial
incapacity, 4 = third-party assistance or
reduced mobility.
--spouse-non-resident-irpf / --no-spouse-non-resident-irpf
Spouse is non-resident IRPF
--spouse-eu-eea-resident / --no-spouse-eu-eea-resident
Spouse is EU/EEA resident
--spouse-eu-eea-country <str> Spouse EU/EEA country
--family-descendants-eu-eea-deduction / --no-family-descendants-eu-eea-deduction
EU/EEA descendants in family-unit deduction
--family-minor-children-in-unit / --no-family-minor-children-in-unit
Minor children in family unit
--has-employees / --no-has-employees
Has employees and pays salaries with
retención
--pays-professionals-with-retencion / --no-pays-professionals-with-retencion
Pays professionals with retención
--art109-activity-income-withholding-ge-70pct / --no-art109-activity-income-withholding-ge-70pct
Art. 109 coverage - at least 70% of covered
professional, agricultural, livestock, or
forestry activity income subject to
withholding or payment on account
--pays-rent-with-retencion / --no-pays-rent-with-retencion
Pays local rent with retención
--pays-capital-income-with-retencion / --no-pays-capital-income-with-retencion
Pays capital income with retención
--modelo-111-no-retenciones-periods <str>
Comma-separated Modelo 111 no-obligation
periods, format YYYY:PERIOD (for example
2025:2T,2025:3T). Use only when no subject
payments were made.
--irpf-estimation-regime <str> IRPF estimation regime for economic-activity
income
--objective-estimation-modulos-iae-epigraph <str>
IAE epigraph for objective-estimation
modules, such as 972.
--objective-estimation-modulos-module-1-units <str>
Annual module 1 units for objective-
estimation modules.
--objective-estimation-modulos-module-2-units <str>
Annual module 2 units for objective-
estimation modules.
--objective-estimation-modulos-module-3-units <str>
Annual module 3 units for objective-
estimation modules.
--objective-estimation-modulos-module-4-units <str>
Annual module 4 units for objective-
estimation modules.
--objective-estimation-modulos-module-5-units <str>
Annual module 5 units for objective-
estimation modules.
--objective-estimation-modulos-module-6-units <str>
Annual module 6 units for objective-
estimation modules.
--objective-estimation-modulos-module-7-units <str>
Annual module 7 units for objective-
estimation modules.
--irpf-special-regime <str> IRPF special regime. "general" for most
taxpayers. "impatriado" for workers who
relocated to Spain and elected the Beckham
Law regime (Art. 93 LIRPF), available for
the first 6 years after relocation.
--irpf-special-regime-start-date <str>
Date the worker elected the inpatriate
regime (YYYY-MM-DD). Only when irpf-special-
regime is "impatriado". RIRPF Art. 116. The
regime expires at the end of the 6th
calendar year.
--does-intracomunitario / --no-does-intracomunitario
Conducts intracomunitario operations
--third-party-transactions-above-347-threshold / --no-third-party-transactions-above-347-threshold
Third-party transactions exceed Modelo 347
threshold
--bienes-extranjero-above-threshold / --no-bienes-extranjero-above-threshold
Foreign-held assets above legal threshold
--monedas-virtuales-extranjero-above-threshold / --no-monedas-virtuales-extranjero-above-threshold
Virtual currencies held abroad above Modelo
721 threshold
--llm-vision / --no-llm-vision Enable on-host LLM vision for reading
invoices.
--google-export / --no-google-export
Enable Google Sheets export.
--notes <str> Notes for your own records (optional)
--secrets-stdin Read the secrets as one bounded JSON object
from standard input instead of prompting.
--secrets-fd <int> File descriptor to read machine secrets
from.
--install-completion Install completion for the current shell.
--show-completion Show completion for the current shell, to
copy it or customize the installation.
--help Show this message and exit.
aeat config profile edit --helpaeat config profile edit --helpUsage: aeat config profile edit [OPTIONS] [profile_name]
Re-run the wizard against an existing profile and update values in place
Arguments:
profile_name Profile name to write the answers into
Options:
--quiet Run non-interactively using only the
supplied flag values; required flags left
unset cause an error. Sufficient on its own;
combine with --accept-defaults to fill the
rest from descriptor defaults.
--accept-defaults Fill every unsupplied flag from the
descriptor defaults, without prompting. Use
alongside --quiet, or on its own for an all-
defaults create.
--output-language <es|en|ca|hu>
CLI output language for this profile
--entity-type <str> Natural person, legal entity, or attribution
entity
--legal-entity-form <str> Recognised legal form when the entity type
is a legal entity
--tax-id <str> Tax identifier (NIF/CIF/DNI/NIE) for the
active profile
--name <str> Display name shown in local reviews
--surnames <str> Surnames or company name for export headers
--legal-name <str> Legal or company name for legal-entity
export headers
--fiscal-residency <str> Fiscal residency category: resident_irpf
(habitual resident in Spain) or
non_resident_irnr (non-resident, IRNR
taxation RDLeg 5/2004).
--country-of-fiscal-residence <str>
ISO 3166-1 alpha-2 code of the country of
fiscal residence (e.g. GB, DE, FR). Required
when fiscal-residency is non_resident_irnr.
--representante-fiscal-nif <str>
NIF/NIE of the fiscal representative in
Spain. Required for non-EU/EEA non-residents
(Art. 47 LGT + Art. 10 TRLIRNR RDLeg
5/2004).
--representante-fiscal-nombre <str>
Full name of the fiscal representative in
Spain.
--tax-residence-jurisdiction-scope <str>
Declared territorial regime: common
territory or the not-yet-supported foral
territory.
--tax-residence-ccaa <str> Tax-residence autonomous community, under
the common regime. If the value is not
recognised, the error lists the accepted
communities.
--address-postcode <str> Tax address postcode
--irpf-income-categories <str> IRPF income category; pass --irpf-income-
categories once per category
--activity <str> Business activity as plain text, or the IAE
heading if you know it
--activity-start-date <str> Censo registration / start-of-activity date
(YYYY-MM-DD). Optional; when set,
obligations for periods before this date are
not shown.
--incn-prior-12-months <str> Net turnover (importe neto de la cifra de
negocios) over the prior 12 months, in
euros. Above 6,000,000 EUR Modelo 202
mandates the Art. 40.3 LIS modality; below
it both modalities are available. Optional.
--new-entity-first-two-profit-periods / --no-new-entity-first-two-profit-periods
Mark this when a newly-created legal entity
is in one of its first two profit-making tax
periods (LIS Art. 29) to opt into the 15
percent reduced rate. Optional; unset leaves
the entity on its otherwise-applicable rate.
--ley-49-2002-option-declared / --no-ley-49-2002-option-declared
Record whether Modelo 036 casilla 651
declares the Ley 49/2002 Title II option.
--ley-49-2002-option-date <str>
Record the Modelo 036 casilla 653 date for
the Ley 49/2002 Title II option.
--ley-49-2002-renunciation-declared / --no-ley-49-2002-renunciation-declared
Record whether Modelo 036 casilla 652
declares renunciation of the Ley 49/2002
Title II regime.
--ley-49-2002-renunciation-date <str>
Record the Modelo 036 casilla 654 date for
the Ley 49/2002 Title II renunciation.
--iva-regime <str> IVA regime
--iva-m303-regime-composition <str>
Modelo 303 regime composition: general,
simplified, or mixed.
--iva-roi-enrolled / --no-iva-roi-enrolled
Enrolled in ROI
--iva-oss-enrolled / --no-iva-oss-enrolled
Enrolled in OSS
--iva-group-member-enrolled / --no-iva-group-member-enrolled
Enrolled as a member entity of an IVA group
--iva-group-dominant-entity-enrolled / --no-iva-group-dominant-entity-enrolled
Enrolled as the dominant entity of an IVA
group
--iva-sii-enrolled / --no-iva-sii-enrolled
Whether the taxpayer is enrolled in the SII
--iva-redeme-enrolled / --no-iva-redeme-enrolled
Whether the taxpayer is registered in REDEME
--iva-intracommunity-operations-exceed-50000-eur / --no-iva-intracommunity-operations-exceed-50000-eur
Intra-community operations exceed 50,000 EUR
--iva-cash-accounting-regime-enrolled / --no-iva-cash-accounting-regime-enrolled
Declare enrolment in the special IVA cash-
accounting regime.
--iva-voluntary-sii-enrolled / --no-iva-voluntary-sii-enrolled
Declare voluntary SII enrolment separately
from mandatory inclusion triggers.
--iva-hydrocarbon-deposit-advance-payment-deduction-entitled / --no-iva-hydrocarbon-deposit-advance-payment-deduction-entitled
Declare entitlement to deduct advance
payments under the hydrocarbon tax-deposit
regime.
--enrollment-large-company / --no-enrollment-large-company
Large-company enrollment
--enrollment-public-administration-budget-gt-6000000 / --no-enrollment-public-administration-budget-gt-6000000
Public administration budget over 6,000,000
--taxation-type <str> Income-tax return type: 1 = individual, 2 =
joint (family unit).
--taxpayer-sex <str> First taxpayer sex: H = male, M = female.
--taxpayer-marital-status <1|2|3|4|5>
First taxpayer marital status: 1 = single, 2
= married, 3 = widowed, 4 = separated or
divorced, 5 = registered civil partnership.
--situacion-familiar <casado|pareja_hecho_registrada|pareja_hecho_no_registrada|soltero|separado_divorciado>
Family situation under Art. 82 LIRPF:
determines whether joint taxation is
available and which family unit variant
applies.
--taxpayer-marriage-date <str> Start date of the current marriage (YYYY-MM-
DD). Only when marital status = 2 (married).
Derives casillas 0245/0246/0247 (matrimonio
sobrevenido, Art. 82 LIRPF).
--taxpayer-birth-date <str> First taxpayer birth date
--taxpayer-disability-grade <str>
First taxpayer disability grade: 1 =
33%-64%, 2 = 65% or higher, 3 = judicial
incapacity, 4 = third-party assistance or
reduced mobility.
--taxpayer-death-date <str> First taxpayer death date
--spouse-tax-id <str> Spouse NIF/NIE
--spouse-name <str> Spouse given name
--spouse-surnames <str> Spouse surnames
--spouse-birth-date <str> Spouse birth date
--spouse-sex <str> Spouse sex: H = male, M = female.
--spouse-disability-grade <str>
Spouse disability grade (if applicable): 1 =
33%-64%, 2 = 65% or higher, 3 = judicial
incapacity, 4 = third-party assistance or
reduced mobility.
--spouse-non-resident-irpf / --no-spouse-non-resident-irpf
Spouse is non-resident IRPF
--spouse-eu-eea-resident / --no-spouse-eu-eea-resident
Spouse is EU/EEA resident
--spouse-eu-eea-country <str> Spouse EU/EEA country
--family-descendants-eu-eea-deduction / --no-family-descendants-eu-eea-deduction
EU/EEA descendants in family-unit deduction
--family-minor-children-in-unit / --no-family-minor-children-in-unit
Minor children in family unit
--has-employees / --no-has-employees
Has employees and pays salaries with
retención
--pays-professionals-with-retencion / --no-pays-professionals-with-retencion
Pays professionals with retención
--art109-activity-income-withholding-ge-70pct / --no-art109-activity-income-withholding-ge-70pct
Art. 109 coverage - at least 70% of covered
professional, agricultural, livestock, or
forestry activity income subject to
withholding or payment on account
--pays-rent-with-retencion / --no-pays-rent-with-retencion
Pays local rent with retención
--pays-capital-income-with-retencion / --no-pays-capital-income-with-retencion
Pays capital income with retención
--modelo-111-no-retenciones-periods <str>
Comma-separated Modelo 111 no-obligation
periods, format YYYY:PERIOD (for example
2025:2T,2025:3T). Use only when no subject
payments were made.
--irpf-estimation-regime <str> IRPF estimation regime for economic-activity
income
--objective-estimation-modulos-iae-epigraph <str>
IAE epigraph for objective-estimation
modules, such as 972.
--objective-estimation-modulos-module-1-units <str>
Annual module 1 units for objective-
estimation modules.
--objective-estimation-modulos-module-2-units <str>
Annual module 2 units for objective-
estimation modules.
--objective-estimation-modulos-module-3-units <str>
Annual module 3 units for objective-
estimation modules.
--objective-estimation-modulos-module-4-units <str>
Annual module 4 units for objective-
estimation modules.
--objective-estimation-modulos-module-5-units <str>
Annual module 5 units for objective-
estimation modules.
--objective-estimation-modulos-module-6-units <str>
Annual module 6 units for objective-
estimation modules.
--objective-estimation-modulos-module-7-units <str>
Annual module 7 units for objective-
estimation modules.
--irpf-special-regime <str> IRPF special regime. "general" for most
taxpayers. "impatriado" for workers who
relocated to Spain and elected the Beckham
Law regime (Art. 93 LIRPF), available for
the first 6 years after relocation.
--irpf-special-regime-start-date <str>
Date the worker elected the inpatriate
regime (YYYY-MM-DD). Only when irpf-special-
regime is "impatriado". RIRPF Art. 116. The
regime expires at the end of the 6th
calendar year.
--does-intracomunitario / --no-does-intracomunitario
Conducts intracomunitario operations
--third-party-transactions-above-347-threshold / --no-third-party-transactions-above-347-threshold
Third-party transactions exceed Modelo 347
threshold
--bienes-extranjero-above-threshold / --no-bienes-extranjero-above-threshold
Foreign-held assets above legal threshold
--monedas-virtuales-extranjero-above-threshold / --no-monedas-virtuales-extranjero-above-threshold
Virtual currencies held abroad above Modelo
721 threshold
--llm-vision / --no-llm-vision Enable on-host LLM vision for reading
invoices.
--google-export / --no-google-export
Enable Google Sheets export.
--notes <str> Notes for your own records (optional)
--install-completion Install completion for the current shell.
--show-completion Show completion for the current shell, to
copy it or customize the installation.
--help Show this message and exit.
aeat --format json config profile statusaeat --format json config profile status{ "active_profile": "docs-sequence-sandbox", "command": "config.profile.status", "notices": [], "result": { "active_profile": "docs-sequence-sandbox", "activity_present": true, "configured": true, "iva_regime": "GENERAL", "precondition_action": null, "profile_id": "<profile-id>", "profile_record_error": null, "profile_record_present": null, "registered_profile": null, "tax_id_present": true, "tax_residence_ccaa": "" }, "schema_version": "2", "status": "success" }
Confirm both flag listings run and name the active profile the flags apply to.
Create your profile¶
Create a profile interactively, or non-interactively with flags.
Run the guided wizard when you’re setting up a profile for the first time:
aeat config profile create my-profileaeat config profile create my-profileThe wizard is a full-page, question-by-question walk. Answer one page, move to the next; go back to change an earlier answer at any time. The first page asks for your output language. Answer it and the rest of the wizard renders in the language you chose. The pages then walk your identity, fiscal residence, economic activity, IVA, enrollment, family situation (including your descendientes), recurring obligations, and service preferences, ending on a review page that shows every answer before anything is committed. Questions are conditional: the wizard only asks what applies to the answers you already gave.
Each page explains its choices and shows the expected format for dates, amounts, and identifiers, and refuses an invalid value on the spot. A malformed date or tax identifier never reaches your stored profile.
The wizard prompts for the profile passphrase before it stores anything. Once the profile exists it asks whether to set up an optional recovery code, which can reset a forgotten passphrase; answering no is the default and you can enable it later. See protect access to your data.
For unattended runs, supply the passphrase through the machine channel described in Run without a passphrase prompt; recovery is never offered on that path.
Use --language en, es, ca, or hu for one command. A profile can also
store its default output language.
Save now, finish later¶
Stop a first-time setup at any point and keep what you answered. Choose save
and exit on any page: every answer you gave is already stored, and the profile
stays marked as setup-incomplete. After unlocking it, aeat config profile show reports that setup state; profile list deliberately reports only the
saved names and which profile is active.
Resume by running the same create command again with the same profile name.
The wizard picks up where you left off with your earlier answers in place.
Answer the remaining pages and confirm the review page to complete setup. The
profile then becomes active and ready for aeat app commands.
Descendientes are the one exception on resume: the wizard asks for them again so the set you confirm is always complete and current.
Use flags with --quiet when you want a repeatable, scriptable setup, passing
the entity type, tax id, name, and surnames to aeat config profile create. The
worked example below runs a
complete scripted create.
--quiet runs without prompts and uses only the flags you provide. A --quiet
run refuses if a required flag is missing and tells you which ones to add. A
scripted create needs the filing identity: the tax identifier, the entity type,
and the name and surnames:
Refused. Profile creation is missing filing identity details. Add these flags
and run the command again: --entity-type --name --surnames.
Add --accept-defaults when you intentionally want Cadrumo to fill the questions
you omit from its built-in defaults.
Worked example: a natural person with an activity¶
This example creates a natural-person profile for an individual with an economic activity, then inspects and validates it before you rely on it:
aeat config profile view docs-sequence-sandboxaeat config profile view docs-sequence-sandboxProfile record is valid. record_validity valid issues=0 profile_id <profile-id> display_name docs-sequence-sandbox setup_state complete activities.description documentation examples identity.name Docs identity.surnames Sandbox identity.tax_id sha256:1c9f9632 iva.cash_accounting_regime_enrolled false iva.hydrocarbon_deposit_advance_payment_deduction_entitled false iva.m303_regime_composition general iva.redeme_enrolled false iva.regime GENERAL iva.voluntary_sii_enrolled false tax_residence.jurisdiction_scope common_regime taxpayer_type.entity_type natural_person
aeat --format json config profile validate docs-sequence-sandboxaeat --format json config profile validate docs-sequence-sandbox{ "active_profile": "docs-sequence-sandbox", "command": "config.profile.validate", "notices": [], "result": { "display_name": "docs-sequence-sandbox", "issues": [], "profile_id": "<profile-id>", "schema_version": 6, "setup_state": "complete", "valid": true }, "schema_version": "2", "status": "success" }
Confirm the scripted create produces a natural-person profile that validates.
The facts setup asks for¶
Setup groups its questions by decision area. These values are stable command
tokens: they’re case-sensitive and don’t translate. Run
aeat config profile create --help for the exhaustive flag list. It includes the
conditional spouse, family-unit, non-resident, and enrollment questions this
guide summarizes rather than repeats.
Who the taxpayer is¶
Choose the entity type:
natural_person- an individual.legal_entity- a company. Record its legal form too, such assl,sa, orcooperativa.attribution_entity- a co-ownership or community of goods whose income is attributed to its members.
For a natural person, list each kind of income that applies, repeating the flag once per category:
actividad_economica- business or professional activity.trabajo- salaried employment.capital_inmobiliario- rental income from property.capital_mobiliario- investment income such as dividends or interest.ganancias_patrimoniales- capital gains.pension- a retirement or disability pension.
Choose actividad_economica only when the taxpayer runs an activity. A pure
landlord, a salaried-only taxpayer, or a pensioner with no activity should not
select it.
For an activity, record how IRPF estimates its yield. Direct estimation is the
default and files Modelo 130. Use --irpf-estimation-regime objetiva for the
objective-estimation (módulos) regime, which files Modelo 131 instead.
Identity¶
The tax identifier (NIF, CIF, DNI, or NIE) is required. Spanish citizens use their DNI as their NIF; foreign individuals use their NIE; companies use a NIF or CIF. Record the name and surnames (or the entity’s display name), the economic activity when there is one, and the fiscal-address postcode.
Where the taxpayer is resident¶
For a Spanish IRPF (personal income tax) resident, set the autonomous community
(--tax-residence-ccaa), such as madrid or cataluna.
This tool does not model the foral regimes. Setting the community to
pais_vasco or navarra is refused, because residents there file with their
Hacienda Foral under the Concierto Económico, not with the AEAT:
Invalid value for '--tax-residence-ccaa': Residents in pais_vasco file with the
corresponding Hacienda Foral under the Concierto Económico (Ley 12/2002), not
with the AEAT. This CLI does not model foral declarations.
For a non-resident, set --fiscal-residency non_resident_irnr (not
--tax-residence-ccaa), then supply the country of residence with
--country-of-fiscal-residence (an ISO 3166-1 alpha-2 code, such as DE) and,
when required, a fiscal representative with --representante-fiscal-nif and
--representante-fiscal-nombre.
Which IVA regime applies¶
Set --iva-regime to the taxpayer’s IVA regime:
GENERAL- the standard regime; files quarterly IVA through Modelo 303.SIMPLIFICADO- the simplified, module-based regime.RECARGO_EQUIVALENCIA- the equivalence surcharge for qualifying retailers.REAGP- the special regime for agriculture, livestock, and fishing.EXENTO- exempt activities, such as some education or healthcare.
Record any IVA enrollments that apply, such as ROI (intra-community operators) or OSS (one-stop-shop for cross-border B2C sales).
Which recurring obligations apply¶
These facts decide which forms the taxpayer must file. Record the ones that are true:
--has-employeesor--pays-professionals-with-retencion- pays salaries or professional fees with withholding.--pays-rent-with-retencion- pays business-premises rent with withholding.--does-intracomunitario- trades with businesses in other EU countries.--third-party-transactions-above-347-threshold- transactions with third parties exceed the Modelo 347 threshold.--bienes-extranjero-above-threshold- foreign assets exceed the legal threshold.--art109-activity-income-withholding-ge-70pct- the Art. 109 RIRPF 70 percent income-coverage exception applies for covered professional, agricultural, livestock, or forestry activity income. For activity starts, record the coverage fact for the current payment period.
Leaving an obligation flag unset is not the same as marking it false. When a fact is undeclared, the readiness check reports the related form as incomplete (cannot determine), not not applicable. Record each fact you know.
Check your facts before you calculate¶
A wrong or missing fact produces a wrong filing. Confirm the profile before you calculate a modelo. The example shows the active profile’s readiness summary and stored facts, validates them against the schema, then checks whether the profile holds the facts a specific form needs for a specific filing context:
aeat config profile statusaeat config profile statusprofile docs-sequence-sandbox profile_id <profile-id> identity.tax_id sha256:1c9f9632 activities.description documentation examples iva.regime GENERAL tax_residence.ccaa <unset> Next step: `aeat app overview status`
aeat config profile viewaeat config profile viewProfile record is valid. record_validity valid issues=0 profile_id <profile-id> display_name docs-sequence-sandbox setup_state complete activities.description documentation examples identity.name Docs identity.surnames Sandbox identity.tax_id sha256:1c9f9632 iva.cash_accounting_regime_enrolled false iva.hydrocarbon_deposit_advance_payment_deduction_entitled false iva.m303_regime_composition general iva.redeme_enrolled false iva.regime GENERAL iva.voluntary_sii_enrolled false tax_residence.jurisdiction_scope common_regime taxpayer_type.entity_type natural_person
aeat config profile validateaeat config profile validatereadiness ready issues=0 profile_id <profile-id> display_name docs-sequence-sandbox setup_state complete schema_version 6 valid True
aeat --format json app modelo readiness --modelo 303 --year 2026 --period 1Taeat --format json app modelo readiness --modelo 303 --year 2026 --period 1T{ "active_profile": "docs-sequence-sandbox", "command": "modelo.readiness", "notices": [ { "action": null, "code": "modelo.readiness.per_operation_axis_not_assessed", "context": { "modelo": "303", "profile_ready": "True" }, "message": "No schema-required profile field is currently declared for Modelo 303, so profile_ready reflects only the export-identity and conditional checks, not a per-modelo assessment. Do not read profile_ready as a complete check for this modelo.", "severity": "warning" }, { "action": null, "code": "modelo.readiness.ledger_preflight_scope", "context": { "binding_ready": "false", "ledger_ready": "true", "missing_bindings": "4" }, "message": "ledger_ready only means the period ledger rows passed transaction preflight; missing_bindings/source_binding_ready still decide source completeness.", "severity": "info" } ], "result": { "binding_ready": false, "filing_year": 2026, "ledger_checked_transaction_count": 0, "ledger_issues": [], "ledger_period": { "code": "1T", "filing_year": 2026 }, "ledger_preflight_required": true, "ledger_ready": true, "missing": [], "missing_bindings": [ { "binding_id": "modelo-303-autoconsumo-promotor-base", "input_channel": "decimal", "source": "profile" }, { "binding_id": "modelo-303-bienes-inversion-regularizacion-casilla-43", "input_channel": "decimal", "source": "bienes_inversion_regularizacion" }, { "binding_id": "modelo-303-compensacion-pendiente-anteriores", "input_channel": "decimal", "source": "previous_filing" }, { "binding_id": "modelo-303-prorrata-regularizacion-casilla-44", "input_channel": "decimal", "source": "prorrata_regularizacion" } ], "modelo": "303", "operation": "modelo.readiness", "period": { "code": "1T", "filing_year": 2026 }, "profile_id": "<profile-id>", "profile_ready": true, "profile_refusal": "", "ready": false, "registry_ready": true, "registry_refusal": "", "revision_id": "2026-y-siguientes" }, "schema_version": "2", "status": "warning" }
Confirm the active profile's facts validate and see what a specific filing still needs.
preflight names the missing fields for that (modelo, filing-year, period)
context. Use Choose which modelo to file to find the period
codes a modelo accepts. Fix any wrong facts with edit before you continue.
How your facts decide which forms apply¶
The profile facts you recorded determine which modelos the taxpayer must file.
Use this mapping to sanity-check your profile, then confirm a specific form with
preflight:
When this is true of the taxpayer |
These forms apply |
|---|---|
Is a natural person |
Modelo 100 (annual Renta) |
Is a company |
Modelo 200 (annual IS, corporate income tax), Modelo 202 (payments on account) |
Runs an activity under direct estimation |
Modelo 130 (quarterly IRPF) |
Runs an activity under objective estimation (módulos) |
Modelo 131 |
Art. 109 activity-income coverage exception applies |
Removes the Modelo 130 obligation |
Charges VAT under the general regime |
Modelo 303 (quarterly), Modelo 390 (annual) |
Pays employees or professionals with withholding |
Modelo 111 (quarterly), Modelo 190 (annual) |
Pays business-premises rent with withholding |
Modelo 115 (quarterly), Modelo 180 (annual) |
Trades with EU businesses |
Modelo 349 |
Has third-party transactions over the 347 threshold |
Modelo 347 |
Holds foreign assets over the legal threshold |
Modelo 720 |
This is a guide, not the authority. The tool decides applicability from the full profile and the registry rules. To see what applies to your profile, use Choose which modelo to file.
Modify your profile¶
Re-run the wizard over an existing profile to change its facts:
aeat config profile edit my-profileaeat config profile edit my-profileEdit mode walks the same pages with your current answers in place. Change what you need, then confirm the review page. Nothing is written until you confirm: edits stay staged during the walk, and an interrupted edit discards them all. There is no save-and-exit in edit mode. Finish the walk in one sitting. The tool tells you both things at the end of every interactive edit, so an edit never silently half-applies.
Descendientes are not part of profile edit. Manage them with the descendiente command below. The edit summary reminds you of this every time.
For a scripted change, pass --quiet with only the flags you want to change;
every fact you don’t name stays as it was.
Manage your descendants¶
Descendientes drive the mínimo por descendientes in the annual Renta.
Declare them during first-time setup; manage them afterwards with the
descendiente command.
Open the paged descendant editor:
aeat config profile descendienteaeat config profile descendienteThe editor shows your declared descendientes, lets you change any answer, add one, or reduce the count, and commits the complete set when you confirm. Reducing the count removes the descendientes beyond it. The stored set always matches exactly what you confirmed.
Script the same changes with the flag verbs:
aeat --format json config profile descendiente listaeat --format json config profile descendiente list{ "active_profile": "docs-sequence-sandbox", "command": "config.profile.descendiente.list", "notices": [], "result": { "descendientes": [], "profile": "docs-sequence-sandbox", "total": 0 }, "schema_version": "2", "status": "success" }
aeat --format json config profile descendiente add --descendiente \
NACIMIENTO=2018-04-01,DISCAPACIDAD=0,CONVIVENCIA=trueaeat --format json config profile descendiente add --descendiente `
NACIMIENTO=2018-04-01,DISCAPACIDAD=0,CONVIVENCIA=true{ "active_profile": "docs-sequence-sandbox", "command": "config.profile.descendiente.add", "notices": [], "result": { "added": 1, "profile": "docs-sequence-sandbox", "total": 1 }, "schema_version": "2", "status": "success" }
aeat --format json config profile descendiente remove 0aeat --format json config profile descendiente remove 0{ "active_profile": "docs-sequence-sandbox", "command": "config.profile.descendiente.remove", "notices": [], "result": { "profile": "docs-sequence-sandbox", "removed_index": 0, "total": 0 }, "schema_version": "2", "status": "success" }
Confirm the descendiente count returns to zero after the removal.
add takes one --descendiente per child as KEY=VALUE pairs separated by
commas. NACIMIENTO (birth date, AAAA-MM-DD) is required; ADOPCION,
DISCAPACIDAD (0, 33, or 65), CONVIVENCIA, CUSTODIA,
MESES_TRABAJO, GASTOS_GUARDERIA, and NIF are optional. A
descendiente without a tax identifier is fine. Leave NIF out. remove
takes the position from list, counting from 0.
MESES_TRABAJO names which months the mother worked, not how many. Write a
month as two digits, a run as MM-MM, and separate entries with ;. Write
MESES_TRABAJO=05-08 for May to August. Write MESES_TRABAJO=01;03;09-12 for
January, March, and September to December.
Name the months. The guardería increment counts only the months the mother worked and the child attended, so a count cannot say whether the two overlap.
Maintain your profile¶
The following steps edit a fact and back up the profile to a sealed archive:
aeat config profile edit docs-sequence-sandbox --quiet --address-postcode 28013aeat config profile edit docs-sequence-sandbox --quiet --address-postcode 28013Profile docs-sequence-sandbox Status updated Next aeat app modelo work create
aeat --format json config profile archive export docs-sequence-sandbox --output \
docs-sequence-sandbox.cadrumo-bucket.tar.gzaeat --format json config profile archive export docs-sequence-sandbox --output `
docs-sequence-sandbox.cadrumo-bucket.tar.gz{ "active_profile": "docs-sequence-sandbox", "command": "config.profile.archive.export", "notices": [], "result": { "archive_schema_version": 4, "bucket_id": "<bucket-id>", "recovery_enrolled": false, "target": "docs-sequence-sandbox.cadrumo-bucket.tar.gz" }, "schema_version": "2", "status": "success" }
Confirm the profile survives an edit and a sealed archive backup.
What each step does:
Edit re-runs the wizard, or changes only the flags you pass with
--quiet. See Modify your profile. Runshow,status, orvalidateagain after editing.Archive export writes a sealed, encrypted copy of the profile. The target filename must end with
.cadrumo-bucket.tar.gz. The archive is encrypted with the profile passphrase and does not carry the profile label. Restore it withaeat config profile archive import, and read a sealed archive’s header without decrypting it usingaeat config profile archive inspect.
A sealed archive contains taxpayer data, including the tax identifier, activity, and local filing history. Store it as sensitive tax data, and don’t attach it to a support request. See import, export, and evidence.
Choose your service capabilities¶
Each profile carries its own opt-in for three optional services. The setup wizard asks these questions when you create or edit a profile, and you can change them at any time. These steps show the current posture, turn one capability off, then show the posture again:
aeat config profile capabilities viewaeat config profile capabilities viewllm_vision enabled default llm_vision is on by default (no profile opt-in) google_export enabled default google_export is on by default (no profile opt-in) cloud_evidence_upload disabled default cloud_evidence_upload is off by default (no profile opt-in)
aeat config profile capabilities set llm_vision offaeat config profile capabilities set llm_vision offcapability llm_vision state off
aeat --format json config profile capabilities viewaeat --format json config profile capabilities view{ "active_profile": "docs-sequence-sandbox", "command": "config.profile.capabilities.show", "notices": [], "result": { "capabilities": [ { "capability": "llm_vision", "enabled": false, "reason": "profile opted out of llm_vision", "source": "profile" }, { "capability": "google_export", "enabled": true, "reason": "google_export is on by default (no profile opt-in)", "source": "default" }, { "capability": "cloud_evidence_upload", "enabled": false, "reason": "cloud_evidence_upload is off by default (no profile opt-in)", "source": "default" } ], "profile_id": "<profile-id>" }, "schema_version": "2", "status": "success" }
Confirm a capability change updates the active profile.
The three capabilities are:
cloud_evidence_upload- allow sending sensitive evidence to a cloud LLM provider. Off by default. Barred for gestor profiles.llm_vision- read invoices with the on-host vision model. On by default.google_export- export calculations to Google Sheets. On by default.
Turn any capability on or off with aeat config profile capabilities set.
The example turns llm_vision off. Pass cloud_evidence_upload on to enable
cloud upload. Missing package extras produce the exact install command. See
Install Cadrumo for the extras.
Sign out without deleting the profile using aeat config logout after the
login-gated maintenance and capability checks above. Logout closes the active
storage session, discards its in-memory keys, disposes the bucket engines, and
clears the local active-profile pointer:
aeat config logoutaeat config logoutlogged_out_profile docs-sequence-sandbox
aeat --format json config profile statusaeat --format json config profile status{ "active_profile": "docs-sequence-sandbox", "command": "config.profile.status", "error": { "action": { "action": { "action_id": "operator.profile.login", "cli_path": [ "config", "login" ], "target_command_key": "config.login" }, "argument_bindings": [ { "argument_name": "name", "source": "operator_action.verdict_context", "source_evidence_id": null, "source_key": "name", "status": "resolved", "value": "docs-sequence-sandbox" } ], "conditionality": "immediate", "evidence": [ { "condition_id": "profile.session.logged_in", "evidence_id": "profile.session.resume", "provenance": "persisted_state", "values": { "profile_name": "docs-sequence-sandbox", "session_refusal_reason": "absent", "session_resumed": false } } ], "failed_condition_id": "profile.session.logged_in", "missing_argument_names": [], "no_recovery_outcome": null }, "category": "REFUSED", "code": "REFUSED_CLI_BOUNDARY", "context": { "reason": "absent" }, "message": "You are not logged in. Run `aeat config login` to unlock your profile.", "retryable": false, "runbook_id": null, "trace_id": null }, "notices": [], "schema_version": "2", "status": "error" }
Confirm logout closes the active session without deleting the profile.
See what changed¶
Every change to a profile - creation, edits, imports, classifications, calculations, and filings - is recorded as an event in that profile’s append-only history (a log you can read but not alter). Reading history needs an active profile, so switch to it first after logout. The example creates, renames, and edits a profile before filtering its history:
aeat config profile history --helpaeat config profile history --helpUsage: aeat config profile history [OPTIONS] [profile]
Show the append-only event history for one profile
Arguments:
profile Profile name whose event history should be inspected
Options:
--event-type <str> Filter the history to one or more event
types (repeatable)
--since <str> Filter the history to events at or after
this ISO-8601 timestamp (e.g.
2026-04-01T00:00:00+00:00)
--until <str> Filter the history to events at or before
this ISO-8601 timestamp (e.g.
2026-04-30T23:59:59+00:00)
--object-id <str> Filter the history to events targeting a
specific object_id (exact match)
--actor <str> Filter the history to events recorded by a
specific actor (exact match)
--output-language, --language <es|en|ca|hu>
Output language for the response text (es,
en, ca, hu).
--install-completion Install completion for the current shell.
--show-completion Show completion for the current shell, to
copy it or customize the installation.
--help Show this message and exit.
Confirm the profile history records each change and can be filtered.
Repeat --event-type to include several types. An unknown type is refused with
the full accepted list, so an empty value is a quick way to discover the
vocabulary.
A rename appears as two events on purpose: profile.renamed records that the
data changed, and bucket.renamed records that you ran the rename action. One
answers “what changed”, the other “what was done”.
Delete a profile permanently¶
Delete a profile for good only after closing its active session. Cadrumo refuses to delete the active profile, so log out first and then confirm the irreversible deletion of that exact named profile. This terminal example comes after every profile operation in this guide because the deleted profile cannot be used again:
aeat --format json config logoutaeat --format json config logout{ "active_profile": "docs-sequence-sandbox", "command": "config.logout", "notices": [], "result": { "already_logged_out": false, "logged_out_profile": "docs-sequence-sandbox" }, "schema_version": "2", "status": "success" }
aeat --format json config profile delete docs-sequence-sandbox --yesaeat --format json config profile delete docs-sequence-sandbox --yes{ "active_profile": null, "command": "config.profile.delete", "notices": [ { "action": null, "code": "config.profile.delete.deleted", "context": { "profile_id": "<profile-id>" }, "message": "Profile deleted along with its local state.", "severity": "info" } ], "result": { "completed_at": "2026-04-01T09:00:00+00:00", "deleted": true, "display_name": "docs-sequence-sandbox", "earliest_safe_erase_date": null, "fingerprint": { "digest": "<masked>", "file_count": 4, "schema_version": 1, "total_bytes": 1850 }, "profile_id": "<profile-id>", "retained_record_count": 0 }, "schema_version": "2", "status": "success" }
Confirm logout makes the sandbox profile inactive before deleting only that exact profile.
If setup looks wrong¶
If a command reports no active profile, an invalid field value, or that you’re working under the wrong profile, see Diagnose and repair your local setup.
When the troubleshooting steps don’t resolve it, follow Prepare a privacy-safe support request. It names the outputs to include and the personal data to leave out before you take the issue to the project’s issue tracker.