Skip to navigation

Spain Public Administration Flow

Official records as an experience we host — your customer identifies themselves before the Spanish administrations in our widget, wearing your brand

View as Markdown

Spain Public Administration is the flow that reads official records from the Spanish government portals, with your customer’s consent, in a secure experience hosted by INFONITE. Like every flow, it works out of the box: there is nothing to build between the session you open and the records you receive. It enables businesses to automate onboarding, credit and mortgage underwriting, income, asset and debt analysis, and background and driver checks by retrieving official, tamper-proof government records straight from the source.


Use cases

What the administrations hold about a person, and what it is used for. Each one names the sources it reads — every source is a feature you ask for when you create the session, and What you can ask for says which.

Lending and risk

The questions a credit file asks, answered by the administration that holds each answer rather than by documents the applicant brings.

Mortgage underwriting Social Security AEAT CIRBE Cadastre
One session for the whole file: who employs the applicant and what they earn; up to five years of the income the AEAT has on record, payer by payer; every home loan they already hold, with its lender, the date it was signed and their share of it; every debt the Banco de España knows of; and the homes they own, and with whom. Each answer comes from the administration that issued it, with the official documents attached.
Income verification Social Security AEAT
Contribution bases and the income floor computed from them, beside what employers and banks reported to the AEAT year after year — the income an applicant declares, checked against two official sources.
Self-employed income AEAT Social Security
Where there are no pay slips: the income of each economic activity, with its activity code, across up to five fiscal years, and the self-employed contributions paid — a trend, not a single good year.
Debt and credit risk CIRBE AEAT
Every loan, card and guarantee in the CIRBE, and from the tax data, which bank holds each home loan, since when, and how much capital the person paid back each year.
Tenant screening Social Security AEAT CIRBE
Employment, income and debts in one session, before a lease is signed — and whether the income on the application is the income the AEAT knows about.
Guarantors Cadastre CIRBE Social Security
The guarantor opens a session of their own: the properties they hold and their share of each, their debts and their income, read with their consent and not from the applicant’s word.
Insolvency and debt restructuring AEAT CIRBE Cadastre
The complete picture a restructuring or a second-chance proceeding asks for — income, debts and assets — from official sources, in one sitting, instead of a folder of certificates gathered over weeks.

Assets and wealth

What the person owns, as the State records it.

Asset verification Cadastre
Every property the person holds in the Cadastre: where it is, what it is used for, its cadastral value and, when it is shared, every co-owner and their percentage — so the stake you count is the person’s own, not the whole house.
Wealth and investment advice AEAT
The accounts that earned interest, bank by bank, the savings income and the shares and funds sold each year: an investor profile built from what the AEAT recorded, not from a questionnaire.
Pension verification Social Security
The public pensions a person receives — retirement, widowhood, incapacity — straight from the Social Security.

People and hiring

Who the person is, what they studied and where they worked — checked at the source, not on a photocopy.

KYC and onboarding Social Security AEAT
Name, document, addresses and contact details as the administrations hold them, to prefill a registration or check what was typed; and when two administrations describe two different people, the session flags it.
CV verification Education Social Security
Each degree on the CV against the Ministry’s registry, by its official title number, and each job against the work history, employer by employer and with dates: a CV checked line by line.
Regulated professions Education
Healthcare, engineering, teaching, law: the official degree a position legally requires, confirmed before the contract is signed rather than after an inspection.
Employment verification Social Security
Who employs the person today, since when and on what contract, from the official work history.
Education finance and grants Education AEAT
The degree that qualifies an applicant for a master’s loan or a grant, and the household income the grant depends on, in the same session.

Mobility

The person behind the wheel and the vehicles in their name, from the DGT.

