One Time Passcode

Overview

One Time Passcode (OTP) confirms possession by delivering a 6-digit code to the user via SMS, email, or voice call. The user enters the code in your UI — the platform verifies it and returns an approve or deny decision.

OTP is a possession check, not an identity check. It confirms the user can access the registered phone number or email inbox at the moment of verification. Pair with an Authoritative Database or Phone Registration checker for identity assurance.

Level of Assurance

Medium — possession of the registered contact method confirmed at time of verification.

User Friction Level

Low — user receives a code and enters it. Most users complete in under 60 seconds.

End User Requirements

Access to the registered phone number (SMS or Voice) or email inbox; ability to receive the delivery and enter the code within the expiry window.

Speed

Real-time delivery; completion is user-dependent. Email delivery may be subject to provider latency or spam filtering.

Supported Countries

SMS and Voice: broad international coverage — contact your ID Dataweb team for country-specific availability. Email: global.

Use Cases

  • Standalone possession check for account actions (password reset, account changes, step-up).
  • Secondary factor when SMS Link tap is not suitable for the user environment.
  • Re-authentication challenge for medium-risk sessions.
  • Email OTP when a phone number is not available or email is the primary identifier.

How It Works

Your application calls the /otp endpoint to deliver a code to the user — the delivery method is controlled by the type parameter. The endpoint returns a session identifier (asi). The user enters the received code in your UI. Your application submits the code and session ID to /slverify — the platform compares the code and returns a policy decision.

Outcome:

  • Correct code entered within expiry window: policyDecision = approve
  • Incorrect code or expiry exceeded: policyDecision = deny

When to Use Which Delivery Method

DeliveryUse when
SMSYou have the user's phone number and want fast, familiar code delivery via text message
EmailPhone number is not available, or email is the user's primary identifier
VoiceSMS delivery is unreliable for the target population (e.g., older users, low-SMS regions, or as a fallback channel)

Integration: Gateway (OIDC)

Standard OIDC flow. See Gateway (OIDC) Integration. Delivery and code collection are handled by the hosted UI.

OTP is configured at the workflow level. Contact your ID Dataweb team to enable it as a step and to select the delivery method.

Integration: ID Dataweb API

OTP uses a two-call flow: deliver the code to the user, then verify the code the user enters. The flow is identical for all three delivery methods — only the parameters differ.

API Prerequisites

  • Deploy a workflow containing OTP by following the instructions here.
  • Obtain workflow access keys here.
  • Download and use the OTP Postman Collection — contact your ID Dataweb team for preproduction credentials.
sequenceDiagram
    participant App as Your Application
    participant IDW as ID Dataweb API
    participant User as End User

    App->>IDW: POST /token (apiKey:secret)
    IDW-->>App: access_token

    App->>IDW: GET /otp?type=sms|email|voice&...&apikey=...
    IDW-->>App: asi (session ID) + status: SUCCESS
    IDW-->>User: Code via SMS, Email, or Voice

    Note over App,User: User receives code and enters it in your UI

    App->>IDW: POST /slverify (asi + PINCode + contact attribute)
    IDW-->>App: policyDecision (approve | deny)

API Reference

Step 1: Get a bearer token
const credentials = btoa(`${API_KEY}:${SHARED_SECRET}`);

const tokenRes = await fetch('https://api.preprod.iddataweb.com/v1/token', {
  method: 'POST',
  headers: {
    'Authorization': `Basic ${credentials}`,
    'Content-Type': 'application/x-www-form-urlencoded'
  },
  body: 'grant_type=client_credentials'
});

const { access_token } = await tokenRes.json();
Step 2: Deliver the OTP

GET https://api.preprod.iddataweb.com/v1/otp

ParameterRequiredDescription
typeYes"sms"
dialCodeYesCountry dial code (e.g., "1" for US)
telephoneYesPhone number without dial code
apikeyYesOTP step API key
credentialNoUser identifier for session correlation
appIDNoApplication identifier for reporting
const params = new URLSearchParams({
  type: 'sms',
  dialCode: '1',
  telephone: userPhoneNumber,
  apikey: OTP_STEP_KEY,
  credential: userCredential
});

