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

# Create Verification

> Start a new identity verification session against one of your activated connections.

Starts a verification session against a **connection instance**, a connection you activated for your app. Get the id from [Get Connections](/v2/api-reference/verifications/get-connections).

## Headers

<ParamField header="Authorization" type="string" required>
  `Basic <base64(appId:appSecret)>`. See [Authentication](/v2/api-reference/authentication).
</ParamField>

<ParamField header="Content-Type" type="string" required default="application/json">
  Must be `application/json`.
</ParamField>

## Request Body

<ParamField body="connectionId" type="string" default="smart-id">
  The catalog connection id, as listed in the Console and returned by [Get Connections](/v2/api-reference/verifications/get-connections) (for example `smart-id`, `google-wallet-us-mdl`). It resolves to your app's activated instance of that connection. Provide exactly one of `connectionId`, `connectionInstanceId`, or `providerId`.
</ParamField>

<ParamField body="connectionInstanceId" type="string">
  Alternative to `connectionId` or `providerId`: the activated connection instance (`conn_…`) from Get Connections.
</ParamField>

<ParamField body="providerId" type="string">
  Catalog provider id (`provider.id` from Get Connections). Resolves among the workflow's enabled connections. If several match, the request returns `400` and names the candidates. Add `credentialId` or use `connectionId`.
</ParamField>

<ParamField body="credentialId" type="string">
  Catalog credential id (`credential.id` from Get Connections). Only accepted together with `providerId`. The pair identifies one catalog connection. A credential id alone does not identify a provider.
</ParamField>

<ParamField body="workflowId" type="string">
  The workflow that governs this verification: which connections are enabled and which claims are requested. Defaults to the app's default workflow. An unknown id returns `400 VALIDATION_INVALID_PARAMETER`. An app with no workflow returns `409 WORKFLOW_NOT_CONFIGURED`.
</ParamField>

<ParamField body="userInput" type="object">
  Values the connection needs before it can start: a lookup key such as a registration id, or the values to compare for a `match` connection. One flat map. The fields come from the connection's `userInputSchema`. Required fields are validated before the session starts: a missing field or an out-of-range `select` value returns HTTP 400, and a value the connection rejects returns HTTP 422 `VALIDATION_INVALID_USER_DATA`. Keys the schema does not declare are dropped. See [User Input](/v2/api-reference/verifications/user-input).

  ```json theme={null}
  {
    "registrationId": "PNOEE-38001085718"
  }
  ```
</ParamField>

<ParamField body="redirectUri" type="string">
  Where to send the user after a redirect-based flow completes. Required when the session starts a `redirect` flow (otherwise `400 VALIDATION_REDIRECT_URI_REQUIRED`). REST creation does not select a default from the app's OIDC redirect URI allowlist.
</ParamField>

<ParamField body="flowType" type="string">
  Preferred flow when the connection supports more than one: `qr`, `redirect`, `push`, `dc`, or `query`. The response's `flowType` reports the flow that was actually started.
</ParamField>

<Note>
  The claims requested from the provider are decided by the workflow (the common claims of the verification step plus any credential-specific claims for this connection), not by the request body. `requestedClaims`, `requestedLoa`, and `matchData` from v1 are not accepted. Unknown fields are ignored. See [Workflows](/v2/guides/verifications/workflows).
</Note>

### Provider-key example

```json theme={null}
{
  "providerId": "google-wallet",
  "credentialId": "us-mdl"
}
```

The selected connection must still be activated and enabled in the resolved workflow.

## Response

Returns `201 Created`.

<ResponseField name="verificationId" type="string">
  The session id (UUID v7). It is also the `sub` of the userinfo response.
</ResponseField>

<ResponseField name="status" type="string">
  `awaiting_user_action` immediately after creation. Later values: `authenticating`, `completed`, `failed`, `cancelled` (`processing` is reserved and not currently returned). An unfinished verification expires at `expiresAt` and is then deleted. See [Verification Flow](/v2/guides/verifications/verification-flow).

  A `query` connection (lookup eID such as `ng-nin` or `br-cpf`) runs its lookup inside this call, so `status` is already `completed` or `failed`. See [Flow Types](/v2/guides/reference/flow-types).
</ResponseField>

