> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://infonite.dev/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://infonite.dev/_mcp/server.

# Spain Public Administration API

The **Spain Public Administration Flow API** provides a secure, user-consent-driven integration gateway with official Spanish government portals.
It enables businesses to automate user onboarding, risk analysis, background screening, and academic verification by retrieving official, tamper-proof government records in real-time.

***

## Key Use Cases

#### KYC & Onboarding

Verify identity details directly from official population registers to streamline customer registration.

#### Credit Risk & Underwriting

Retrieve Social Security history (*Vida Laboral*) and Tax declarations (*AEAT*) with user consent to feed scoring models.

#### Tenant Screening

Assess rental solvency by verifying real-time employment status and net tax income directly from government registries.

#### Debt & CIRBE Analysis

Verify outstanding bank debts, loan declarations, and credit exposure from the Bank of Spain's risk registry (*CIRBE*).

#### Background Screening

Verify employment history and academic degrees (*MEC*) directly from official sources.

#### Asset & Mobility

Check vehicle specifications, ownership status, and driver points (*DGT*) for fleet or insurance onboarding.

***

## Target Coverage & Entity Types

The Spain Public Administration Flow API currently provides comprehensive real-time data extraction for **Individuals (Personas Físicas)** across population, tax, labor, and educational registers.

**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.

***

## Integration Lifecycle

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

#### Initialize Session

Call [Create Session](api:POST/es-public-administration/v1/manager/init) with your configuration, required features, and an optional encryption `aes_key` to obtain the secure `widget_url`.

#### User Interaction

Redirect your customer to the `widget_url`. The widget dynamically guides them to authorize and complete portal logins (Cl\@ve Móvil — push, SMS or QR — or a direct SMS OTP issued by the authority).

#### Receive Results

* **Asynchronous (Recommended)**: Listen for the webhook event (`es-public-administration:ended`). If an `aes_key` was provided, the payload is delivered fully encrypted directly to your system.
* **Synchronous (Optional Fallback)**: Poll [Get Session State](api:GET/es-public-administration/v1/manager/\{session_id}) and fetch structured data via [Get Session Results](api:GET/es-public-administration/v1/manager/\{session_id}/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 *Vida Laboral* work history certificates, official tax declarations, or *CIRBE* credit risk reports) using [Download Attachments](api:GET/attachments/\{session_id}/\{attachment_id}).

**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](api:DELETE/es-public-administration/v1/manager/\{session_id}/delete) 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](api:GET/es-public-administration/v1/manager/\{session_id}), and inside the `data` of every webhook payload.

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 observed                                                             | Does it mean the session is finished?                                  |
| :---------------------------------------------------------------------------- | :--------------------------------------------------------------------- |
| `is_closed: true`                                                             | **Yes.** This is the signal.                                           |
| The widget closed, or the browser sent its completion message                 | No. The customer is done; the session may not be.                      |
| You received the `es-public-administration:partial` webhook                   | **No.** That event exists precisely to hand you data *before* the end. |
| `status_code` is `WAITING`, cursor is `es-public-administration:connect:wait` | No. A source is still working in the background.                       |
| You received the `es-public-administration:ended` webhook                     | Yes — 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:

```javascript
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.
}
```

***

## 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::`:

```json
{
  "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.

**Interactive Decryption Sandbox**\
To test your encryption/decryption logic in real-time or copy implementation code templates (Node.js, Python, and Java), please check our [Payload Encryption Guide](/payload-encryption).

For detailed parameter schemas, check the interactive explorer panel next to each endpoint in the API Reference.