Skip to content

V2 API Reference

piekstra edited this page Feb 7, 2026 · 1 revision

V2 API Reference

This documents the TP-Link Kasa Cloud API v2, reverse-engineered from the Kasa Android app v3.4.451 (decompiled February 2026).

Overview

TP-Link migrated from a V1 API to a V2 API for authentication. Key differences:

Aspect V1 (Legacy) V2 (Current)
Base URL https://wap.tplinkcloud.com https://n-wap.tplinkcloud.com
Auth endpoint POST / with {"method":"login","params":{...}} POST /api/v2/account/login with flat body
appType Kasa_Android Kasa_Android_Mix
Request signing None HMAC-SHA1 on every request
URL query params token only appName, appVer, termID, ospf, brand, locale, + token
MFA/2FA Not supported Full support
Refresh tokens Not supported Supported
SSL Standard certs TP-Link private CA chain
Device operations V1 format on / Same V1 format on /, but with signing + query params

Authentication Flow

Step 1: Regional URL Discovery

Before logging in, discover the regional server for the user's account.

Endpoint: POST https://n-wap.tplinkcloud.com/api/v2/account/getAccountStatusAndUrl

Body:

{
  "appType": "Kasa_Android_Mix",
  "cloudUserName": "user@example.com"
}

Response:

{
  "error_code": 0,
  "result": {
    "accountApiUrl": "https://use1-account-api.i.tplinkcloud.com",
    "serviceRegion": "us-east-1",
    "appServerUrl": "https://n-use1-wap.tplinkcloud.com",
    "appServerUrlV2": "https://n-use1-wap.i.tplinkcloud.com",
    "status": 1
  }
}

Use appServerUrl for subsequent requests. The status field indicates account state (1 = active).

Step 2: Login

Endpoint: POST {appServerUrl}/api/v2/account/login

Body (flat JSON, no wrapper):

{
  "appType": "Kasa_Android_Mix",
  "appVersion": "3.4.451",
  "cloudPassword": "your_password",
  "cloudUserName": "user@example.com",
  "platform": "Android",
  "refreshTokenNeeded": true,
  "supportBindAccount": false,
  "terminalUUID": "uuid-v4-string",
  "terminalName": "MyDevice",
  "terminalMeta": "MyDevice"
}

Successful Response:

{
  "error_code": 0,
  "result": {
    "token": "xxxxxxxx-xxxxxxxxxxxxxxxxxxxx",
    "refreshToken": "xxxxxxxx-xxxxxxxxxxxxxxxxxxxx",
    "accountId": "1234567",
    "email": "user@example.com",
    "regionCode": "US",
    "supportedMFATypes": [],
    "appServerUrl": "https://n-use1-wap.tplinkcloud.com",
    "appServerUrlV2": "https://n-use1-wap.i.tplinkcloud.com"
  }
}

MFA Required Response (error -20677):

{
  "error_code": -20677,
  "result": {
    "mfaProcessId": "process-id-string",
    "supportedMFATypes": ["email"],
    "accountId": "1234567"
  }
}

See MFA Authentication Flow for handling this case.

Step 3: Device Operations

Device listing and passthrough commands still use the V1 JSON format, but on the V2 infrastructure with signing and query params.

Get Device List:

POST {appServerUrl}/?token={token}&appName=Kasa_Android_Mix&appVer=3.4.451&...

Body:
{
  "method": "getDeviceList",
  "params": {}
}

Passthrough (control a device):

POST {appServerUrl}/?token={token}&appName=Kasa_Android_Mix&appVer=3.4.451&...

Body:
{
  "method": "passthrough",
  "params": {
    "deviceId": "DEVICE_ID_HERE",
    "requestData": "{\"system\":{\"set_relay_state\":{\"state\":1}}}"
  }
}

Note: requestData is a JSON string, not a nested object.

URL Query Parameters

All requests require these query parameters (added by the Retrofit interceptor C29914q in the Android app):

Parameter Value Required
appName Kasa_Android_Mix Always
appVer 3.4.451 Always
netType wifi Always
termID UUID v4 string Always
ospf Android 14 Always
brand TPLINK Always
locale en_US Always
model Device model string Optional
termName Terminal name Optional
termMeta Terminal metadata Optional
token Auth token When authenticated

Request Signing

See HMAC Request Signing for full details.

Error Codes

Code Meaning
0 Success
-20104 Parameter doesn't exist (missing required field)
-20571 Invalid request or signature
-20651 Token expired (use refresh token)
-20655 Refresh token expired (re-login required)
-20677 MFA required
-23003 App version too old

V2 Account Endpoints

All under {appServerUrl}/api/v2/account/:

Endpoint Description Auth Required
getAccountStatusAndUrl Regional URL discovery No
login Login with credentials No
logout Invalidate token Yes
getAccountInfo Get account details Yes
checkMFACodeAndLogin Complete MFA login No
getEmailVC4TerminalMFA Request email MFA code No
getPushVC4TerminalMFA Request push MFA notification No
register Create new account No
getRegVeriCode Get registration verification code No
checkRegVeriCode Verify registration code No
resetCloudPassword Reset password No
modifyCloudPassword Change password Yes
getCountryCallingCodes Get country codes list No
checkPassword Validate password No

SSL/TLS

The V2 servers (n-wap.tplinkcloud.com, n-use1-wap.tplinkcloud.com) use TP-Link's private CA chain:

Root: tp-link-CA (self-signed)
  └── Intermediate: TP-LINK CA P1
        └── Leaf: *.tplinkcloud.com

Standard SSL verification will fail. Options:

  1. Bundle the CA chain and pass it to your HTTP client
  2. Use appServerUrlV2 (e.g., n-use1-wap.i.tplinkcloud.com) which uses public certs
  3. Disable SSL verification (not recommended for production)

The CA chain can be extracted from the server:

openssl s_client -showcerts -connect n-wap.tplinkcloud.com:443 < /dev/null 2>/dev/null | \
  awk '/BEGIN CERT/,/END CERT/{print}'

Clone this wiki locally