Compliance

SEBI 2FA Trading App India 2026: Developer API Guide

Learn how to comply with the sebi 2fa trading app india 2026 rules. A technical guide on daily session resets, static IP binding, and secure SMS OTP fallback.

StartMessaging Team
SEBI 2FA Trading App India 2026: Developer API Guide

Kabir sat back in his chair at 8:45 AM, staring at the telemetry dashboard for FinHedge, a Bengaluru-based copy-trading and algo-execution platform. The Indian market open was exactly 30 minutes away, but the logs were already turning amber. A series of connection failures and session expirations had locked out active users connecting to Zerodha Kite Connect, Upstox API, and Angel One SmartAPI. On April 1, 2026, the updated SEBI algorithmic trading guidelines officially went active, changing how developer platforms interface with broker APIs. The days of logging in once, saving a long-lived OAuth session token, and running automated orders for weeks are over. Every developer platform must implement daily session resets and multi-factor logins. For Kabir’s team, a minor API configuration slip resulted in hundreds of rejected connection attempts. This guide details how to implement the sebi 2fa trading app india 2026 requirements, handling the technical architecture of daily resets, static IP whitelisting, and fallback options.


What SEBI’s April 2026 2FA Mandate Requires

The regulatory backbone of this change is SEBI Circular SEBI/HO/MIRSD/MIRSD-PoD/P/2025/0000013, which went into effect on April 1, 2026. The regulator designed this framework to control retail participation in automated trading and secure demat accounts. Previously, developers could log in once, save a session token, and let their algo run indefinitely. Under the sebi mandatory 2fa india april 2026 rules, this is a compliance violation. The framework requires two-factor authentication (2FA) for every login session. The first factor must be a standard credential like a username and password or MPIN. The second factor must run on a distinct channel, such as an SMS OTP, TOTP via authenticator apps, or biometric validation. OAuth-based login flows that previously bypassed multi-factor validation on active developer keys are no longer compliant.

Another critical piece is the daily session reset requirement. Every active API session must be invalidated before the next trading day’s pre-open session (which starts at 9:00 AM IST). Sessions cannot carry over from the previous day. This means that if a trader runs a script that executes orders at 9:15 AM, their script must trigger the 2FA flow every single morning. For developer teams, this creates an operational challenge. You cannot hardcode a session token or rely on long-lived cookies. Instead, you must design an automated login sequence that handles the daily 2FA challenge reliably. This affects every developer building a custom algo strategy, fintech platforms running portfolio rebalancing engines, copy-trading networks, and retail brokers providing API interfaces.

SEBI Rule RequirementWhat It Means for Algo Trading App Developers
Mandatory 2FAEvery login session must verify two distinct factors. Single-factor token storage is forbidden.
Distinct ChannelsFactor 1 (Password/MPIN) and Factor 2 (SMS OTP, TOTP, or Biometric) must be independent.
Daily Session ExpirySessions must end before 9:00 AM IST next day. Refresh tokens cannot bypass this reset.
Static IP WhitelistingAPI traffic must originate from registered, static IP addresses bound to the trader’s profile.
Tamper-Evident LogsMaintain 5 years of logs tracking IP, session duration, and 2FA authentication status.

The transition has clean-cut boundaries. Standard client-side SDKs provided by Zerodha Kite Connect, Upstox, and Angel One have rewritten their authorization routes to enforce these daily sessions. If your backend script attempts to submit an order using a session token generated yesterday, the broker’s API returns a 401 Unauthorized or 403 Forbidden response.


Does SMS OTP Satisfy SEBI’s 2FA Requirement?

Yes, SMS OTP satisfies the mandate, but only under specific compliance conditions. SEBI requires the second factor to be from a distinct category—meaning a physical possession factor (“something the user has”). An SMS OTP sent to the client’s KYC-registered mobile number qualifies because it proves possession of the registered SIM card. However, sending the OTP to a secondary phone number or an unverified email address is a compliance violation. The broker and the client application must ensure the message is dispatched strictly to the mobile number registered in the broker’s KYC profile.

This daily reset frequency alters the operational economics of using SMS OTP. In a typical consumer app, users authenticate once and stay logged in for months. But with a daily reset requirement on a trading app, each active trader generates approximately 250 SMS OTPs per year (one for each trading day). If your copy-trading platform has 1,000 active traders, your backend will send roughly 2.5 lakh SMS OTPs annually. At standard Indian SMS rates of ₹0.25 per OTP, this amounts to a significant recurring operational cost.

To optimize these costs and improve the user experience, Time-based One-Time Passwords (TOTP) should be positioned as the primary authentication factor for daily users, while using SMS OTP as the fallback. Authenticator apps (like Google Authenticator or Microsoft Authenticator) run offline, have zero per-verification cost, and avoid delivery latencies. The best practice is to offer TOTP as the primary route, with sebi oauth 2fa sms fallback india integration for users who lose access to their authenticator app, change their device, or fail to complete the TOTP challenge.

