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

# Auth + Device Fingerprint

> Validates an OTPless auth token and returns the device fingerprint in one backend-to-backend call. Requires `clientId` and `clientSecret`.

- Read `deviceFingerprinting.status` (`SUCCESS`, `FAILED`, `PENDING`, `TIMEOUT`) before using the data.
- `PENDING` and `TIMEOUT` occur only in ASYNC mode.
- A `FAILED` fingerprint does not mean auth failed; the top-level `status` is still `SUCCESS`.


Validate an OTPless auth token and retrieve device fingerprint data in a single backend call. Call this after the OTPless SDK returns an auth token; the response includes both authentication details and device fingerprint data.

<Info>
  **Device fingerprinting mode.** The OTPless SDK supports two modes, ASYNC and SYNC, configured by your native developer at the SDK level. Both modes use this same endpoint; only the timing of when the token is available to your app differs.
</Info>

## Integration flows

Both modes call this same endpoint. The difference is only in when the SDK returns the auth token to your app.

### ASYNC mode

Authentication and device fingerprinting run concurrently. The SDK returns the auth token as soon as authentication completes, without waiting for fingerprinting to finish. The fingerprint result is attached by the OTPless backend when your backend calls validate token.

| Step | Actor           | Action                                                                                                                                                                                              |
| ---- | --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 1    | Client App      | OTPless SDK initiates authentication. Device fingerprinting runs in the background concurrently.                                                                                                    |
| 2    | OTPless SDK     | Authentication completes and returns the auth token to the Client App. Fingerprinting continues in the background.                                                                                  |
| 3    | Client App      | Receives the auth token and sends it to the Client Backend.                                                                                                                                         |
| 4    | Client Backend  | Calls `POST /auth/v2/validate/token` with the token to validate authentication and retrieve device fingerprint data.                                                                                |
| 5    | OTPless Backend | Validates the token, attaches the fingerprint result (if available), and returns the full response.                                                                                                 |
| 6    | Client Backend  | Reads `deviceFingerprinting.status`: SUCCESS includes full data, FAILED means fingerprinting errored, PENDING means fingerprinting not yet complete, TIMEOUT means the threshold time was exceeded. |

### SYNC mode

The SDK returns the auth token only after both authentication and device fingerprinting have completed. This guarantees fingerprint data is always available when your backend calls validate token.

| Step | Actor           | Action                                                                                                     |
| ---- | --------------- | ---------------------------------------------------------------------------------------------------------- |
| 1    | Client App      | OTPless SDK initiates authentication and device fingerprinting together.                                   |
| 2    | OTPless SDK     | Waits for both authentication and device fingerprinting to complete before returning.                      |
| 3    | Client App      | Receives the auth token only after fingerprinting is complete. Sends the token to the Client Backend.      |
| 4    | Client Backend  | Calls `POST /auth/v2/validate/token` with the token.                                                       |
| 5    | OTPless Backend | Validates the token and returns the full response with device fingerprint data.                            |
| 6    | Client Backend  | Reads `deviceFingerprinting.status`: SUCCESS includes full fingerprint data, FAILED includes message only. |

<Info>
  `PENDING` and `TIMEOUT` can only occur in ASYNC mode, where the SDK returns the auth token before fingerprinting completes. In SYNC mode, the SDK waits for fingerprinting to finish, so the status is always `SUCCESS` or `FAILED`.
</Info>


## OpenAPI

````yaml POST /auth/v2/validate/token
openapi: 3.0.3
info:
  title: Auth + Device Fingerprint
  version: 1.0.0
servers:
  - url: https://auth.otpless.app
    description: OTPless authentication service
security:
  - clientIdHeader: []
    clientSecretHeader: []
