All checks were successful
Auto Tag on Version Change / check-version (push) Successful in 3s
3.9 KiB
3.9 KiB
OTP / 2FA Verification
Submit a TOTP code to complete login when two_factor_required was true in the login response.
Endpoint
POST https://fahipay.mv/api/app/otp/
Prerequisites
- Completed the login step and received
two_factor_required: true - The
__Secure-sesssession cookie from the login response must be present - A valid TOTP code from the user's authenticator app
Request
Content-Type: multipart/form-data
Form Fields
| Field | Value | Notes |
|---|---|---|
code |
123456 |
6-digit TOTP code from the user's authenticator app |
channel |
totp |
Always totp |
action |
login |
Always login for the login flow |
grant_type |
auth_id |
Always auth_id |
lang |
en |
Always en |
version |
2.0.0 |
App version string |
platform |
BasedBank |
Client identifier (app in the original Fahipay app) |
device[available] |
true |
Same device fields as login — must match |
device[platform] |
Android |
|
device[uuid] |
a1b2c3d4e5f60718 |
Must be the same UUID used in the login request |
device[model] |
22101320I |
|
device[manufacturer] |
Xiaomi |
|
device[isVirtual] |
false |
|
device[serial] |
unknown |
The
device[uuid]must be identical to the one sent in the login request. The server uses this to tie the OTP challenge to the login attempt.
curl Example
curl --request POST \
--url https://fahipay.mv/api/app/otp/ \
--compressed \
--header 'Cookie: __Secure-sess=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' \
--header 'accept: application/json' \
--header 'accept-encoding: gzip, deflate, br' \
--header 'connection: keep-alive' \
--header 'user-agent: Mozilla/5.0 (Linux; Android 14; 22101320I Build/AP2A.240905.003; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/129.0.6668.70 Mobile Safari/537.36' \
--form 'code=123456' \
--form 'channel=totp' \
--form 'action=login' \
--form 'grant_type=auth_id' \
--form 'lang=en' \
--form 'version=2.0.0' \
--form 'platform=BasedBank' \
--form 'device[available]=true' \
--form 'device[platform]=Android' \
--form 'device[uuid]=a1b2c3d4e5f60718' \
--form 'device[model]=22101320I' \
--form 'device[manufacturer]=Xiaomi' \
--form 'device[isVirtual]=false' \
--form 'device[serial]=unknown'
Responses
Success
{
"title": "Success",
"authID": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"msg": "Code verification successful",
"type": "success"
}
| Field | Type | Description |
|---|---|---|
authID |
string |
40-char hex token — use as authid header for all subsequent requests |
type |
string |
"success" |
msg |
string |
Human-readable confirmation |
Failure — Wrong code
{
"title": "Error",
"msg": "Invalid OTP code",
"type": "error"
}
Failure — Expired / session mismatch
{
"title": "Error",
"msg": "Session expired. Please login again.",
"type": "error"
}
If the session cookie has expired or the UUID does not match, re-run the full login flow from Step 1.
TOTP Details
Fahipay uses standard RFC 6238 TOTP:
| Parameter | Value |
|---|---|
| Algorithm | HMAC-SHA1 |
| Period | 30 seconds |
| Digits | 6 |
| Encoding | Base32 secret |
The user's TOTP seed is set up during initial Fahipay account creation and is the same secret used in any standard authenticator app (Google Authenticator, Aegis, etc.).
Storing the Session
After receiving authID, persist both values for future sessions:
| Value | Description |
|---|---|
authID |
40-char hex token — send as authid header |
__Secure-sess |
Cookie value — send as Cookie: __Secure-sess=<value> |
On app restart, attempt requests with the stored session before falling back to a full re-login.