<ResponseField name="flowType" type="string">
  The flow that was started: `qr`, `redirect`, `push`, `dc`, or `query`. See [Flow Types](/v2/guides/reference/flow-types).
</ResponseField>

<ResponseField name="flowDetails" type="object">
  What your UI needs to continue. The keys depend on `flowType`.

  <Expandable title="Properties">
    <ResponseField name="qrData" type="string">
      `qr` flows: the payload to render as a QR code.
    </ResponseField>

    <ResponseField name="linkData" type="string">
      `qr` and `dc` flows: a Hopae-hosted URL that opens the wallet or app on a phone. Safe to open directly on the user's device.
    </ResponseField>

    <ResponseField name="autoStartToken" type="string">
      `qr` flows on some providers: token for same-device app launch.
    </ResponseField>

    <ResponseField name="authorizationUrl" type="string">
      `redirect` flows: the URL to send the user to.
    </ResponseField>

    <ResponseField name="verificationCode" type="string">
      `push` flows: the code the user must confirm in their app. Absent for providers that do not issue one (then `flowDetails` is omitted).
    </ResponseField>

    <ResponseField name="description" type="string">
      `push` flows: instruction to show next to `verificationCode`.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="error" type="object">
  Present only when the session already failed at creation, which happens only on a `query` connection. Same shape as in [Get Verification](/v2/api-reference/verifications/get-verification): `type`, `code` (for example `INVALID_ID_NUMBER`), `message`.
</ResponseField>

<ResponseField name="createdAt" type="string">
  ISO 8601 creation time.
</ResponseField>