paths:
  /auth/v2/validate/token:
    post:
      summary: Validate token with device fingerprint
      description: >
        Validates an OTPless auth token and returns the device fingerprint in
        one backend-to-backend call. Requires `clientId` and `clientSecret`.


        - Read `deviceFingerprinting.status` (`SUCCESS`, `FAILED`, `PENDING`,
        `TIMEOUT`) before using the data.

        - `PENDING` and `TIMEOUT` occur only in ASYNC mode.

        - A `FAILED` fingerprint does not mean auth failed; the top-level
        `status` is still `SUCCESS`.
      operationId: validateTokenWithDeviceFingerprint
      requestBody:
        description: Payload containing the auth token received from the OTPless SDK.
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                token:
                  type: string
                  description: The auth token received from the OTPless SDK.
              required:
                - token
      responses:
        '200':
          description: >-
            Authentication completed. Check deviceFingerprinting.status for the
            fingerprint result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidateTokenResponse'
              examples:
                fingerprintAvailable:
                  summary: Success (fingerprint available)
                  value:
                    token: e9e3f030c1384b55bb42f2ecf8fd1786
                    status: SUCCESS
                    userId: MO-ceb09c6e14cf4733b72a4317f30a3f0f
                    timestamp: '2026-05-12T07:19:42Z'
                    identities:
                      - identityType: MOBILE
                        identityValue: 91XXXXXXXXXX
                        channel: SILENT_AUTH
                        methods:
                          - SILENT_AUTH
                        verified: true
                        verifiedAt: '2026-05-12T07:19:42Z'
                    deviceFingerprinting:
                      status: SUCCESS
                      sessionId: 8481663f-ceec-499d-ba04-2afd1527cdb8
                      deviceId: 781b21f7-220b-4f44-9155-6261f8564924
                      newDevice: false
                      riskAssessment:
                        sessionRiskLevel: HIGH
                        deviceRiskLevel: HIGH
                        sessionRiskScore: 99
                        deviceRiskScore: 95
                        ipFraudScore: 0
                        flags:
                          isAppTampered: true
                          debuggingEnabled: true
                          googlePlayStoreInstall: false
                      deviceContext:
                        brand: iQOO
                        model: I2410
                        os: Android
                        osVersion: '16'
                        screenResolution: 1080x2238
                        totalRamBytes: 7804567552
                        simInfo:
                          totalSimsUsed: 5
                          activeSims:
                            - id: 4
                              slotIndex: 0
                              carrierName: Vi India
                            - id: 1
                              slotIndex: 1
                              carrierName: airtel
                      networkContext:
                        ipAddress: xxx.xxx.xxx.xxx
                        isp: Bharti Airtel Limited
                        location:
                          city: Ahmedabad
                          region: Gujarat
                          country: India
                fingerprintUnavailable:
                  summary: Fingerprint unavailable (auth still succeeded)
                  value:
                    token: 51086843d2bd432ebff9d8ec33b07202
                    status: SUCCESS
                    userId: MO-ceb09c6e14cf4733b72a4317f30a3f0f
                    timestamp: '2026-05-11T14:19:59Z'
                    identities:
                      - identityType: MOBILE
                        identityValue: 91XXXXXXXXXX
                        channel: SILENT_AUTH
                        methods:
                          - SILENT_AUTH
                        verified: true
                        verifiedAt: '2026-05-11T14:19:59Z'
                    deviceFingerprinting:
                      status: FAILED
                      message: Device intelligence data not available
        '400':
          description: Bad Request - missing or invalid request parameters.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                message: Invalid Request
                errorCode: '7114'
                description: 'Request error: Invalid token'
        '401':
          description: >-
            Unauthorized - the token is expired, or clientId / clientSecret is
            missing or invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                tokenExpired:
                  summary: Token is expired
                  value:
                    message: Expired
                    errorCode: '7301'
                    description: 'Request error: Token is expired'
                merchantCredentialsEmpty:
                  summary: Merchant credentials are empty
                  value:
                    message: Access blocked
                    errorCode: '7012'
                    description: 'Authorization error: Merchant credentials are empty'
                invalidCredentials:
                  summary: Invalid credentials
                  value:
                    message: Access blocked
                    errorCode: '7002'
                    description: 'Authorization error: Invalid credentials'
      x-codeSamples:
        - lang: shell
          label: cURL
          source: |
            curl --location 'https://auth.otpless.app/auth/v2/validate/token' \
              --header 'Content-Type: application/json' \
              --header 'clientId: YOUR_CLIENT_ID' \
              --header 'clientSecret: YOUR_CLIENT_SECRET' \
              --data '{
                  "token": "1efbffd3ebd64132b7b9d0c08ac063b3"
              }'