Professional drivers DGT
For ride-hailing, delivery, trucking and bus companies: every licence category the driver holds, when it was issued and when it expires, and the points balance — before the first shift, and again before each renewal.
Motor insurance DGT
Years of driving, the points history and the vehicles registered to the person, with their inspection and insurance status: a premium priced on the official record.
Vehicle-backed lending DGT
The vehicles registered to the person, their administrative situation and an official report on whether they carry incidents, before one is taken as collateral.

Combine them freely: the session reads every source you name, and what each one costs your customer is one identification per administration.


Target Coverage & Entity Types

The flow currently reads the records of Individuals (Personas Físicas) from the Social Security (work history, contribution bases, public pensions), the Banco de España (the CIRBE credit registry), the DGT (driving licence and vehicles), the Agencia Tributaria (yearly fiscal data and income-tax returns) and, through the Carpeta Ciudadana, the Cadastre (properties) and the Ministry’s registries of official degrees.

Corporate Coverage (Personas Jurídicas) — Coming Soon 🚀
We are actively developing extensions to support corporate and legal entities. Upcoming capabilities will include:

  • Corporate Fiscal Data: Retrieve AEAT filings and tax declarations for businesses.
  • Commercial Registry Extracts: Automated retrieval of official company records (Registro Mercantil).
  • Corporate Representative Verification: Automated verification of legal powers of attorney.

What you can ask for

Each source is a feature, and a session reads the ones your backend names in settings.executions_features when it creates it — one source, several, or all of them:

SourceFeature codeWhat comes back
Social Security — work history (Vida Laboral), contribution bases, income floorlabor_checkLabor Check
Social Security — public pensionspublic_pensionsPublic Pensions
Banco de España — credit registry (CIRBE)credit_registry_dataCredit Registry
DGT — driving licence, vehiclesdriver_data, vehicles_dataDriver, Vehicles
Agencia Tributaria (AEAT) — yearly tax situationyearly_individual_taxTaxes
Carpeta Ciudadana — academic degreesacademic_dataAcademic Records
Carpeta Ciudadana — real estateproperties_dataProperties
The person’s identity, as the administration holds itcustomer_information_readCustomer Profile

["credit_registry_data"] reads the CIRBE report alone; ["labor_check", "credit_registry_data"] reads both.

yearly_individual_tax reads the last three closed fiscal years unless you ask for more: up to five, with {"code": "yearly_individual_tax", "configurations": {"last_n_years": 5}}. Taxes has the details.

The Agencia Tributaria and the Carpeta Ciudadana are administrations of their own: asking for one of their features adds one more Cl@ve identification for the person, after the Social Security’s. Ask for what you will use. Which administrations a session may ask your customer to sign in to, and in which order, is yours to decide: Choosing the administrations.

What your customer needs

Every source is read in your customer’s name, on the administration’s own site, through Cl@ve, the Spanish government’s sign-in:

  • To be registered in Cl@ve. The Cl@ve app is not needed: by default the code arrives by SMS, to the phone registered in Cl@ve. The push option uses the app when the person has it.
  • Their identity document: a DNI with its validity date (the issue date for a permanent DNI), or an NIE with its support number.

Without Cl@ve, the Social Security can still be read. labor_check and public_pensions accept a sign-in with the document, the date of birth and the mobile registered with the Social Security, by SMS code. The CIRBE report, the DGT, the Agencia Tributaria and the Carpeta Ciudadana need Cl@ve.


Integration Lifecycle

Integrating the interactive flow and retrieving verified records involves four straightforward steps:

1

Initialize Session

Call Create Session with your configuration, the required features, and an optional encryption aes_key (what it protects) to obtain the secure widget_url.

2

User Interaction

Redirect your customer to the widget_url. The widget guides them through consent and the sign-in — see what your customer needs.

3

Receive Results

The two ways the platform offers, and note that neither of them is the redirect in the step above — that one moves a browser, not data.

  • Asynchronous (Recommended): Listen for the webhook event (es-public-administration:ended), a call from our servers to yours. If an aes_key was provided, the payload is delivered fully encrypted directly to your system.
  • Synchronous (Optional Fallback): Poll Get Session State and fetch structured data via Get Session Results once status transitions to COMPLETED.