<ResponseField name="expiresAt" type="string">
  ISO 8601 expiry, 30 minutes after creation. A verification not finished by then has expired and is deleted: `GET /verifications/{id}` returns `404`. Stop polling at this time and start a new verification. See [Expiry](/v2/guides/verifications/verification-flow#expiry).
</ResponseField>

<ResponseField name="connectionInstanceId" type="string">
  Echo of the connection instance used.
</ResponseField>

<ResponseField name="connectionId" type="string">
  The catalog connection id, for example `google-wallet-us-mdl`.
</ResponseField>

<ResponseField name="credentialId" type="string">
  The credential being verified, for example `us-mdl`.
</ResponseField>

<ResponseField name="providerId" type="string">
  The provider presenting the credential, for example `google-wallet`.
</ResponseField>

<ResponseField name="verificationModel" type="string">
  `disclosure` or `match`. Tells you which userinfo shape to expect.
</ResponseField>

<RequestExample>
  ```bash cURL theme={null}
  curl --request POST \
    --url 'https://api.hopae.com/connect/v2/verifications' \
    --user '{appId}:{appSecret}' \
    --header 'Content-Type: application/json' \
    --data '{
      "connectionId": "smart-id",
      "userInput": { "registrationId": "PNOEE-38001085718" }
    }'
  ```
</RequestExample>

<ResponseExample>
  ```json Push flow 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",
    "polling": { "intervalMs": 2000, "maxDurationMs": 1800000 },
    "connectionInstanceId": "conn_01J8XK2P4M9QR3TV",
    "connectionId": "smart-id",
    "credentialId": "smart-id",
    "providerId": "smart-id",
    "verificationModel": "disclosure"
  }
  ```

  ```json Query flow (completed) 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"
  }
  ```

  ```json Query flow (failed) theme={null}
  {
    "verificationId": "019bc4f6-7d18-7a2e-8c61-5b9f0e3d4c21",
    "status": "failed",
    "flowType": "query",
    "error": {
      "type": "verification_error",
      "code": "INVALID_ID_NUMBER",
      "message": "Invalid or unknown ID number. Please check and try again."
    },
    "createdAt": "2026-09-03T09:25:47.093Z",
    "expiresAt": "2026-09-03T09:55:47.093Z",
    "connectionInstanceId": "conn_01J8XP4T2H7MCV5N",
    "connectionId": "ng-nin",
    "credentialId": "ng-nin",
    "providerId": "ng-nin",
    "verificationModel": "disclosure"
  }
  ```

  ```json Redirect flow 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",
    "polling": { "intervalMs": 2000, "maxDurationMs": 1800000 },
    "connectionInstanceId": "conn_01J8XM0R7C2VHK4Y",
    "connectionId": "mitid",
    "credentialId": "mitid",
    "providerId": "mitid",
    "verificationModel": "disclosure"
  }
  ```

  ```json QR flow theme={null}
  {
    "verificationId": "019bc4f4-5e77-7a9c-b0d1-6c3a2f8e9b44",
    "status": "awaiting_user_action",
    "flowType": "qr",
    "flowDetails": {
      "qrData": "<value to render as a QR code>"
    },
    "createdAt": "2026-09-03T09:12:44.301Z",
    "expiresAt": "2026-09-03T09:42:44.301Z",
    "polling": { "intervalMs": 2000, "maxDurationMs": 1800000 },
    "connectionInstanceId": "conn_01J8XN2C6QF9W1AZ",
    "connectionId": "freja-plus",
    "credentialId": "freja-plus",
    "providerId": "freja",
    "verificationModel": "disclosure"
  }
  ```

  ```json DC flow 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",
    "polling": { "intervalMs": 2000, "maxDurationMs": 1800000 },
    "connectionInstanceId": "conn_01J8XN9W3D6BQZ1F",
    "connectionId": "google-wallet-us-mdl",
    "credentialId": "us-mdl",
    "providerId": "google-wallet",
    "verificationModel": "disclosure"
  }
  ```
</ResponseExample>

## Errors

| HTTP | Code | When |
| :- | :- | :- |
| 400 | `VALIDATION_INVALID_PARAMETER` | Unknown `workflowId`. Missing or multiple start keys. `credentialId` without `providerId`. An ambiguous `providerId`. The connection is not available for this app or not activated for your app. A required `userInput` field is missing or invalid |
| 400 | `VALIDATION_REDIRECT_URI_REQUIRED` | The connection starts a `redirect` flow and the request has no `redirectUri` |
| 403 | `PROVIDER_DISABLED_IN_WORKFLOW` | The connection is activated but not enabled in the resolved workflow |
| 404 | `RESOURCE_NOT_FOUND` | Unknown `connectionId` or provider/credential pair, or a `connectionInstanceId` that does not belong to your app |
| 409 | `WORKFLOW_NOT_CONFIGURED` | The app has no workflow. Create one before starting a verification |
| 422 | `VALIDATION_INVALID_USER_DATA` | A `userInput` value is present but the connection or its provider rejects it |
| 502 | `PROVIDER_INITIALIZATION_FAILED` | The provider refused to start the session. The verification is recorded as `failed` |

See [Error Codes](/v2/api-reference/error-codes) for the envelope.


## OpenAPI

````yaml POST /verifications
openapi: 3.1.0
info:
  title: Hopae Connect Verification API
  version: 2.0.0
servers:
  - url: https://api.hopae.com/connect/v2
    description: Hopae Connect
security:
  - basicAuth: []
tags:
  - name: Verifications
paths:
  /verifications:
    post:
      tags:
        - Verifications
      summary: Create Verification
      operationId: createVerification
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateVerificationRequest'
      responses:
        '201':
          description: Created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VerificationCreated'
        '400':
          description: >-
            `VALIDATION_INVALID_PARAMETER`: invalid selection, input, or unknown
            workflow.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: VALIDATION_INVALID_PARAMETER
                  message: Invalid parameter
                  details: {}
                request_id: req_01J8XQ3V9K2M7N4P
        '403':
          description: >-
            `PROVIDER_DISABLED_IN_WORKFLOW`: the connection is not enabled in
            the workflow.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: PROVIDER_DISABLED_IN_WORKFLOW
                  message: Connection disabled in workflow
                  details: {}
                request_id: req_01J8XQ3V9K2M7N4P
        '404':
          description: '`RESOURCE_NOT_FOUND`: unknown connection or workflow.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: RESOURCE_NOT_FOUND
                  message: Connection not found
                  details: {}
                request_id: req_01J8XQ3V9K2M7N4P
        '409':
          description: '`WORKFLOW_NOT_CONFIGURED`: the app has no workflow.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '502':
          description: '`PROVIDER_INITIALIZATION_FAILED`: the provider refused to start.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: PROVIDER_INITIALIZATION_FAILED
                  message: Provider failed to start
                  details: {}
                request_id: req_01J8XQ3V9K2M7N4P
components:
  schemas:
    CreateVerificationRequest:
      type: object
      properties:
        connectionId:
          type: string
          description: >-
            Catalog connection id from Get Connections. Mutually exclusive with
            connectionInstanceId and providerId.
          example: smart-id
        connectionInstanceId:
          type: string
          description: >-
            Activated instance (`conn_…`). Mutually exclusive with connectionId
            and providerId.
        workflowId:
          type: string
          description: >-
            Workflow to run. Defaults to the app's default workflow. An unknown
            id returns 400. An app with no workflow returns 409
            WORKFLOW_NOT_CONFIGURED.
        userInput:
          type: object
          description: Values the connection needs, per its `userInputSchema`.
          additionalProperties: true
          example:
            registrationId: PNOEE-38001085718
        redirectUri:
          type: string
          description: >-
            Where to send the user after a redirect flow. Supply it explicitly
            when the flow needs a return destination. REST does not default from
            the OIDC allowlist.
        flowType:
          type: string
          description: Preferred flow when the connection supports several.
          enum:
            - qr
            - redirect
            - push
            - dc
            - query
        providerId:
          type: string
          description: >-
            Catalog provider id. Mutually exclusive with connectionId and
            connectionInstanceId. Add credentialId when the provider has
            multiple enabled credentials.
        credentialId:
          type: string
          description: Catalog credential id. Accepted only together with providerId.
      description: >-
        Provide exactly one of connectionId, connectionInstanceId, or
        providerId. credentialId is valid only with providerId.
      oneOf:
        - required:
            - connectionId
          not:
            anyOf:
              - required:
                  - connectionInstanceId
              - required:
                  - providerId
              - required:
                  - credentialId
        - required:
            - connectionInstanceId
          not:
            anyOf:
              - required:
                  - connectionId
              - required:
                  - providerId
              - required:
                  - credentialId
        - required:
            - providerId
          not:
            anyOf:
              - required:
                  - connectionId
              - required:
                  - connectionInstanceId
    VerificationCreated:
      type: object
      properties:
        verificationId:
          type: string
          description: The session id.
        status:
          type: string
          description: '`awaiting_user_action` after creation.'
          enum:
            - awaiting_user_action
            - authenticating
            - processing
            - completed
            - failed
            - expired
            - cancelled
        flowType:
          type: string
          description: The flow that was started.
          enum:
            - qr
            - redirect
            - push
            - dc
            - query
        flowDetails:
          type: object
          description: What your UI needs next. Keys depend on `flowType`.
          properties:
            qrData:
              type: string
              description: '`qr`: payload to render as a QR code.'
            linkData:
              type: string
              description: '`qr`, `dc`: URL that opens the wallet or app on the phone.'
            autoStartToken:
              type: string
              description: '`qr`: token for same-device app launch.'
            authorizationUrl:
              type: string
              description: '`redirect`: URL to send the user to.'
            verificationCode:
              type: string
              description: '`push`: code the user confirms in their app.'
            description:
              type: string
              description: '`push`: instruction to show with the code.'
        error:
          type: object
          description: >-
            Present only when the session already failed at creation (a `query`
            connection): `type`, `code`, `message`.
        createdAt:
          type: string
          description: ISO 8601.
        expiresAt:
          type: string
          description: ISO 8601, 30 minutes after creation.
        connectionInstanceId:
          type: string
          description: The instance used.
        connectionId:
          type: string
          description: Catalog connection id.
        credentialId:
          type: string
          description: The credential.
        providerId:
          type: string
          description: The provider.
        verificationModel:
          type: string
          description: '`disclosure` or `match`.'
          enum:
            - disclosure
            - match
        polling:
          type: object
          description: >-
            Present while the session is not terminal. Wait `intervalMs` between
            polls. It is set per connection, because some providers reject
            faster status reads. `maxDurationMs` is the session window.
          properties:
            intervalMs:
              type: integer
              description: Milliseconds to wait between polls.
            maxDurationMs:
              type: integer
              description: Milliseconds from creation to expiry.
          required:
            - intervalMs
            - maxDurationMs
    Error:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
            message:
              type: string
            details:
              type: object
        request_id:
          type: string
  securitySchemes:
    basicAuth:
      type: http
      scheme: basic
      description: >-
        `Basic base64(appId:appSecret)`. See
        [Authentication](/v2/api-reference/authentication).

````

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