Kite Connect authentication errors: invalid app code and incorrect api_key or access_token
Kite Connect authentication errors fall into two layers that are often confused: the human Kite login, where “Invalid app code” means the second-factor code failed, and the Kite Connect API , where “Incorrect api_key or access_token” means a programmatic session is invalid or expired. The first is almost always a device-clock problem on the time-based login code; the second is almost always the daily 6 a.m. expiry of a Kite Connect access token, returned to your program as an HTTP 403 with a TokenException. They look similar because both involve a token and both block access, but they sit at different layers and have different fixes.
The distinction matters because the wrong mental model wastes time. A trader who reads “Invalid app code” as a password problem keeps retyping a code that was never wrong; a developer who reads “Incorrect api_key or access_token” as a bad key keeps re-checking a key that is correct, when the real issue is an expired token that the login flow refreshes daily. This article takes each error in its own section: the exact message, the layer it lives on, the technical cause, and the precise fix. It draws the line between the in-app login code documented in Kite app code and the API credentials documented in how to generate a Kite Connect API key .
Conflict-of-interest disclosure. This guide is published by the WebNotes Editorial Team for informational purposes and is written independently. WebNotes operates a Zerodha account-opening referral programme, disclosed on the pages that carry the referral link; this guide does not carry it and earns no referral commission from the procedure described here.
“Invalid app code” on Kite login
The message is “Invalid App Code”. It appears on the Kite login second-factor screen, after you have entered your user ID and password and Kite asks for your app code , the six-digit code shown in the Kite mobile app or in your external authenticator.
Why it appears, even when the code is right
The app code is a time-based one-time password (TOTP). A TOTP is computed from two inputs: a secret shared once between Zerodha’s server and your device, and the current time rounded to a 30-second window. Both ends compute the same six-digit number independently and compare them. Because time is an input, the codes only match when both clocks agree. If your phone’s clock, or the clock on the device you are logging in from, has drifted by more than a window, the code your app generates lands in a different time slot from the one Zerodha’s server is checking, and the server rejects it as invalid.
So the headline cause is counter-intuitive: the “Invalid app code” error usually appears even when you have typed the correct code, because the failure is a clock mismatch rather than a wrong code. Zerodha states this directly: authentication may fail if the time on your devices is out of sync, and the code can be correct yet still rejected. Retyping the code does not help, because the next code is computed from the same drifted clock.
How to fix it
The fix is to make both clocks accurate by switching them to network-provided automatic time, then retry. Zerodha’s documented steps by platform:
- On Android: Settings, Date and time, then turn on “Network provided time”.
- On iPhone: Settings, General, Date and Time, then turn on “Set Automatically”.
- On Windows: Settings, Time and Language, turn on “Set the time automatically”, then click “Sync now”.
Apply this on both the device that generates the code, your phone, and the device you are logging in from, because a drift on either side breaks the match. After both clocks are on automatic, the next app code your app shows will line up with the server’s window and the login goes through.
Two follow-ups. If you would rather not depend on the Kite app’s in-built code at all, set up an external authenticator (Authy, Google Authenticator, Microsoft Authenticator, Bitwarden, Ente Auth) from the Kite login page; once external TOTP is enabled, Kite asks for the authenticator’s code instead of the in-app app code, and the same clock rule still applies. If you have lost the device entirely and cannot read any code, you reset the second factor through Zerodha’s recovery flow rather than fighting the error; see how to reset 2FA on Zerodha .
This error is a Kite login error, seen by a person in a browser. It has nothing to do with the Kite Connect API key. A developer whose program fails to authenticate is hitting the next error, not this one.
“Incorrect api_key or access_token” on the Kite Connect API
The API returns this as “Orders couldn’t be loaded. Incorrect ‘api_key’ or ‘access token’.” in the Kite client, and as a TokenException in the raw API response. It is a programmatic error: your code, or a third-party app you authorised, called a Kite Connect endpoint with credentials the server would not accept.
What the API actually returns
Kite Connect signals an invalid or expired session with HTTP status 403, accompanied by a TokenException. Zerodha’s developer documentation describes TokenException as preceded by a 403 header and indicating the expiry or invalidation of an authenticated session, triggered by the user logging out, a natural expiry, or the user logging in to another Kite instance. The documented recommended action is to clear the user’s session and re-initiate a login. So when a program reports “Incorrect api_key or access_token”, the underlying signal is a 403 TokenException, and the right response is to re-authenticate, not to keep retrying the same call.
The api_key half of the message is rarely the real problem once an app is set up, because the api_key is a fixed public identifier that does not change between sessions. The access_token half is almost always the real problem, because the access token is short-lived by design.
Why the access token expires daily
A Kite Connect access token is not permanent. Unless you invalidate it earlier through the logout API or a master logout on Kite web, it expires at 6 a.m. on the next day, a regulatory requirement Zerodha implements on every Kite Connect session. The practical consequence is that an automated system which obtained a token yesterday will get a 403 TokenException on its first call after 6 a.m. today, because the token it is holding has lapsed. This is the single most common cause of the error in a working integration: nothing is wrong with the key or the code; the token simply aged out at the daily reset.
There is no silent renewal that keeps a running script alive across the 6 a.m. boundary on its own. The session has to be re-established by running the login flow again, which produces a fresh access token valid until the next 6 a.m.
The request-token-to-access-token exchange
Re-establishing a session uses the OAuth-style flow that every Kite Connect integration runs. The steps:
- Send the user to the Kite login page with your
api_key. The user enters their Zerodha credentials and second factor. - After a successful login, Zerodha redirects to your registered redirect URL with a
request_tokenas a query parameter. This request token is short-lived, valid only for a few minutes, and must be exchanged at once. - Your app computes a
checksum, which is the SHA-256 hash ofapi_key + request_token + api_secretconcatenated in that order. - Your app POSTs
api_key,request_tokenandchecksumto the session token endpoint. Zerodha verifies the checksum, which proves your app holds the privateapi_secretwithout that secret ever travelling over the wire, and returns the full user profile along with theaccess_token. - Your app uses that access token on every subsequent call, in the header
Authorization: token api_key:access_token, until the 6 a.m. reset.
The checksum step is where a mismatched api_secret shows up. If your app signs with a stale secret, because someone regenerated the api_secret in the developer console and invalidated the old one, the checksum will not verify and the exchange fails. Regenerating the api_secret immediately invalidates every active session that used the old secret, so a regeneration is a second, less frequent cause of the error: not an expired token, but a secret your code no longer matches. For the full credential-creation flow, see how to generate a Kite Connect API key
, and for the token exchange in code, how to generate the request_token and access_token
.
The fixes, in order of likelihood
- Re-run the login flow to obtain a fresh access token. This clears the daily 6 a.m. expiry, the most common cause, and is the documented response to a 403 TokenException. Automated systems should schedule a daily login that completes before the first call of the trading day; see how to automate Kite Connect TOTP .
- Confirm the api_secret your code signs with matches the current secret in the developer console. If anyone regenerated it, every old session breaks; update your stored secret and re-authenticate.
- Confirm the Kite Connect subscription is active. If the Rs 2,000 per month subscription lapses, API calls fail with the same 403 token error; renew it from the console. See how to renew a Kite Connect subscription .
- Confirm you are not invalidating your own session by logging in to Kite elsewhere. A second login to another Kite instance can expire the API session, exactly as the documentation lists, so check for a stray login or another app holding the token.
Telling the two errors apart
The clean separation: “Invalid app code” is a Kite login second-factor failure that a human sees in a browser, fixed by syncing device clocks. “Incorrect api_key or access_token” is a Kite Connect API failure that a program receives as a 403 TokenException, fixed by re-authenticating to get a fresh daily access token.
They share the word “token” and both block access, which is why they get confused, but they live on different layers. The app code authenticates a person into Kite. The access token authenticates a program into the Kite Connect API. A developer building an automated system meets both: the app code (or external TOTP) gates the login step that yields the request token, and the access token gates every API call after that. The login flow at Kite Connect OAuth login flow shows how the two connect, where a second-factor success produces the request token that the checksum step turns into the access token.
See also
- Zerodha
- Kite by Zerodha
- Kite Connect API
- Kite app code
- How to generate a Kite Connect API key
- Kite Connect API key
- How to generate the request_token and access_token
- Kite Connect OAuth login flow
- How to automate Kite Connect TOTP
- How to place an order via the Kite Connect REST API
- How to renew a Kite Connect subscription
- Kite Connect ecosystem
- Kite app code vs TOTP vs SMS OTP
- How to reset 2FA on Zerodha
- How to recover your Kite password
- How to recover your Kite user ID
- Zerodha 12-character user ID format
- How to secure your trading account
- Zerodha cyber-security
- Kite chart errors
- Kite order quantity and value limits
- Kite web
- Kite mobile app
- Zerodha Console
- SEBI
External references
- Zerodha support: Why is an “Invalid App Code” error displayed on Kite?
- Zerodha support: What is an App Code and why is it displayed on the Kite app?
- Kite Connect docs: Exceptions and error handling
- Kite Connect docs: User and session (login flow, checksum, access_token)
- Z-Connect by Zerodha: Two factor authentication (2FA)
References
- Zerodha support, “Why is an ‘Invalid App Code’ error displayed on Kite?” (as of 21 June 2026).
- Kite Connect developer documentation, “Exceptions and error handling” (TokenException, HTTP 403), kite.trade/docs/connect/v3/exceptions/ (as of 21 June 2026).
- Kite Connect developer documentation, “User and session” (request_token exchange, checksum as SHA-256 of api_key + request_token + api_secret, access_token expiry at 6 a.m. next day), kite.trade/docs/connect/v3/user/ (as of 21 June 2026).
- SEBI circular SEBI/HO/MIRSD/DOP/CIR/P/2018/147, dated 3 December 2018, on two-factor authentication for login to online trading accounts.