+-----------------------------------------------------------+
|                  Static IP Verification                   |
+-----------------------------------------------------------+
                             |
                             v
+-----------------------------------------------------------+
|              First Factor: Username + Password            |
+-----------------------------------------------------------+
                             |
                             v
+-----------------------------------------------------------+
|           Is TOTP Enrolled for this account?              |
+-----------------------------------------------------------+
              /                               \
             / (Yes)                           \ (No)
            v                                   v
+-----------------------+           +-----------------------+
|  Request TOTP Code    |           |  Trigger SMS OTP via  |
|  (Google/MS Auth)     |           |  StartMessaging API   |
+-----------------------+           +-----------------------+
            \                                   /
             \                                 /
              v                               v
+-----------------------------------------------------------+
|        Verify & Issue Session JWT (Expires 3:45 AM)       |
+-----------------------------------------------------------+

Integrating a multi-factor login flow requires an understanding of how DLT registration in India affects delivery. For SMS OTPs, carriers scrub messages based on approved templates registered on DLT portals. Choosing a provider that handles these DLT hurdles dynamically is critical. StartMessaging offers DLT-free OTP delivery by routing traffic through pre-approved transactional headers, removing the two-week setup bottleneck for your startup.


Implementation Architecture: 2FA Login Flow for Broker API Platforms

Let’s translate these compliance rules into a concrete backend architecture. We will build a Node.js/Express implementation that handles static IP binding, checks for TOTP enrollment, generates secure OTPs using crypto.randomInt, stores them in Redis with a 5-minute TTL, and enforces daily resets using a cron job.

Static IP binding is a separate SEBI requirement: all API requests must originate from static, whitelisted IP addresses. This check must occur before the 2FA challenge is triggered. If an incoming login request originates from an unwhitelisted IP address, the request should be rejected at the firewall or middleware layer immediately, preventing credential probing and unnecessary SMS OTP expenses.

1. The Core Login and Authentication Flow

Here is the Express application structure. It implements static IP checks, determines the 2FA channel, manages Redis-backed OTP challenges, and interacts with the StartMessaging API to dispatch fallback SMS messages.

// server.js
import express from 'express';
import crypto from 'node:crypto';
import { createClient } from 'redis';
import speakeasy from 'speakeasy';

const app = express();
app.use(express.json());

const redisClient = createClient({ url: process.env.REDIS_URL || 'redis://localhost:6379' });
await redisClient.connect();

const OTP_TTL_SECONDS = 300;
const IP_WHITELIST = new Set(['203.0.113.50', '127.0.0.1']);

function enforceStaticIP(req, res, next) {
  const clientIp = req.headers['x-forwarded-for'] || req.socket.remoteAddress;
  if (!IP_WHITELIST.has(clientIp)) {
    return res.status(403).json({ success: false, error: 'Access Denied: Unwhitelisted IP.' });
  }
  next();
}

app.post('/api/auth/login', enforceStaticIP, async (req, res) => {
  const { username, password } = req.body;
  const user = {
    id: 'usr_98437',
    username: 'kabir_options',
    phoneNumber: '+919876543210',
    totpSecret: 'NBSWY3DPEB3W64TBNQ',
    isTotpEnrolled: false
  };

  if (username !== user.username) {
    return res.status(401).json({ success: false, error: 'Invalid credentials.' });
  }

  if (user.isTotpEnrolled && user.totpSecret) {
    return res.status(200).json({ success: true, step: '2FA_CHALLENGE', method: 'TOTP', userId: user.id });
  }

  const otpCode = crypto.randomInt(100000, 999999).toString();
  const redisKey = `trading-2fa:${user.id}`;
  await redisClient.hSet(redisKey, { code: otpCode, attempts: '0' });
  await redisClient.expire(redisKey, OTP_TTL_SECONDS);

  try {
    const response = await fetch('https://api.startmessaging.com/otp/send', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json', 'X-API-Key': process.env.STARTMESSAGING_API_KEY },
      body: JSON.stringify({ phoneNumber: user.phoneNumber, variables: { otp: otpCode } })
    });
    const result = await response.json();
    if (!response.ok || !result.success) throw new Error('API dispatch error');

    return res.status(200).json({
      success: true,
      step: '2FA_CHALLENGE',
      method: 'SMS_OTP',
      userId: user.id,
      otpRequestId: result.data.otpRequestId,
      message: `OTP sent to KYC number ending in ${user.phoneNumber.slice(-4)}`
    });
  } catch (error) {
    return res.status(500).json({ success: false, error: 'OTP delivery failed.' });
  }
});

2. OTP Verification and JWT Expiration Math

