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

# Poll verification session status

> Returns the current state of a verification session. **`verificationSession` must be the `verification_id` (UUID) from `POST /users/{id}/verification/flows`.

Poll while the user is in the Veriff/BankID flow until `status` is terminal: `approved`, `declined`, `cancelled`, `expired`, or `error`.
**`next_action`** is always set — e.g. `continue_verification` while the session is non-terminal; when terminal, values such as `redirect_to_partner`, `retry`, or `show_error` indicate suggested client behaviour.
**`onboarding`** matches the **v2** object returned on `GET /users/{id}`: `steps`, `missing_steps`, `is_onboarded`, `status_version`, `evaluated_at`. The ID step is **`steps.id_verification`** (not `entity_verification`): it is true when entity verification is approved **and** identity from Veriff/BankID is complete.

**403** if the session belongs to another partner — body typically `{ "error": "<message>" }`.
**404** if the session id does not exist — same error shape.




## OpenAPI

````yaml /easyfreelance-partner-api-merged.yaml get /verification/status/{verificationSession}
openapi: 3.0.3
info:
  title: EasyFreelance Partner API
  version: 1.0.0
  description: >
    REST API for partners under `/api/v1`.


    **Authentication:** Every request requires:

    - `Authorization: Bearer <token>` — Sanctum personal access token (created
    in partner **API settings**).

    - `API-key: <uuid>` — Partner API key (same settings).


    **Idempotency (optional):** Header `Idempotency-key` may be sent on partner
    requests.

    - If you omit it, the request behaves normally.

    - If you send it, the value must be a **valid UUID**; otherwise the API
    returns **400**.

    - If the same key has **already been stored** for this partner, the API
    returns **400** (key already used). That check runs for any route once the
    key exists in the idempotency store.

    - **Recommended especially for `POST /payouts`** (create payouts), so safe
    retries do not create duplicate payout side effects. You typically do not
    need this header on read-only calls.


    **Error responses:** Partner endpoints often return JSON with an **`error`**
    key (string or structured validation payload). Some operations documented
    here reference Laravel-style responses with a **`message`** field (e.g.
    unauthenticated). Use HTTP status codes as the primary contract; exact
    wording of messages may change with locale or small API updates.


    **Rate limiting:** Authenticated partner traffic shares **one rolling limit
    per API identity** (Sanctum token / partner user): **500 requests per
    minute** across all `/api/v1/...` routes. When exceeded, the API returns
    **429 Too Many Requests**; responses may include a **`Retry-After`** header
    (seconds). There are no separate per-route partner limits — polling, login
    links, terms updates, and everything else draw from the same budget.


    **Entity verification (Veriff / BankID)** — high-level partner flow:

    1. Register and get approval for a return URL: `POST
    /verification-return-urls` (admin approval). The response includes
    **`requested_url`** (the registered base URL string), **`status`**, and
    auxiliary fields **`normalized_host`**, **`normalized_scheme`**, and
    **`normalized_path_prefix`**. Those `normalized_*` values support display,
    allowlisting, and database uniqueness; **matching** when starting a flow is
    driven by the stored **`requested_url`** (exactly, or as an approved base
    plus allowed dynamic path segments per server rules) — not by treating
    `normalized_path_prefix` as a separate “path template”.

    2. Start a session: `POST /users/{id}/verification/flows` with `provider`
    and `partner_return_url`. The return URL must be **allowed** for your
    partner against an **approved** `requested_url` as above.

    3. Response includes `verification_id` (correlate this ID when **polling**
    `GET /verification/status/{verificationSession}`) and `verification_url` —
    open this URL in the end user’s browser.

    4. The user completes the flow on EasyFreelance-hosted pages, is redirected
    to Veriff or BankID, then returns to EasyFreelance; when finished,
    EasyFreelance redirects the user to `partner_return_url`.

    5. The partner backend should poll using `verification_id` until `status` is
    terminal, and/or consume out-of-band notifications if your deployment offers
    webhooks (not described in this OpenAPI file).


    Details and field semantics for verification are documented under the
    **VerificationFlow** and **VerificationReturnUrlRequest** tags and in the
    operation descriptions below.
servers:
  - url: https://app.easyfreelance.no/api/v1
    description: Production
  - url: https://test.easyfreelance.no/api/v1
    description: Test environment
security:
  - bearer: []
    ApiKeyAuth: []
tags:
  - name: PartnerTerms
    description: Terms metadata and per-user approval
  - name: User
    description: Employees linked to the partner
  - name: Payout
    description: Create and list payouts
  - name: VerificationFlow
    description: >
      **Veriff / BankID** verification for employees: register an allowed
      partner return URL, start a session per user, send the user to
      `verification_url`, poll with `verification_id`, and finally the user is
      redirected to your `partner_return_url`.


      End-to-end: partner return URL approval → `POST …/verification/flows` →
      browser opens **`verification_url`** (verification bouncer on
      EasyFreelance) → user is sent to Veriff or BankID → user returns to
      EasyFreelance → redirect to partner. **`verification_url`** is the same
      style of bouncer URL for both providers (Veriff then redirects out to the
      hosted flow; BankID continues in-app). Use `verification_id` as the
      correlation ID for polling `GET
      /verification/status/{verificationSession}`.
  - name: VerificationReturnUrlRequest
    description: >-
      Register and track approval of partner return URLs used after
      verification.