Official Support Documents
In addition to structured JSON data, the results include secure download IDs. You can retrieve the official, tamper-proof PDFs (such as the Vida Laboral work history report, the contribution bases report, or the CIRBE credit risk report) using Download Attachments.

When a source answers late
Not every administration answers in real time — the CIRBE credit risk report from the Banco de España is the usual case. Rather than hold your customer in front of a spinner, the widget lets them go and the session keeps working in the background.

Subscribe to es-public-administration:partial to receive everything gathered up to that moment, in the same schema as the final results, so you can move early. That payload is partial: the sources that had not answered yet are absent from it. The session stays open, and es-public-administration:ended still fires afterwards with the complete, final data — that is the one that closes the verification.

4

Cleanup Session (Optional)

Manually purge the session and its results using Delete Session immediately after processing to maintain strict data minimization. If omitted, session data and decrypted results are automatically deleted after a security retention timeout.


Knowing when a session is finished

A session is finished when is_closed is true. Nothing else means finished.

is_closed is the single authoritative signal, and it is delivered everywhere you look: in the session state from Get Session State, and at the top of the partial and ended webhooks — false and true —, with an aes_key or without one.

While is_closed is false, the results are partial: records may still change, be corrected, or appear for the first time as the pending sources answer.

Every other signal you may be tempted to use is ambiguous, because the widget is not the session. The customer can be long gone while a source — typically the CIRBE report from the Banco de España — is still being produced.

What you observedDoes it mean the session is finished?
is_closed: trueYes. This is the signal.
The widget closed, or the browser sent its completion messageNo. The customer is done; the session may not be.
You received the es-public-administration:partial webhookNo. That event exists precisely to hand you data before the end.
status_code is WAITING, cursor is es-public-administration:connect:waitNo. A source is still working in the background.
You received the es-public-administration:ended webhookYes — and its payload carries is_closed: true.

One check, wherever you are. Whether you are handling a webhook or polling the session, branch on the same field:

if (results.is_closed) {
// Final. Safe to score, decide, archive, and delete the session.
} else {
// Partial. Use it to move early, but do not close the case on it.
}

How a session ends

Once is_closed is true, status_code says who ended the session:

status_codeWho ended itWhen
COMPLETED—At least one administration was connected and nothing was left to offer, whatever else failed or was abandoned on the way. Also when you cancel a session that had already retrieved something.
CUSTOMER_CANCELLEDYour customerThey left the experience — the es-public-administration:ended event says why, in user_feedback. Or they abandoned a connection, and the session ended without connecting any administration.
SYSTEM_CANCELLEDThe platformNo administration could be connected and your customer abandoned none: their sign-ins failed until no administration was left to offer — wrong credentials, most of the time, a Cl@ve registration that does not allow it, an administration not available. Or the session reached its limit of connection attempts.
CLIENT_CANCELLEDYouYou cancelled the session before anything was retrieved.
TIMED_OUT—The session reached its time limit before your customer finished.
FAILEDThe platformSomething went wrong on our side.

Abandoning a connection is not leaving the session. While a sign-in or a reading is in progress, your customer can abandon that one connection from the widget, and the session goes on:

  • Before signing in, the same administration is offered again, for them to start over. An abandon is not a failed sign-in: it never closes an administration, and it never makes the session report clave_access_unavailable.
  • After signing in, what that administration had already returned is kept, and the session moves on to the next administration in your allowed_sources that can still add something.

When the session ends without connecting any administration, messages carries the flag no_source_connected, whichever of the two cancellations it was.


What the session tells you, beside the data

The results carry a messages list next to the records: situations the session detected while it ran. Most sessions detect none and the list is empty.

A message is not a log line. A situation is reported once, however many times it occurred, so messages is a set of facts about the verification rather than a trace of it — and message_id is the stable name of the situation, which is what you automate on. The wording of message is for a person and may be rewritten; the id is the contract.

