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

# Create and dispatch a PIN

> Generate a PIN and send it to one or more channels in parallel.

This is the call that starts a verification. OneXtel generates the PIN, substitutes it into the
template's content for each channel you asked for, and dispatches to all of them **in parallel** —
then returns a `pinId` and what each channel did.

Hold on to the `pinId`. It is what you [verify](/api-reference/verify/verify-a-pin) against, and
what you [resend](/api-reference/verify/resend-a-pin) on. The code itself is never returned to
you and never stored in the clear.

<Note>
  Omit `channels` to send on the template's default channel. Pass it to override — every channel you
  name must already have a channel account configured on that template, or the call fails with
  `channel_not_configured`.
</Note>

## Partial success

A `201` means **at least one** channel accepted the message, not all of them. Read `channels[]`
to see which:

```json Response — SMS accepted, WhatsApp rejected theme={null}
{
  "pinId": "pin_x9k2m1qz",
  "status": "PENDING",
  "expiresAt": "2026-08-04T10:22:03.221Z",
  "attemptsRemaining": 3,
  "channels": [
    { "channel": "sms", "status": "accepted", "providerMessageId": "3f9a1c02" },
    { "channel": "whatsapp", "status": "rejected", "errorCode": "131047", "errorMessage": "Re-engagement message" }
  ]
}
```

Only when **every** requested channel is rejected do you get `502 dispatch_failed`. So do not
retry on a `201` — the user has a code.

<Warning>
  Always send the `Idempotency-Key` header on this call. Without it, a network timeout you retry
  will dispatch a second PIN and invalidate the first, and the user will be typing a code that no
  longer verifies. See [Idempotency](/api-reference/verify/overview#idempotency).
</Warning>


## OpenAPI

````yaml POST /v1/pins
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:
    post:
      tags:
        - Pins
      summary: Create and dispatch a PIN
      description: >
        Generates a PIN, dispatches it synchronously to every requested channel
        in parallel, and returns per-channel dispatch status. `201` covers
        partial failure (at least one channel accepted); `502 dispatch_failed`
        means every requested channel was rejected.
      operationId: createPin
      parameters:
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreatePinRequest'
      responses:
        '201':
          description: At least one channel accepted the message.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PinDispatchResponse'
        '400':
          $ref: '#/components/responses/ValidationFailed'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          description: '`not_found` / `template_not_found`'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: >-
            `template_disabled` / `channel_not_configured` /
            `channel_account_disabled` / `idempotency_key_reuse` /
            `idempotency_in_progress`
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: '`rate_limited` / `daily_cap_exceeded`'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '502':
          description: '`dispatch_failed`'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  parameters:
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      description: >
        Protects a send/resend against duplicate dispatch on retry. Replaying
        the same key + body within 24h returns the original response verbatim;
        the same key with a different body is rejected
        (`idempotency_key_reuse`); a concurrent request with the same key still
        in flight is rejected (`idempotency_in_progress`).
      schema:
        type: string
  schemas:
    CreatePinRequest:
      type: object
      required:
        - destination
        - templateId
      properties:
        destination:
          type: string
          minLength: 1
          maxLength: 64
          description: >-
            Destination, exactly as the active provider expects it — never
            reformatted.
          examples:
            - '+919876543210'
        templateId:
          type: string
          minLength: 1
          description: The template to send under.
          examples:
            - tpl_abc123
        channels:
          type: array
          minItems: 1
          description: Channels to dispatch on. Omit to use the template's default channel.
          items:
            $ref: '#/components/schemas/ChannelType'
          examples:
            - - sms
        referenceId:
          type: string
          minLength: 1
          maxLength: 200
          description: >-
            Optional caller-supplied correlation id, searchable in
            Verifications.
          examples:
            - order_1234
        templateParams:
          $ref: '#/components/schemas/TemplateParams'
    PinDispatchResponse:
      type: object
      properties:
        pinId:
          type: string
          examples:
            - pin_x9k2m1qz
        status:
          type: string
          enum:
            - PENDING
            - VERIFIED
            - EXPIRED
            - BLOCKED
          examples:
            - PENDING
        expiresAt:
          type: string
          format: date-time
          examples:
            - '2026-08-04T10:22:03.221Z'
        attemptsRemaining:
          type: integer
          examples:
            - 3
        channels:
          type: array
          items:
            $ref: '#/components/schemas/ChannelDispatch'
    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
    ChannelType:
      type: string
      enum:
        - sms
        - whatsapp
        - email
    TemplateParams:
      type: object
      description: >
        Per-send override for a WhatsApp template's non-OTP placeholders, by
        position. Omitted positions fall back to the template's stored default.
      additionalProperties:
        type: string
      examples:
        - '1': Jane Doe
          '2': ORD-1234
    ChannelDispatch:
      type: object
      properties:
        channel:
          $ref: '#/components/schemas/ChannelType'
        status:
          type: string
          enum:
            - accepted
            - rejected
            - error
          description: >
            `accepted` — the provider took the message. `rejected` — the
            provider refused it. `error` — the dispatch itself failed (timeout,
            transport, unexpected response).
        providerMessageId:
          type: string
          description: The provider's id for the message, when it returned one.
        errorCode:
          type: string
        errorMessage:
          type: string
  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.