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
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.
Assets and wealth
What the person owns, as the State records it.
People and hiring
Who the person is, what they studied and where they worked — checked at the source, not on a photocopy.
Mobility
The person behind the wheel and the vehicles in their name, from the DGT.
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:
["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:
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.
User Interaction
Redirect your customer to the widget_url. The widget guides them through consent and the sign-in — see what your customer needs.
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 anaes_keywas 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.
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.
One check, wherever you are. Whether you are handling a webhook or polling the session, branch on the same field:
How a session ends
Once is_closed is true, status_code says who ended the session:
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_sourcesthat 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.
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:
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.
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:::
Follow these steps to decrypt the payload on your server:
- Remove Prefix: Strip the
aes::prefix from the string. - Decode Base64: Decode the remaining string to retrieve the raw bytes.
- Extract Parts:
- IV (Initialization Vector): First 12 bytes.
- Tag (Authentication Tag): Last 16 bytes.
- Ciphertext: All middle bytes.
- Decrypt: Decrypt using AES-256-GCM with your session key (
aes_key), the extracted IV, and the Tag.