components:
  schemas:
    ValidateTokenResponse:
      type: object
      properties:
        token:
          type: string
          description: The auth token passed in the request.
        status:
          type: string
          description: SUCCESS when authentication passed.
          example: SUCCESS
        userId:
          type: string
          description: Unique user identifier assigned by OTPless.
        timestamp:
          type: string
          format: date-time
          description: ISO 8601 timestamp of the authentication event.
        identities:
          type: array
          items:
            $ref: '#/components/schemas/Identity'
        deviceFingerprinting:
          $ref: '#/components/schemas/DeviceFingerprinting'
    ErrorResponse:
      type: object
      properties:
        message:
          type: string
          description: Short error message.
        errorCode:
          type: string
          description: OTPless error code.
        description:
          type: string
          description: Longer error description.
    Identity:
      type: object
      properties:
        identityType:
          type: string
          description: Type of identity verified, e.g. MOBILE, EMAIL.
          example: MOBILE
        identityValue:
          type: string
          description: The verified identity value, e.g. the phone number.
          example: 91XXXXXXXXXX
        channel:
          type: string
          description: Authentication channel used, e.g. SILENT_AUTH, OTP.
          example: SILENT_AUTH
        methods:
          type: array
          items:
            type: string
          example:
            - SILENT_AUTH
        verified:
          type: boolean
          example: true
        verifiedAt:
          type: string
          format: date-time
    DeviceFingerprinting:
      type: object
      description: >-
        Device fingerprint result. Present when Device Fingerprinting is
        enabled.
      properties:
        status:
          type: string
          enum:
            - SUCCESS
            - FAILED
            - PENDING
            - TIMEOUT
          description: >-
            SUCCESS includes the full fingerprint data. FAILED means
            fingerprinting could not complete (status and message only). PENDING
            means fingerprinting had not completed when the token was validated
            (ASYNC only). TIMEOUT means it exceeded the allowed threshold and
            was terminated (ASYNC only).
        message:
          type: string
          description: >-
            Descriptive message. Present when status is FAILED, PENDING, or
            TIMEOUT.
        sessionId:
          type: string
          description: Session identifier. Present on SUCCESS.
        deviceId:
          type: string
          description: Persistent device identifier. Present on SUCCESS.
        newDevice:
          type: boolean
          description: true if this device has not been seen before. Present on SUCCESS.
        riskAssessment:
          $ref: '#/components/schemas/RiskAssessment'
        deviceContext:
          type: object
          description: >-
            Hardware, storage, lifecycle, and SIM information. Present on
            SUCCESS.
        networkContext:
          type: object
          description: IP address, ISP, and geolocation. Present on SUCCESS.
    RiskAssessment:
      type: object
      description: Risk scores and boolean flags. Present on SUCCESS.
      properties:
        sessionRiskLevel:
          type: string
          example: HIGH
        deviceRiskLevel:
          type: string
          example: HIGH
        sessionRiskScore:
          type: integer
          example: 99
        deviceRiskScore:
          type: integer
          example: 95
        ipFraudScore:
          type: integer
          example: 0
        flags:
          type: object
          description: Boolean device signals.
  securitySchemes:
    clientIdHeader:
      type: apiKey
      in: header
      name: clientId
      description: The clientId used for API authentication.
    clientSecretHeader:
      type: apiKey
      in: header
      name: clientSecret
      description: The clientSecret used for API authentication.

````