Once the user inputs the 6-digit challenge value, the backend verifies it against the stored value. Upon verification, the backend issues an API session token. To satisfy SEBI’s strict daily logout rules, we configure the session token’s expiration to fall before the next day’s pre-open window.

The standard daily reset limit is set to 3:45 AM IST of the following day, which falls after the post-market wrap-up and before the next morning’s pre-open at 9:00 AM IST.

app.post('/api/auth/verify', enforceStaticIP, async (req, res) => {
  const { userId, code, method } = req.body;
  const user = { id: 'usr_98437', totpSecret: 'NBSWY3DPEB3W64TBNQ' };

  if (method === 'TOTP') {
    const verified = speakeasy.totp.verify({
      secret: user.totpSecret,
      encoding: 'base32',
      token: code,
      window: 1
    });
    if (!verified) return res.status(400).json({ success: false, error: 'Invalid TOTP.' });
  } else if (method === 'SMS_OTP') {
    const redisKey = `trading-2fa:${userId}`;
    const storedState = await redisClient.hGetAll(redisKey);
    if (!storedState || !storedState.code) {
      return res.status(400).json({ success: false, error: 'OTP expired.' });
    }

    const attempts = parseInt(storedState.attempts, 10);
    if (attempts >= 3) {
      await redisClient.del(redisKey);
      return res.status(403).json({ success: false, error: 'Account locked.' });
    }

    if (storedState.code !== code) {
      await redisClient.hIncrBy(redisKey, 'attempts', 1);
      return res.status(400).json({ success: false, error: 'Invalid OTP.' });
    }
    await redisClient.del(redisKey);
  }

  const sessionToken = crypto.randomUUID();
  const sessionExpiry = getNextResetTimestamp();
  const sessionKey = `active-session:${userId}`;

  await redisClient.hSet(sessionKey, { token: sessionToken, expiresAt: sessionExpiry.toISOString() });
  const secondsToExpiry = Math.max(1, Math.floor((sessionExpiry.getTime() - Date.now()) / 1000));
  await redisClient.expire(sessionKey, secondsToExpiry);

  return res.status(200).json({ success: true, sessionToken, expiresAt: sessionExpiry.toISOString() });
});

function getNextResetTimestamp() {
  const now = new Date();
  const istOffset = 5.5 * 60 * 60 * 1000;
  const nowIst = new Date(now.getTime() + istOffset);
  const resetIst = new Date(nowIst);
  resetIst.setUTCHours(3, 45, 0, 0);

  if (nowIst.getTime() >= resetIst.getTime()) {
    resetIst.setUTCDate(resetIst.getUTCDate() + 1);
  }
  return new Date(resetIst.getTime() - istOffset);
}

3. Automated Daily Session Resets (Cron Engine)

A scheduled background process runs to clear active sessions in the database before the market pre-open. This ensures that any stale tokens are removed from the database even if the cache keys fail to auto-expire.

// sessionPruningCron.js
import cron from 'node-cron';
import { createClient } from 'redis';

const redisClient = createClient({ url: process.env.REDIS_URL || 'redis://localhost:6379' });
await redisClient.connect();

cron.schedule('0 3 * * *', async () => {
  try {
    let cursor = 0;
    do {
      const reply = await redisClient.scan(cursor, { MATCH: 'active-session:*', COUNT: 100 });
      cursor = reply.cursor;
      if (reply.keys.length > 0) await redisClient.del(reply.keys);
    } while (cursor !== 0);
  } catch (error) {
    console.error('Session pruning failed:', error);
  }
}, { scheduled: true, timezone: 'Asia/Kolkata' });

OTP Delivery for Trading: Why Speed Matters

In generic e-commerce applications, a 30-second delay in receiving an OTP is a minor usability friction. For algorithmic trading apps, a 30-second delay is a financial risk.

Between 9:00 AM and 9:15 AM IST, traders scramble to log into their terminals to audit open positions, adjust margins, and prepare order books before the market opens. During this 15-minute window, millions of verification requests are processed simultaneously.

Under this heavy network load, standard “grey routes” (which route messages through international routing paths to cut costs) suffer from latency spikes of 30 to 60 seconds. A delay of this length can prevent a trader from entering a critical option trade during the opening minute, resulting in substantial financial losses.

This environment makes Tier-1 direct route OTP delivery—with a p50 latency of under 5 seconds—an operational requirement for trading applications.

Grey Route Latency:
[Login Attempt] -> [International Transit] -> [Carrier Queue Spike] -> [OTP Arrives: 45s Delay]

Direct Route Latency (StartMessaging):
[Login Attempt] -> [Direct Telecom Link] -> [Instant Handset Push] -> [OTP Arrives: 3s Delay]