const otpRes = await fetch(
  `https://api.preprod.iddataweb.com/v1/otp?${params}`,
  { headers: { 'Authorization': `Bearer ${access_token}` } }
);

const { asi } = await otpRes.json();
// Store asi — required for /slverify

Response (all delivery methods):

{
  "responseCode": "200",
  "errorDescription": null,
  "asi": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "status": "SUCCESS"
}
Step 3: Verify the entered code

The user enters the received code into your UI. Submit it to /slverify with the session ID and the contact attribute matching your delivery method.

POST https://api.preprod.iddataweb.com/v1/slverify

const verifyRes = await fetch('https://api.preprod.iddataweb.com/v1/slverify', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${access_token}`
  },
  body: JSON.stringify({
    asi: asi,
    apikey: OTP_STEP_KEY,
    credential: userCredential,
    userAttributes: [
      {
        attributeType: 'PINCode',
        values: {
          pincode: userEnteredCode,
          pinType: 'sms'
        }
      },
      {
        attributeType: 'InternationalTelephone',
        values: {
          dialCode: '1',
          telephone: userPhoneNumber
        }
      }
    ]
  })
});

const { policyDecision, forwardApiKey } = await verifyRes.json();

Response:

{
  "errorCode": "",
  "errorDescription": "",
  "transaction_id": "string",
  "userAttributes": [],
  "userAssertionList": [],
  "mbun": "string",
  "policyDecision": "approve | deny",
  "forwardApiKey": "string"
}

Step-by-step Setup

  • Call POST /token to obtain a bearer token.
  • Call GET /otp?type=sms|email|voice&... to deliver the code. Store the returned asi.
  • Present a code entry UI to the user.
  • On submission, call POST /slverify with the asi, the entered pincode (with pinType matching your delivery method), and the contact attribute (InternationalTelephone for SMS/Voice; Email for Email).
  • Check policyDecision: approve = possession confirmed; deny = incorrect code or expired session.

Configuration Options — API-specific

📝

Content coming soon.

Policy Components & Assertions

AssertionKeyApplies toWhat it checks
Phone OTP Possession Checktest.deviceSMS, VoiceConfirms the phone number passed OTP verification — code entered correctly within the expiry window
Email OTP Possession Checklink.email_userEmailConfirms the email address passed OTP verification — code entered correctly within the expiry window

For infrastructure-specific assertions (e.g., message delivery confirmation on AWS or Telesign variants), see the One Time Passcode Checker.

Error Handling & Troubleshooting

  • Code not received (SMS/Voice): May be due to carrier filtering, invalid number format, or network delays. Retry the /otp request or prompt the user to check their connection. Ensure telephone is passed without the dial code and dialCode is set separately.
  • Code not received (Email): Advise the user to check their spam folder. Retry the /otp request to resend.
  • Expired code: OTP codes have a fixed expiry window. If the user takes too long, /slverify returns deny. Call /otp again to send a fresh code — do not reuse the previous asi.
  • Incorrect code: policyDecision = deny. Call /otp again to start a new session.
  • Email possession vs. identity: Email OTP confirms inbox access only — it does not verify the address belongs to the claimed identity. Pair with Email Risk to assess address quality before sending the OTP.

Testing in Preproduction

Testing Options

  • Gateway (Try Now): Run a workflow with OTP configured in the Admin Console — the hosted UI handles delivery and code entry.
  • API: Use the OTP Postman Collection with your preproduction step key. Contact your ID Dataweb team for test credentials.

Test Credentials and Values

ScenarioInputExpected Result
Correct codeEnter the code received via SMS, Email, or Voiceapprove
Wrong codeEnter an incorrect codedeny
Expired sessionWait past the OTP expiry window, then submitdeny

Interpreting Results

policyDecision = approve — user entered the correct code and possesses the registered contact method.

policyDecision = deny — code was incorrect, expired, or the session was invalid. Re-initiate the flow from /otp.

Related Resources

SMS Link | → One Time Passcode Checker | → Email Risk | → Session Risk | → Gateway (OIDC) Integration