paths:
  /verification/status/{verificationSession}:
    get:
      tags:
        - VerificationFlow
      summary: Poll verification session status
      description: >
        Returns the current state of a verification session.
        **`verificationSession` must be the `verification_id` (UUID) from `POST
        /users/{id}/verification/flows`.


        Poll while the user is in the Veriff/BankID flow until `status` is
        terminal: `approved`, `declined`, `cancelled`, `expired`, or `error`.

        **`next_action`** is always set — e.g. `continue_verification` while the
        session is non-terminal; when terminal, values such as
        `redirect_to_partner`, `retry`, or `show_error` indicate suggested
        client behaviour.

        **`onboarding`** matches the **v2** object returned on `GET
        /users/{id}`: `steps`, `missing_steps`, `is_onboarded`,
        `status_version`, `evaluated_at`. The ID step is
        **`steps.id_verification`** (not `entity_verification`): it is true when
        entity verification is approved **and** identity from Veriff/BankID is
        complete.


        **403** if the session belongs to another partner — body typically `{
        "error": "<message>" }`.

        **404** if the session id does not exist — same error shape.
      operationId: verification.status.show
      parameters:
        - name: verificationSession
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Current session state
          content:
            application/json:
              schema:
                type: object
                description: >-
                  Current verification session state. Poll until `status` is
                  terminal (`approved`, `declined`, `cancelled`, `expired`,
                  `error`).
                properties:
                  verification_id:
                    type: string
                    description: Same ID as returned from `POST …/verification/flows`.
                  user_id:
                    type: integer
                    description: Employee user id this session belongs to.
                  provider:
                    type: string
                    enum:
                      - veriff
                      - bankid
                  id_type:
                    type: string
                    nullable: true
                    description: '`local` or `international` for Veriff; `null` for BankID.'
                  status:
                    type: string
                    description: >
                      `pending` until terminal; then `approved`, `declined`,
                      `cancelled`, `expired`, or `error`. After `approved`,
                      check `onboarding` for remaining employee steps.
                  verified_at:
                    type: string
                    nullable: true
                    format: date-time
                    description: >-
                      ISO-8601 completion time when terminal; `null` while
                      `pending`.
                  expires_at:
                    type: string
                    format: date-time
                  next_action:
                    type: string
                    enum:
                      - continue_verification
                      - redirect_to_partner
                      - retry
                      - show_error
                    description: Suggested client behaviour from session state.
                  last_polled_at:
                    type: string
                    format: date-time
                  onboarding:
                    type: object
                    nullable: true
                    description: >-
                      Same v2 onboarding payload as GET `/users/{id}`; `null` if
                      the employee user record is missing.
                    properties:
                      is_onboarded:
                        type: boolean
                      missing_steps:
                        type: array
                        items:
                          type: string
                      steps:
                        type: object
                        properties:
                          email_verified:
                            type: boolean
                          terms_approved:
                            type: boolean
                          profile:
                            type: boolean
                          id_verification:
                            type: boolean
                          bank_account:
                            type: boolean
                      status_version:
                        type: string
                      evaluated_at:
                        type: string
                        format: date-time
                required:
                  - verification_id
                  - user_id
                  - provider
                  - id_type
                  - status
                  - verified_at
                  - expires_at
                  - next_action
                  - last_polled_at
                  - onboarding
        '401':
          $ref: '#/components/responses/AuthenticationException'
        '403':
          description: >
            Forbidden — verification session exists but belongs to another
            partner. Body typically `{ "error": "<message>" }` (wording may
            vary).
          content:
            application/json:
              schema:
                type: object
                description: >-
                  Partner-style error envelope; prefer the `error` property for
                  handling.
                properties:
                  error:
                    anyOf:
                      - type: string
                      - type: array
                        items:
                          type: object
                          additionalProperties: true
                      - nullable: true
                required:
                  - error
        '404':
          description: >
            Verification session not found. Body typically `{ "error":
            "<message>" }`.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    anyOf:
                      - type: string
                      - type: array
                        items:
                          type: object
                          additionalProperties: true
                      - nullable: true
                required:
                  - error
components:
  responses:
    AuthenticationException:
      description: Unauthenticated
      content:
        application/json:
          schema:
            type: object
            properties:
              message:
                type: string
                description: Error overview.
            required:
              - message
  securitySchemes:
    bearer:
      type: http
      scheme: bearer
      description: Sanctum personal access token (`access_tokens` / partner API settings).
    ApiKeyAuth:
      type: apiKey
      in: header
      name: API-key
      description: UUID API key stored for the partner user.

````