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

> ## Agent Instructions
> Money amounts are always major-unit decimal strings (e.g. "1000.00"), never floats and never minor units, in every request, response, and webhook payload.
> Authentication is OAuth 2.0 client credentials: exchange the Client ID and Client Secret at the Token URL for a 24-hour JWT and cache it; do not request a token per call.
> Set a unique clientRef on every money-moving request; it is the idempotency key, and retries return the original resource.
> Quotes are single-use, intent-locked, and expire fast: always read expiresAt, consume the quote with the executor matching its intent, and re-quote on expiry instead of retrying.
> Prefer webhooks over polling for payout, order, application, and virtual-account status tracking.
> Use the sandbox (api.sandbox.zuba.com) with its deterministic magic values before touching production.

# Start the applicant's identity verification

> Starts an identity verification attempt for the application’s applicant and returns `url`, a hosted verification page. Send the applicant to it: they complete the identity check there, with no Zuba dashboard session, and the outcome reaches Zuba by webhook; read it back from GET /v2/applications/{id}/identity-verification. The link is valid until the session expires under the verification workflow’s expiry, and is returned only here, so start a new session for a new link. A new attempt replaces an earlier one, a `waived` outcome included, which then reads `pending` and no longer satisfies POST /v2/applications/{id}/submit until the attempt passes. A start is refused (409) while an attempt is still being decided by the verification provider or a reviewer, for an applicant already verified, and when the attempt changes while starting. A `verified` or `waived` outcome satisfies the identity requirement of POST /v2/applications/{id}/submit.



## OpenAPI

````yaml /openapi.json post /v2/applications/{id}/identity-verification/session
openapi: 3.0.0
info:
  contact: {}
  description: >-
    Comprehensive payment platform API supporting fiat and crypto payments,
    currency conversion, and compliance management
  title: Zuba Payment Platform API
  version: '1.0'
servers: []
security: []
tags:
  - description: Manage M2M API keys and credentials
    name: API Keys
  - description: Per-country bank directories and bank-account enquiries
    name: Banks
  - description: Internal ledger accounts and transactions
    name: Ledger
  - description: Handle incoming payments and deposits
    name: Pay-ins
  - description: Manage payouts, beneficiaries, and SEPA transfers
    name: Payouts
  - description: Manage outbound webhook endpoints and deliveries
    name: Webhooks
paths:
  /v2/applications/{id}/identity-verification/session:
    post:
      tags:
        - Applications (v2)
      summary: Start the applicant's identity verification
      description: >-
        Starts an identity verification attempt for the application’s applicant
        and returns `url`, a hosted verification page. Send the applicant to it:
        they complete the identity check there, with no Zuba dashboard session,
        and the outcome reaches Zuba by webhook; read it back from GET
        /v2/applications/{id}/identity-verification. The link is valid until the
        session expires under the verification workflow’s expiry, and is
        returned only here, so start a new session for a new link. A new attempt
        replaces an earlier one, a `waived` outcome included, which then reads
        `pending` and no longer satisfies POST /v2/applications/{id}/submit
        until the attempt passes. A start is refused (409) while an attempt is
        still being decided by the verification provider or a reviewer, for an
        applicant already verified, and when the attempt changes while starting.
        A `verified` or `waived` outcome satisfies the identity requirement of
        POST /v2/applications/{id}/submit.
      operationId: ApplicationV2Controller_startIdentityVerification
      parameters:
        - in: path
          name: id
          required: true
          schema:
            format: uuid
            type: string
      responses:
        '201':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApplicationIdentityVerificationSessionDto'
          description: ''
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenericErrorResponseDto'
          description: >-
            The application id is not a UUID, or the identity provider refused a
            request while starting verification, other than a rate limit
        '403':
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/GenericErrorResponseDto'
                  - $ref: '#/components/schemas/StepLockedErrorResponseDto'
          description: >-
            The application is back for more information without the step open
            to redo: step_locked (body adds `lockedStep` and `editableSteps`).
            An application that cannot be changed in its status (under review,
            approved or rejected), one belonging to another account, or a
            dashboard session whose workspace role is viewer (Insufficient
            role), returns a generic body.
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenericErrorResponseDto'
          description: Not found
        '409':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenericErrorResponseDto'
          description: >-
            `error` names the cause: identity_already_verified (the applicant is
            already verified), identity_verification_in_review (the current
            attempt is still being decided) or identity_verification_changed
            (the attempt changed while starting). Read GET
            /v2/applications/{id}/identity-verification for the current state.
        '429':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenericErrorResponseDto'
          description: The identity provider is rate limiting starts; retry in a minute
        '503':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenericErrorResponseDto'
          description: Identity verification is not available in this environment
      security:
        - bearer: []
components:
  schemas:
    ApplicationIdentityVerificationSessionDto:
      properties:
        sessionId:
          description: >-
            The attempt's session id. Null in the sandbox, where starting a
            session verifies the applicant at once.
          nullable: true
          type: string
        status:
          description: >-
            `pending` until the applicant completes the link and the outcome
            arrives; read it back from GET
            /v2/applications/{id}/identity-verification. `verified` in the
            sandbox, where starting a session verifies the applicant at once.
          enum:
            - pending
            - verified
          type: string
        submittedAt:
          description: >-
            When the attempt reached its outcome: null while it is pending, set
            in the sandbox, where the attempt is verified at once.
          format: date-time
          nullable: true
          type: string
        url:
          description: >-
            The hosted verification page for this attempt. Send the applicant to
            it: they complete the identity check there, and the outcome reaches
            Zuba by webhook. Valid until the session expires under the
            verification workflow’s expiry. It is returned only here and never
            stored, so start a new session for a new link. Null in the sandbox,
            where starting a session verifies the applicant at once.
          nullable: true
          type: string
      required:
        - status
        - sessionId
        - submittedAt
        - url
      type: object
    GenericErrorResponseDto:
      properties:
        error:
          description: Error type identifier
          example: BAD_REQUEST
          type: string
        message:
          description: Error message
          example: Bad Request
          type: string
        path:
          description: Request path that generated the error
          example: /v1/resource
          type: string
        statusCode:
          description: HTTP status code
          example: 400
          type: number
        timestamp:
          description: ISO timestamp when the error occurred
          example: '2024-01-15T10:30:00.000Z'
          type: string
      required:
        - statusCode
        - message
        - error
        - timestamp
        - path
      type: object
    StepLockedErrorResponseDto:
      properties:
        editableSteps:
          description: Sections the reviewer did flag for editing
          example:
            - documents
          items:
            type: string
          type: array
        error:
          description: Error type identifier
          example: step_locked
          type: string
        lockedStep:
          description: Section rejected because it was not flagged by the reviewer
          example: business_info
          type: string
        message:
          description: Error message
          example: Bad Request
          type: string
        path:
          description: Request path that generated the error
          example: /v1/resource
          type: string
        statusCode:
          description: HTTP status code
          example: 400
          type: number
        timestamp:
          description: ISO timestamp when the error occurred
          example: '2024-01-15T10:30:00.000Z'
          type: string
      required:
        - statusCode
        - message
        - error
        - timestamp
        - path
        - lockedStep
        - editableSteps
      type: object
  securitySchemes:
    bearer:
      bearerFormat: JWT
      description: Enter Auth0 JWT token
      scheme: bearer
      type: http

````

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