> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hopae.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Return Data Model

> What we return after User Verification

<img src="https://mintcdn.com/hopae-a83466ba/87cF-Rmy7UVipV4A/images/returndata.png?fit=max&auto=format&n=87cF-Rmy7UVipV4A&q=85&s=722def57621b4962e6fb244fc78df804" alt="Return Data" width="2382" height="1648" data-path="images/returndata.png" />

## Overview

* Who is the user? → returned under `user`.
* How was this identity verified? → described by `provenance`.
* Did the user's claimed values match the source? → returned under `match` for match-capable providers.

## Verification models

The top-level `verification_model` field tells you which payload shape to read:

| `verification_model` | When                                                                                                     | Read from                       | `user`                                  |
| -------------------- | -------------------------------------------------------------------------------------------------------- | ------------------------------- | --------------------------------------- |
| `disclosure`         | The provider returned user attributes from an authoritative source. Default for all classic providers.   | `user.*` (PII) and `provenance` | object with PII                         |
| `match`              | The provider compared RP-submitted values against the authoritative source and returned a match outcome. | `match.*` and `provenance`      | verified subset of the submitted fields |

`verification_model` is always present. Verifications created before this field existed default to `"disclosure"`. `provider_id` mirrors the single element in `amr` and is also always present.

For match flows, `user` echoes back the verified subset of the values you submitted — per-field providers: only fields with `matched: true`; aggregate providers: every submitted field when the aggregate outcome is `true`, otherwise empty. A match provider may additionally expose disclosed (IDP-asserted) claims; those appear under `user` only when requested via `requestedAttributes`, and a requested-but-unavailable disclosed claim is listed in `missing_claims`.

For match-capable providers, `matchData` (the values the RP wants verified) must be supplied at session creation. The keys are **OIDC-normalized** names (see [Normalized User Data](/guides/concepts/normalized-user-data)) and appear back in `match.submitted_fields` and as `match.details` keys. See [Create Verification](/api-reference/verifications/create-verification) (`matchData` body field) and [OIDC Authorization](/api-reference/oidc/auth) (`match_request` JWT param).

## What “Provenance” Means

Provenance explains the verification story — who vouched for the identity, how it was presented, and when it happened.

* Presentation
  * Channel: the route and transport (for example, `centralized_idp` over `internet`, `chip_based` via `nfc`, `wallet` over `internet`).
  * Credentials\[]: the documents or assertions that were presented (`type` is the provider identifier, alongside issuer details and raw upstream claims).
  * Evidence (when provided)
    * Evidence is included when the credential provides it; the object relays the upstream `token` payload and a semicolon-delimited `names` list describing the keys. Key names are provider-specific—always read them from `names`. Content is relayed from the credential source.
* Metadata
  * Verification identifiers and timestamps for audit and support (`verification_id`, `verified_at`).

### UserInfo Payload Structure

Here is a conceptual map of the UserInfo payload. This tree view shows how the data is organized, with a brief explanation for each major component. For detailed field specifications, refer to the Schema Tables that follow this section.

```jsonc theme={null}
{
  // --- Identity ---
  "sub": "...",                 // Subject identifier (stable per source identity)
  "provider_id": "smartid",     // Provider that authenticated the subject (mirrors amr[0])
  "amr": ["smartid"],
  "verification_model": "disclosure", // "disclosure" | "match" — always present
  "user": {                     // Personal attributes; for "match", the verified subset of submitted fields
    "name": "...",
    "birthdate": "..."
  },

  // --- Assurance ---
  "acr": "...",
  "hopae_loa": 3,
  "hopae_loa_label": "substantial",
  "missing_claims": ["email", "address"],

  // --- Verification Story ---
  "provenance": {
    "presentation": {
      "channel": { "type": "...", "transport": "..." },
      "credentials": [
        {
          "type": "smartid",
          "issuer": { "id": "...", "authority_name": "...", "is_government": false },
          // `type` matches the providerId you supplied when creating the session; evidence keys vary per provider
          "evidence": {
            "token": {
              "<token_key>": "...",
              "<another_key>": "...",
              "...": "..."
            },
            "names": "<token_key>;<another_key>;..."
          }, // optional, may be absent
          "claims": { ... }
        }
      ]
    },
    "_metadata": { "verification_id": "...", "verified_at": "..." }
  },

  // --- Match (only when verification_model is "match") ---
  "match": {
    "matched": true,                          // aggregate outcome
    "granularity": "per_field",               // "per_field" | "aggregate"
    "submitted_fields": ["name", "birthdate"], // RP-submitted matchData keys (OIDC-normalized)
    "details": {                              // per_field: matched + submitted_value; aggregate: submitted_value only
      "name":      { "matched": true, "submitted_value": "Test User" },
      "birthdate": { "matched": true, "submitted_value": "1990-01-01" }
    }
  }
}
```

