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

# Flow Types

> How each flow type runs over the REST API: the sequence, the create response, and what your app does.

The `flowType` in the [Create Verification](/v2/api-reference/verifications/create-verification) response tells you what happens between create and userinfo. Every create response also carries `connectionInstanceId`, `connectionId`, `credentialId`, `providerId`, `verificationModel`, and `expiresAt` (30 minutes after creation).

For the status list, see [Verification Flow](/v2/guides/verifications/verification-flow#lifecycle). For polling, see [REST API Integration](/v2/guides/api-integration#4-poll-until-finished).

<Tabs>
  <Tab title="Redirect">
    The user signs in on the provider's page and returns to your `redirectUri`. Examples: `mitid`, `id-austria`, `cz-bankid-identify`.

    ```mermaid theme={null}
    sequenceDiagram
        participant U as User (browser)
        participant C as Your server
        participant H as Hopae
        participant P as Provider
        C->>H: POST /verifications
        H-->>C: awaiting_user_action (authorizationUrl)
        C->>U: Send the user to authorizationUrl
        U->>P: Sign in
        P-->>H: Result
        H-->>U: Back to your redirectUri
        C->>H: GET /verifications/{id}
        H-->>C: completed
        C->>H: GET /verifications/{id}/userinfo
    ```

    ```json Create response theme={null}
    {
      "verificationId": "019bc4f3-1c02-7d4a-8b7e-2e0f9c5a7d11",
      "status": "awaiting_user_action",
      "flowType": "redirect",
      "flowDetails": {
        "authorizationUrl": "https://connect.hopae.com/v/019bc4f3-1c02-7d4a-8b7e-2e0f9c5a7d11"
      },
      "createdAt": "2026-09-03T09:15:02.118Z",
      "expiresAt": "2026-09-03T09:45:02.118Z",
      "connectionInstanceId": "conn_01J8XM0R7C2VHK4Y",
      "connectionId": "mitid",
      "credentialId": "mitid",
      "providerId": "mitid",
      "verificationModel": "disclosure"
    }
    ```

    **Your app:** send the user to `flowDetails.authorizationUrl`. When the user is back on your `redirectUri`, check the status.
  </Tab>

  <Tab title="QR">
    The user scans a QR code with the eID app and approves there. Examples: `freja-plus`, `diia`.

    ```mermaid theme={null}
    sequenceDiagram
        participant U as User (phone app)
        participant C as Your server
        participant H as Hopae
        participant P as Provider
        C->>H: POST /verifications
        H-->>C: awaiting_user_action (qrData)
        C->>U: Show qrData as a QR code
        U->>P: Scan and approve
        loop Until terminal
            C->>H: GET /verifications/{id}
            H->>P: Check status
            H-->>C: awaiting_user_action, then completed
        end
        C->>H: GET /verifications/{id}/userinfo
    ```

    ```json Create response (abridged) theme={null}
    {
      "verificationId": "019bc4f4-5e77-7a9c-b0d1-6c3a2f8e9b44",
      "status": "awaiting_user_action",
      "flowType": "qr",
      "flowDetails": {
        "qrData": "<value to render as a QR code>",
        "linkData": "<link that opens the eID app on the same phone, when available>"
      },
      "expiresAt": "2026-09-03T09:42:44.301Z",
      "connectionId": "freja-plus"
    }
    ```

    **Your app:** on a desktop, render `flowDetails.qrData` as a QR code. On a phone, open `flowDetails.linkData` instead, when present. Some QR connections have none. Then poll.
  </Tab>

  <Tab title="Push">
    Hopae sends the request to the eID app on the user's registered phone. Examples: `smart-id`, `sk-mobile-id`, `evrotrust-identity-attestation`.

    ```mermaid theme={null}
    sequenceDiagram
        participant U as User (phone app)
        participant C as Your server
        participant H as Hopae
        participant P as Provider
        C->>H: POST /verifications (userInput)
        H->>P: Send request to the user's device
        H-->>C: awaiting_user_action (verificationCode)
        P->>U: Notification
        U->>P: Confirm
        loop Until terminal
            C->>H: GET /verifications/{id}
            H->>P: Check status
            H-->>C: awaiting_user_action, then completed
        end
        C->>H: GET /verifications/{id}/userinfo
    ```

    ```json Create response theme={null}
    {
      "verificationId": "019bc4f2-8a31-7c5e-9d02-4f7a1b3e60d8",
      "status": "awaiting_user_action",
      "flowType": "push",
      "flowDetails": {
        "verificationCode": "4823",
        "description": "Confirm this code matches the one shown in your Smart-ID app"
      },
      "createdAt": "2026-09-03T09:18:31.774Z",
      "expiresAt": "2026-09-03T09:48:31.774Z",
      "connectionInstanceId": "conn_01J8XK2P4M9QR3TV",
      "connectionId": "smart-id",
      "credentialId": "smart-id",
      "providerId": "smart-id",
      "verificationModel": "disclosure"
    }
    ```

    **Your app:** show a waiting screen with `flowDetails.verificationCode` and `description` so the user can match the code, then poll. If the provider issues no code, `flowDetails` is absent.
  </Tab>

  <Tab title="DC">
    The user shares a credential from a phone wallet through the Digital Credentials API. Example: `google-wallet-us-mdl`.

    ```mermaid theme={null}
    sequenceDiagram
        participant U as User (phone wallet)
        participant C as Your server
        participant H as Hopae
        C->>H: POST /verifications
        H-->>C: awaiting_user_action (linkData)
        C->>U: Open linkData on the phone
        U->>H: Hosted page asks the wallet, user shares
        C->>H: GET /verifications/{id}
        H-->>C: completed
        C->>H: GET /verifications/{id}/userinfo
    ```

    ```json Create response theme={null}
    {
      "verificationId": "019bc4f5-9a10-7e3b-8f42-7d1c0b9a3e55",
      "status": "awaiting_user_action",
      "flowType": "dc",
      "flowDetails": {
        "linkData": "https://connect.hopae.com/dc/us-mdl?verification_id=019bc4f5-9a10-7e3b-8f42-7d1c0b9a3e55"
      },
      "createdAt": "2026-09-03T09:21:09.442Z",
      "expiresAt": "2026-09-03T09:51:09.442Z",
      "connectionInstanceId": "conn_01J8XN9W3D6BQZ1F",
      "connectionId": "google-wallet-us-mdl",
      "credentialId": "us-mdl",
      "providerId": "google-wallet",
      "verificationModel": "disclosure"
    }
    ```

    **Your app:**

    * **Same device (phone):** open `flowDetails.linkData` in the system browser. Append `&return_url=<your https URL>` to bring the user back.
    * **Cross-device (desktop):** render `flowDetails.linkData` as a QR code for the phone to scan.
    * Then poll.

    The hosted page needs a browser with the Digital Credentials API, such as Chrome 141+ on Android or Safari 26+ on iOS.

    To run the wallet request on your own page instead, call `POST /verifications/{id}/dc-request`, pass its result to `navigator.credentials.get`, and send the wallet's answer to `POST /verifications/{id}/dc-response`. That call returns the finished verification.

    <Warning>
      In Sandbox, issuer trust-chain checks are not enabled for the DC flow. A sandbox `completed` is not a fraud signal.
    </Warning>
  </Tab>

  <Tab title="Query">
    Hopae checks the data you sent (an ID number, sometimes a photo) with the source registry inside the create call. Nothing is sent to the user. Examples: `ng-nin`, `za-nid`, `br-cpf`.

    ```mermaid theme={null}
    sequenceDiagram
        participant C as Your server
        participant H as Hopae
        participant S as Source registry
        C->>H: POST /verifications (userInput)
        H->>S: Look up the record
        S-->>H: Record, or no match
        H-->>C: completed (or failed + error)
        C->>H: GET /verifications/{id}/userinfo
    ```

    ```json Create response theme={null}
    {
      "verificationId": "019bc4f6-2b41-7f0c-9a55-3e8d1c7b2a90",
      "status": "completed",
      "flowType": "query",
      "createdAt": "2026-09-03T09:24:10.512Z",
      "expiresAt": "2026-09-03T09:54:10.512Z",
      "connectionInstanceId": "conn_01J8XP4T2H7MCV5N",
      "connectionId": "ng-nin",
      "credentialId": "ng-nin",
      "providerId": "ng-nin",
      "verificationModel": "disclosure"
    }
    ```

    **Your app:** no screen and no polling. On `completed`, read userinfo. On `failed`, read `error` in the create response: `error.code` is a general code such as `provider_error`, and the source's own reason (for example `INVALID_ID_NUMBER`) is in `error.details.provider_code`.

    * Create answers `201` either way. A failed lookup is a result, not a request error.
    * The call waits for the source, usually a few seconds. Set your HTTP timeout to at least 30 seconds.
    * A later `GET /verifications/{id}` returns the stored result without asking the source again.

    <Accordion title="Connections with the query flow">
      | Connection | Credential |
      | :- | :- |
      | `ng-nin` | Nigeria NIN |
      | `ng-bvn` | Nigeria BVN |
      | `ng-vid` | Nigeria Voter ID |
      | `za-nid` | South Africa National ID |
      | `ug-nin` | Uganda National ID |
      | `ke-nid` | Kenya National ID |
      | `ke-passport` | Kenya Passport |
      | `ke-alien-card` | Kenya Alien Card |
      | `ao-nin` | Angola National ID |
      | `gh-card` | Ghana Card |
      | `ci-nid` | Côte d'Ivoire National ID |
      | `br-cpf` | Brazil CPF |
      | `br-cpf-cnh-match` | Brazil CNH + biometrics |
      | `mx-curp` | Mexico CURP |
      | `mx-ine-qr` | Mexico INE QR Code |
      | `cl-run` | Chile RUN |
      | `pe-dni` | Peru DNI |
      | `in-pan-match` | India PAN |
      | `id-nik-match` | Indonesia NIK |
      | `id-nik-bio-match` | Indonesia NIK + biometrics |
      | `ph-nid` | Philippine National ID |
      | `co-runt-bio-match` | Colombia RUNT + biometrics |
    </Accordion>

    <Note>
      The v1 API reports these connections as `flowType: push`. They behave the same way: the create response is already final.
    </Note>
  </Tab>
</Tabs>

## Same-device journeys

A phone cannot scan a QR code it is showing. When the verification starts on a phone, use `linkData` (QR and DC) or `authorizationUrl` (redirect) instead of a QR code, keep the `verificationId` before leaving your app, and resume through an allowlisted callback. See [Mobile App Integration](/v2/guides/mobile-app-integration#same-device-journeys).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.