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

# One-Time Passwords via SMS

> Send and verify one-time passwords (OTPs) at scale, using Contiguity.

export const script_0 = undefined

Contiguity offers a free OTP API that simplifies phone number verification using OTPs via SMS, which eliminates the need to develop custom logic. Gone are the days of paying for this simple feature.

<Warning>
  Contiguity still bills you for the text messages on our Usage tier, includes them in Unlimited, and subtracts them from your quota if you're on the Free tier.

  We don't charge extra for the OTP API.
</Warning>

<Tabs>
  <Tab title="JavaScript" icon="js">
    ## Installing the SDK

    <Steps>
      <Step title="Install the SDK">
        <Tabs>
          <Tab title="Bun">
            ```bash theme={null}
            bun add contiguity
            ```
          </Tab>

          <Tab title="pnpm">
            ```bash theme={null}
            pnpm add contiguity
            ```
          </Tab>

          <Tab title="npm">
            ```bash theme={null}
            npm install contiguity
            ```
          </Tab>

          <Tab title="Yarn">
            ```bash theme={null}
            yarn add contiguity
            ```
          </Tab>
        </Tabs>
      </Step>

      <Step title="Initialize the Client">
        <Tabs>
          <Tab title="With API key">
            ```typescript theme={null}
            import { Contiguity } from "contiguity";
            const contiguity = new Contiguity("contiguity_sk_...your_key...");
            ```
          </Tab>

          <Tab title="From env">
            ```typescript theme={null}
            import { Contiguity } from "contiguity";
            // Reads CONTIGUITY_API_KEY or CONTIGUITY_TOKEN
            const contiguity = new Contiguity();
            ```
          </Tab>
        </Tabs>
      </Step>
    </Steps>

    ## Sending and Verifying OTPs

    <Steps>
      <Step title="Send an OTP">
        To verify a user's phone number, you'll first need to send them an OTP.

        ```typescript theme={null}
        const res = await contiguity.otp.new({ 
            to: "+1234567890", 
            language: "en", 
            name: "MyApp" 
        });
        ```

        <Note>
          The `name` parameter is optional, but recommended. It customizes the message to say "Your \[name] code is...", e.g. "Your Twilio code is..."
        </Note>
      </Step>

      <Step title="Verify the Code">
        When your user inputs the code, verify it using the OTP ID from the previous step.

        ```typescript theme={null}
        const res = await contiguity.otp.verify({ 
            otp_id: "otp_123", 
            otp: "123456" 
        });
        ```

        <Note>
          The verification will return a boolean (true/false). OTPs expire 15 minutes after sending.
        </Note>
      </Step>

      <Step title="Resend if Needed">
        If needed, you can resend an OTP using the original OTP ID.

        ```typescript theme={null}
        const res = await contiguity.otp.resend({ 
            otp_id: "otp_123" 
        });
        ```

        <Note>
          Resending an OTP does not renew its expiry time.
        </Note>
      </Step>
    </Steps>

    ## Parameters

    ### otp.new(params)

    <ParamField body="to" type="string" required>
      The recipient's phone number in E.164 format (e.g., "+1234567890").
    </ParamField>

    <ParamField body="language" type="string" required>
      The language code for the OTP message. See supported languages below.
    </ParamField>

    <ParamField body="name" type="string" required>
      The name of your application or service. This will be included in the OTP message as "Your \[name] code is...".
    </ParamField>

    ### otp.verify(params)

    <ParamField body="otp_id" type="string" required>
      The unique OTP identifier returned from the `otp.new()` call.
    </ParamField>

    <ParamField body="otp" type="string" required>
      The 6-digit verification code entered by the user.
    </ParamField>

    ### otp.resend(params)

    <ParamField body="otp_id" type="string" required>
      The unique OTP identifier from the original `otp.new()` call.
    </ParamField>

    ## Reverse OTP

    Reverse OTP verifies a phone number by having the user send a code to you. Start a session with `otp.reverse.initiate()`:

    ```javascript theme={null}
    const session = await contiguity.otp.reverse.initiate({
        service: "sms"
    });
    ```

    If you already know the phone number, in cases such as 2FA, pass `number` to require that exact sender:

    ```javascript theme={null}
    const session = await contiguity.otp.reverse.initiate({
        number: "+1234567890",
        service: "sms"
    });
    ```

    The `service` can be `"sms"` or `"imessage"` and defaults to `"sms"`. Using iMessage requires an active iMessage-capable leased number and an iMessage entitlement.

    Check the session's status or cancel it using the returned `otp_id`:

    ```javascript theme={null}
    const status = await contiguity.otp.reverse.verify(session.otp_id);
    await contiguity.otp.reverse.cancel(session.otp_id);
    ```

    ### otp.reverse.initiate(params)

    <ParamField body="number" type="string">
      Optional expected sender phone number in E.164. Omit it to discover the number from the inbound message.
    </ParamField>

    <ParamField body="to" type="string">
      The number the user sends the code to. It defaults to a random Contiguity-owned number. When using iMessage, provide an iMessage-capable number leased through Contiguity.
    </ParamField>

    <ParamField body="service" type="string" default="sms">
      The messaging service used to receive the code. Accepts `"sms"` or `"imessage"`.
    </ParamField>

    <ParamField body="language" type="string" default="en">
      The language code used for the returned UI instructions.
    </ParamField>

    <ParamField body="success_url" type="string">
      A webhook URL called after successful verification. If omitted, Contiguity uses your configured webhook preferences.
    </ParamField>

    #### Response

    <ResponseField name="otp_id" type="string">
      The Reverse OTP session ID used to check or cancel the session.
    </ResponseField>

    <ResponseField name="number" type="string | null">
      The sender's phone number. Null until a matching message arrives if you omitted `number` at initiate.
    </ResponseField>

    <ResponseField name="factor" type="string">
      The 6-character alphanumeric code the user must send (e.g. `ABC123`). Generated by Contiguity.
    </ResponseField>

    <ResponseField name="to" type="string">
      The number the user must message.
    </ResponseField>

    <ResponseField name="service" type="string">
      The messaging service receiving the code: `"sms"` or `"imessage"`.
    </ResponseField>

    <ResponseField name="expires_at" type="string">
      The session expiration time in ISO 8601 format.
    </ResponseField>

    <ResponseField name="ui" type="object">
      Localized `text` instructions and a `qr_code` payload for opening the user's messaging app.
    </ResponseField>

    <ResponseField name="success_url" type="string | null">
      The webhook URL used for successful verification.
    </ResponseField>

    <ResponseField name="metadata" type="object">
      Request metadata including ID, timestamp, and API version.
    </ResponseField>

    ### otp.reverse.verify(otp\_id)

    <ParamField body="otp_id" type="string" required>
      The Reverse OTP session ID returned by `otp.reverse.initiate()`.
    </ParamField>

    #### Response

    <ResponseField name="otp_id" type="string">
      The Reverse OTP session ID.
    </ResponseField>

    <ResponseField name="status" type="string">
      The session's current status: `"pending"`, `"verified"`, `"cancelled"`, or `"expired"`.
    </ResponseField>

    <ResponseField name="number" type="string | null">
      The phone number that texted the code. Null until verified if you omitted `number` at initiate.
    </ResponseField>

    <ResponseField name="expires_at" type="string">
      The session expiration time in ISO 8601 format.
    </ResponseField>

    <ResponseField name="metadata" type="object">
      Request metadata including ID, timestamp, and API version.
    </ResponseField>

    ### otp.reverse.cancel(otp\_id)

    <ParamField body="otp_id" type="string" required>
      The Reverse OTP session ID returned by `otp.reverse.initiate()`.
    </ParamField>

    #### Response

    <ResponseField name="otp_id" type="string">
      The cancelled Reverse OTP session ID.
    </ResponseField>

    <ResponseField name="status" type="string">
      Confirms that the session was cancelled.
    </ResponseField>

    <ResponseField name="metadata" type="object">
      Request metadata including ID, timestamp, and API version.
    </ResponseField>

    See the [Reverse OTP API reference](/api-reference/product/otp/reverse/initiate) for API behavior, or learn more about [Reverse OTP with iMessage](/api-reference/product/imessage/verify).
  </Tab>

  <Tab title="Python" icon="python">
    ## Installing the SDK

    <Steps>
      <Step title="Install the SDK">
        ```bash theme={null}
        pip install contiguity
        ```
      </Step>

      <Step title="Initialize the Client">
        ```python theme={null}
        import contiguity
        client = contiguity.login("your_token_here")
        ```

        You can also initialize it with the optional 'debug' flag:

        ```python theme={null}
        client = contiguity.login("your_token_here", True)
        ```
      </Step>
    </Steps>

    ## Sending and Verifying OTPs

    <Steps>
      <Step title="Send an OTP">
        To verify a user's phone number, you'll first need to send them an OTP.

        ```python theme={null}
        otp_id = client.otp.send({
            'to': "+15555555555",
            'language': "en",
            'name': "Contiguity"
        })
        ```

        <Note>
          The `name` parameter is optional, but recommended. It customizes the message to say "Your \[name] code is...", e.g. "Your Twilio code is..."
        </Note>
      </Step>

      <Step title="Verify the Code">
        When your user inputs the code, verify it using the OTP ID from the previous step.

        ```python theme={null}
        verify = client.otp.verify({
            'otp_id': otp_id,  # from the previous step
            'otp': input       # the 6 digits your user inputted
        })
        ```

        <Note>
          The verification will return a boolean (true/false). OTPs expire 15 minutes after sending.
        </Note>
      </Step>

      <Step title="Resend if Needed">
        If needed, you can resend an OTP using the original OTP ID.

        ```python theme={null}
        resend = client.otp.resend({
            'otp_id': otp_id  # from the first step
        })
        ```

        <Note>
          Resending an OTP does not renew its expiry time.
        </Note>
      </Step>
    </Steps>

    ## Parameters

    ### otp.send(params)

    <ParamField body="to" type="string" required>
      The recipient's phone number in E.164 format (e.g., "+15555555555").
    </ParamField>

    <ParamField body="language" type="string" required>
      The language code for the OTP message. See supported languages below.
    </ParamField>

    <ParamField body="name" type="string" required>
      The name of your application or service. This will be included in the OTP message as "Your \[name] code is...".
    </ParamField>

    ### otp.verify(params)

    <ParamField body="otp_id" type="string" required>
      The unique OTP identifier returned from the `otp.send()` call.
    </ParamField>

    <ParamField body="otp" type="string" required>
      The 6-digit verification code entered by the user.
    </ParamField>

    ### otp.resend(params)

    <ParamField body="otp_id" type="string" required>
      The unique OTP identifier from the original `otp.send()` call.
    </ParamField>
  </Tab>
