> ## Documentation Index
> Fetch the complete documentation index at: https://onextel-09023014.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Verify a PIN

> Check the code the user typed against the stored hash.

Submit the code exactly as the user typed it. OneXtel compares it against the stored hash in
constant time, so the comparison itself leaks nothing about how close a wrong guess was.

## Reading the outcome

A `200` is the only success. Everything else is a distinct error code, and they mean different
things to your UI:

| Code | HTTP | What to show the user |
| - | - | - |
| — | 200 | Verified — continue the flow |
| `pin_incorrect` | 422 | "That code isn't right" — offer a retry |
| `pin_expired` | 410 | "That code has expired" — offer a resend |
| `pin_blocked` | 409 | "Too many attempts" — offer a resend |
| `pin_already_verified` | 409 | Already used — treat as done, or start a new send |

<Note>
  Expired and incorrect are deliberately separate codes. Collapsing them into one "invalid code"
  message makes a user who waited too long retype a code that can never work.
</Note>

## Attempts

Both the `200` response and a `pin_incorrect` error carry `attemptsRemaining`. Use it to warn
before the PIN is spent — at zero, the next wrong guess returns `pin_blocked` and the PIN is
dead. The allowance is set per template as `pinAttempts` and is reset by every
[resend](/api-reference/verify/resend-a-pin).

Verify calls are rate limited per template via `verifyPinLimit`; exceeding it returns
`rate_limited` (429).


## OpenAPI

````yaml POST /v1/pins/{pinId}/verify
openapi: 3.1.0
info:
  title: Onextel Verify API
  version: 1.0.0
  description: >
    Generate, dispatch and verify one-time PINs across SMS, WhatsApp and email.


    Every request is authenticated with an API key created from the OneXtel
    portal's

    **Developers → API Keys** page, sent as a bearer token.


    Every error response carries the same shape — see

    [Verify Error Codes](/api-reference/verify/error-codes) for the full list:


    ```json

    { "error": { "code": "pin_expired", "message": "...", "details": {},
    "requestId": "req_..." } }

    ```
servers:
  - url: https://api.onexaura.com
    description: Production
security:
  - bearerAuth: []
tags:
  - name: Pins
    description: Create, resend and verify one-time PINs.
  - name: Templates
    description: The templates a PIN can be sent under.
  - name: Channel Accounts
    description: The provider accounts a channel dispatches through.
paths:
  /v1/pins/{pinId}/verify:
    post:
      tags:
        - Pins
      summary: Verify a PIN
      description: >
        Constant-time comparison against the stored hash. Expired and incorrect
        are distinct error codes.
      operationId: verifyPin
      parameters:
        - $ref: '#/components/parameters/PinId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/VerifyPinRequest'
      responses:
        '200':
          description: The PIN matched.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VerifyPinResponse'
        '400':
          $ref: '#/components/responses/ValidationFailed'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          description: '`pin_not_found`'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: '`pin_already_verified` / `pin_blocked`'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '410':
          description: '`pin_expired`'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '422':
          description: '`pin_incorrect`'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: '`rate_limited`'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '502':
          description: '`dispatch_failed`'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  parameters:
    PinId:
      name: pinId
      in: path
      required: true
      schema:
        type: string
        examples:
          - pin_x9k2m1qz
  schemas:
    VerifyPinRequest:
      type: object
      required:
        - pin
      properties:
        pin:
          type: string
          description: The code as the end user typed it.
          examples:
            - '123456'
    VerifyPinResponse:
      type: object
      properties:
        pinId:
          type: string
          examples:
            - pin_x9k2m1qz
        status:
          type: string
          examples:
            - VERIFIED
        attemptsRemaining:
          type: integer
          examples:
            - 2
    Error:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              examples:
                - pin_expired
            message:
              type: string
            requestId:
              type: string
              examples:
                - req_9f3a2c
            details:
              type: object
              additionalProperties: true
  responses:
    ValidationFailed:
      description: '`validation_failed`'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unauthenticated:
      description: '`unauthenticated`'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Forbidden:
      description: '`forbidden` / `workspace_disabled`'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        An API key from the OneXtel portal, **Developers → API Keys**, sent as
        `Authorization: Bearer <key>`.

````

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