Multi-Step Flow: Send and Verify OTP
The Omnix Gateway provides endpoints to generate, send, and verify One-Time Passwords (OTP) over SMS or Email. This guide covers the 3-step integration flow required to implement secure passwordless verification or 2FA using Omnix.
The 3-Step OTP Lifecycle
Implementing verification follows this sequence:
sequenceDiagram
autonumber
participant App as External Application
participant Omnix as Omnix Gateway API
participant User as End User / Device
App->>Omnix: 1. findOrCreateContact (Phone/Email)
Omnix-->>App: Contact Details & contactId
App->>Omnix: 2. requestOtp (contactId + channelType)
Omnix->>User: Sends OTP Code (SMS/Email)
User->>App: Submits Code
App->>Omnix: 3. verifyOtp (contactId + code)
Omnix-->>App: { success: true/false }
Step 1: Match or Create the Contact
Before requesting an OTP, you must obtain a contactId. The findOrCreateContact method checks if the user exists based on their identifiers (phone or email) and returns their system ID.
Request
{
"method": "OmnixGatewayRpc.findOrCreateContact",
"params": {
"subscriptionId": "sub_123456",
"identifiers": {
"phone": "+15551234567"
},
"profile": {
"firstName": "John",
"lastName": "Doe"
}
}
}Response
{
"result": {
"contactId": "con_789012",
"status": "matched"
}
}*For details on contact parsing, see the Contact Schema.*
Step 2: Request the OTP
Initiate the OTP verification. Specify the channelType (sms or email) to determine how the OTP code is dispatched.
Request
{
"method": "OmnixGatewayRpc.requestOtp",
"params": {
"subscriptionId": "sub_123456",
"contactId": "con_789012",
"channelType": "sms"
}
}Response
{
"result": {
"otpSessionId": "otp_abc123xyz",
"expiresAt": "2026-05-30T00:35:00.000Z"
}
}- OTPs remain valid for 5 minutes by default.
- If you request another OTP for the same contact before expiration, it invalidates the previous session.
Step 3: Verify the OTP Code
When the user enters the code received on their device, send it back to the verify endpoint.
Request
{
"method": "OmnixGatewayRpc.verifyOtp",
"params": {
"subscriptionId": "sub_123456",
"contactId": "con_789012",
"code": "847291"
}
}Response (Success)
{
"result": {
"success": true,
"verifiedAt": "2026-05-30T00:31:12.000Z"
}
}Response (Invalid Code)
{
"result": {
"success": false,
"reason": "INVALID_CODE"
}
}Error Handling
| Error Code | Meaning | Recovery Action |
|---|---|---|
CONTACT_NOT_FOUND |
contactId does not exist. |
Re-run Step 1 to create the contact. |
OTP_EXPIRED |
Code was verified after expiresAt. |
Prompt the user to request a new OTP. |
MAX_ATTEMPTS_EXCEEDED |
User entered incorrect codes too many times. | Lock the session. Force requesting a new OTP. |
Related Reference
- OmnixGatewayRpc — Complete method signatures.
- Error Handling — General error responses.
- Contact Schema — Details on profile formatting.