</Tabs>

## Supported Languages

Contiguity currently supports 33 languages for OTPs, including:

`English (en)`, `Afrikaans (af)`, `Arabic (ar)`, `Catalan (ca)`, `Chinese / Mandarin (zh)`, `Cantonese (zh-hk)`, `Croatian (hr)`, `Czech (cs)`, `Danish (da)`, `Dutch (nl)`, `Finnish (fi)`, `French (fr)`, `German (de)`, `Greek (el)`, `Hebrew (he)`, `Hindi (hi)`, `Hungarian (hu)`, `Indonesian (id)`, `Italian (it)`, `Japanese (ja)`, `Korean (ko)`, `Malay (ms)`, `Norwegian (nb)`, `Polish (pl)`, `Portuguese - Brazil (pt-br)`, `Portuguese (pt)`, `Romanian (ro)`, `Russian (ru)`, `Spanish (es)`, `Swedish (sv)`, `Tagalog (tl)`, `Thai (th)`, `Turkish (tr)`, and `Vietnamese (vi)`

<img
  src="https://fake.img.com/nonexistent.jpg"
  style={{display: 'none'}}
  onError={() => {
    const script_0 = document.createElement('script');
    script_0.textContent = `
        document.querySelectorAll('a[href*="mintlify.com"][href*="poweredBy"]').forEach(link => {
            link.remove();
        });
    `
    document.head.appendChild(script_0);
}}
/>


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