TypeWhat it is
flagSomething about the person or the data that deserves a decision on your side. Route these.
warningThe session did its job, and something about how it did it is worth knowing.
errorSomething did not go as intended. retrieved_features already says what came back; an error adds the reason.
infoA note for whoever reads the session. Nothing to act on.

A flag never means something failed on our side. warning and error describe how the reading went; a flag describes what the reading found — a signal a clean, successful verification would not normally carry.

Treat flags as an input to the rules that already decide when a case needs a human. A verification can be technically perfect and still be worth a second look.

location points at the part of the results the message is about, as a loc list — the same shape as the loc of a validation error: ["data", "customer", "profile"], with strings for fields and integers for array positions. An empty list means the message is about the session as a whole. That is why it is a list: a results document contains arrays, and a dotted path cannot address a position without guessing whether 0 is a key or an index.

An example: identities that do not agree

A session can connect more than one administration, and the customer profile is then built by merging what each one returned. If two sources describe different people, the session raises a crossed_identity flag at ["data", "customer", "profile"]: the merged profile keeps the first source’s identity, and the flag is what tells you the merge was not unanimous.

On this flow that flag is a guarantee rather than an expectation. The person authenticates against every administration with the same identity document, fixed when the session is created, so nobody can present one identity to one source and a different one to the next.

It is worth describing anyway, because it is the clearest shape of what a flag is for: a signal that the data is internally inconsistent in a way no single source could report. Experiences where the customer chooses their own credential per source have no such guarantee, and this is the field where that would reach you.

Cl@ve: why an administration could not be connected

Most administrations are reached through Cl@ve, the Spanish State’s identification system, and what the person’s Cl@ve allows decides which of them can be connected. When it gets in the way, the session says so with an info message — the same id however many administrations met it:

message_idWhat happenedWhat the session did
clave_not_registeredThe person is not registered in Cl@ve.No administration that identifies through Cl@ve is offered again. The Seguridad Social, when allowed, is still reached through its SMS access.
clave_level_insufficientThe person has Cl@ve, but registered below the level an administration requires. At ["data", "credit", "registry"] when it is the Banco de España’s level for the CIRBE report, which is then absent; for the whole session otherwise, naming the sources it stopped.That administration is not tried again in the session: the level does not change by trying. The others go on as usual.
clave_access_unavailableSigning in with Cl@ve failed repeatedly, or the access was blocked.The session moves on without that access. It may work again later, in a new session.

None of them means something failed on our side, and none of them is a flag: they explain why a feature you asked for may be missing from retrieved_features.

Every type, every field and what to do with each one is in Get Session Results, and the same list travels in the end and partial webhooks.


Sandbox and production

settings.sandbox is required on every session. true runs against the sandbox — engines that answer with realistic, fabricated records, with no real administration behind them — and any application may open one. false is production: the real administrations, and a real person behind every identification.

Before production

Spain Public Administration in production needs its capability

Sandbox sessions work from the first minute, for every application. A production session needs the application in production and holding the Spain Public Administration capability. Without it, Create Session answers 403 with insufficient_capabilities@product:es_public_administration.


Payload Decryption (AES-256-GCM)

When an aes_key is provided at session creation, webhook payloads are encrypted for security. The data field contains a string prefixed with aes:::

{
"data": "aes::U2FsdGVkX19..."
}

Follow these steps to decrypt the payload on your server:

  1. Remove Prefix: Strip the aes:: prefix from the string.
  2. Decode Base64: Decode the remaining string to retrieve the raw bytes.
  3. Extract Parts:
    • IV (Initialization Vector): First 12 bytes.
    • Tag (Authentication Tag): Last 16 bytes.
    • Ciphertext: All middle bytes.
  4. Decrypt: Decrypt using AES-256-GCM with your session key (aes_key), the extracted IV, and the Tag.