### Match payload example

A complete `/userinfo` response from a match-capable provider:

```json theme={null}
{
  "sub": "dZwCCSTLVMlJlXKTgSERCsApC7OUnBKT",
  "amr": ["id-nik-match"],
  "provider_id": "id-nik-match",
  "verification_model": "match",
  "hopae_loa": 1,
  "hopae_loa_label": "none",
  "missing_claims": [],
  "user": {
    "name": "Test User",
    "birthdate": "1990-01-01"
  },
  "provenance": {
    "presentation": {
      "channel": { "type": "centralized_idp", "transport": "internet" },
      "credentials": [
        {
          "type": "id-nik-match",
          "claims": {
            "fullName": true,
            "dateOfBirth": true,
            "nationalIdNo": true
          },
          "issuer": {
            "authority_name": "Directorate General of Population and Civil Registration (Dukcapil)",
            "is_government": true
          },
          "evidence": {
            "token": {
              "integrator_jws": "eyJhbGciOiJSUzI1NiIsInR5cCI6...",
              "token_type": "integrator"
            },
            "names": "integrator_jws;token_type"
          }
        }
      ]
    },
    "_metadata": {
      "verification_id": "f34e2801c3914b3284f2829ea48eeafc",
      "verified_at": "2026-04-26T15:56:11.110Z",
      "status": "completed"
    }
  },
  "match": {
    "matched": true,
    "granularity": "per_field",
    "submitted_fields": ["name", "birthdate"],
    "details": {
      "name":      { "matched": true, "submitted_value": "Test User" },
      "birthdate": { "matched": true, "submitted_value": "1990-01-01" }
    }
  }
}
```

<Note>
  For match providers, `provenance.presentation.credentials[].claims` carries the upstream IDP response verbatim — typically per-field confirmation from the source authority. This is the audit trail for what the source agreed with — it is not a duplicate of `match.details`. Note the intentional naming asymmetry: `matchData`, `match.submitted_fields`, and `match.details` use OIDC-normalized keys (e.g. `name`, `birthdate`), while `provenance` claims keep the upstream IDP's native keys (e.g. `fullName`, `dateOfBirth`) so the audit trail stays aligned with the source.
</Note>

<Note>
  `details` may include keys that are not in `submitted_fields` when the upstream provider emits additional verifier results (e.g., a liveness signal alongside the demographic match outcome).
</Note>

## Related

* [Data Types — User](/guides/data-types/user)
* [Data Types — Provenance](/guides/data-types/provenance)
* [Level Of Assurance (LoA)](/guides/concepts/assurance)
* [OIDC UserInfo](/api-reference/oidc/userinfo)
* [REST UserInfo](/api-reference/verifications/get-verification-userinfo)

## Next Steps

<CardGroup cols={2}>
  <Card title="OIDC Provider" icon="id-card" href="/guides/concepts/oidc-provider">
    How OIDC fits into User Verification
  </Card>

  <Card title="Verification Flow" icon="diagram-project" href="/guides/concepts/verification-flow">
    Understand the end-to-end lifecycle
  </Card>
</CardGroup>