To address this time-sensitive environment, developer teams should adjust the standard login retry UX:

  • Reduce OTP Cooldowns: Lower the “Resend OTP” cooldown from 30 seconds to 15 seconds. Traders are time-sensitive and are likely to contact support if they are forced to wait on an unresponsive verification screen during market open.
  • Provide Visual Feedback: Display a countdown timer in the UI to manage user expectations.
  • Encourage TOTP Onboarding: Position TOTP as the primary login method for daily active traders. Since TOTP is generated locally, it operates offline, eliminating telecom network delivery delays.
  • Implement a Reliable Fallback: Use a direct-route SMS API as the primary fallback option to ensure delivery if the user’s authenticator app is inaccessible.

Audit Trails: What SEBI Requires You to Log

SEBI audits are thorough, and examiners pay close attention to authentication logs. Under SEBI’s compliance guidelines, you must maintain an audit trail of every login event, session creation, and verification attempt for a minimum of 5 years. Each log entry must capture:

  • The unique user/trader ID
  • A precise timestamp in Indian Standard Time (IST)
  • The type of 2FA method used (SMS OTP, TOTP, or Biometric)
  • The status of the attempt (Success, Failure, Lockout)
  • The static IP address from which the request originated
  • The unique transaction/session token issued
  • The exact session expiration timestamp

To align with the Digital Personal Data Protection (DPDP) Act, you must hash the user’s phone number in the logs using a secure hashing algorithm like SHA-256 rather than storing it in plaintext. Additionally, you should never log the raw OTP value. Maintain these logs in a tamper-evident, read-only datastore. Gaps in the logs—such as trading days with active orders but no corresponding 2FA event record—will trigger compliance failures during regulatory audits.

Here is an example audit log schema for PostgreSQL to capture these events:

CREATE TABLE authentication_audit_logs (
    id SERIAL PRIMARY KEY,
    trader_id VARCHAR(64) NOT NULL,
    hashed_phone VARCHAR(64) NOT NULL,
    auth_timestamp TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    auth_method VARCHAR(20) CHECK (auth_method IN ('SMS_OTP', 'TOTP', 'BIOMETRIC')),
    request_ip VARCHAR(45) NOT NULL,
    status VARCHAR(20) CHECK (status IN ('SUCCESS', 'FAILED', 'LOCKOUT')),
    session_token_uuid UUID,
    session_expires_at TIMESTAMP WITH TIME ZONE,
    provider_reference VARCHAR(128)
);

CREATE INDEX idx_trader_auth ON authentication_audit_logs(trader_id, auth_timestamp);
CREATE INDEX idx_provider_ref ON authentication_audit_logs(provider_reference);

When storing user data, keep this audit database separate from your operational user-profile database. In the event of a SEBI audit, you can export these records directly to demonstrate 2FA enforcement on all active API keys during the audit window.


Frequently Asked Questions

Q: Does SEBI’s 2FA requirement apply to all retail traders or only algo traders?

A: The 2FA mandate applies to all retail trading logins and API access keys, including automated algo-trading bots. If you access a broker’s API to execute orders—whether manually or through an automated script—you must complete the 2FA challenge on every login session.

Q: Does SMS OTP satisfy SEBI’s two-factor authentication requirement?

A: Yes. An SMS OTP sent to the client’s KYC-registered mobile number qualifies as a second-factor possession element. However, sending the OTP to a secondary phone number or an unverified email address is not compliant.

Q: How often does a trader need to complete 2FA on a broker API?

A: A trader must complete the 2FA login challenge once per trading session. SEBI requires all broker session keys to be invalidated before the next trading day’s pre-open session (9:00 AM IST). Sessions cannot carry over, requiring a fresh login challenge each trading day.

Q: Can I use TOTP (Google Authenticator) instead of SMS OTP for SEBI compliance?

A: Yes. TOTP is an approved second-factor authentication method. It is often preferred for daily active traders as it functions offline, has zero per-verification cost, and avoids SMS delivery delays.

Q: What happens if a trader doesn’t receive their OTP at market open?

A: A delayed OTP can lock traders out of the market during critical trading windows. To mitigate this risk, trading platforms should implement a direct-route SMS API fallback, reduce the resend cooldown window to 15 seconds, and encourage the use of TOTP as the primary option.

Q: How long must I retain 2FA audit logs under SEBI rules?

A: You must retain authentication logs and audit trails for a minimum of 5 years (some brokers mandate 8 years). Gaps in these logs during an audit can result in compliance penalties.


By integrating a dual-factor architecture that supports both TOTP and SMS OTP fallback, Kabir and his team resolved the connection issues on FinHedge. They achieved a 99.8% session verification success rate, even during high-volatility market opens. If you are building automated trading tools on Zerodha, Upstox, or Angel One, reliable OTP delivery is essential for compliance. Register for a StartMessaging account to access direct-route SMS delivery in India for ₹0.25 per OTP.

S

StartMessaging Team

StartMessaging Team

Related posts