Phone Management
Flow Summary
The current phone module has two flows:
Set Phone Flow
Step 1. Send OTPPOST /api/v1/auth/set-phone/otp
Step 2. Verify and savePOST /api/v1/auth/set-phone/verification
Replace Phone Flow
Step 1. Send OTP (current)POST /api/v1/auth/reset-phone/current-phone/otp
Step 2. Verify (current)POST /api/v1/auth/reset-phone/current-phone/verification
Step 3. Send OTP (new)POST /api/v1/auth/reset-phone/new-phone/otp
Step 4. Verify (new)POST /api/v1/auth/reset-phone/new-phone/verification
In development environments, OTP is currently hardcoded to 123456.
All routes below should be treated as protected routes and sent with:
Authorization: Bearer <access_token>
Set Phone (For Users Without A Verified Phone)
Use this when the user registered without a verified phone, or has a stored phone that is still unverified.
1. Send OTP
POST /api/v1/auth/set-phone/otp
Request
{
"phone_code": "855",
"country_code": "KH",
"phone_number": "012345678"
}
Success response
{
"status_code": 200,
"message": "OTP sent successfully",
"data": {
"set_phone_session_id": "9b7f1b4d-7c75-4d14-bec8-0d03b0f809d6",
"expires_at": 300
}
}
Current rules
- If the user already has a stored phone value, the submitted phone must match that stored phone exactly after normalization.
- If the user has no phone yet, the service validates the phone format and checks that the phone number is not already used by another user.
- The OTP session is stored in Redis for 5 minutes.
- The response reuses the phone-reset OTP message key.
2. Verify OTP And Save Phone
POST /api/v1/auth/set-phone/verification
Request
{
"set_phone_session_id": "9b7f1b4d-7c75-4d14-bec8-0d03b0f809d6",
"otp_code": "123456"
}
Success response
{
"status_code": 200,
"message": "Phone number updated successfully",
"data": {
"success": true,
"message": "Phone number set and verified successfully."
}
}
Notes
- The OTP session purpose must be
set_phone. - On success, the service updates
phone,phone_code,country_code, and setsis_phone_verified = true. - The OTP session is deleted after a successful verification.
Reset Phone (Replace An Existing Verified Phone)
This is a 4-step flow.
1. Send OTP To Current Phone
POST /api/v1/auth/reset-phone/current-phone/otp
Request
{
"phone_code": "855",
"country_code": "KH",
"phone_number": "012345678"
}
Success response
{
"status_code": 200,
"message": "Phone reset initiated successfully",
"data": {
"current_phone_session_id": "f2b4a8f8-0f5f-4a8d-9b20-8f2a1f4f34c2",
"phone": "85512345678",
"expires_at": 300
}
}
Notes
phone_codeandphone_numberare required.country_codeis optional here.- The submitted current phone must match the logged-in user’s registered phone.
- The service rate-limits this step to once per minute per user. If hit, it returns a failure payload with
retry_after. - The OTP session is stored in Redis for 5 minutes.
2. Verify Current Phone OTP
POST /api/v1/auth/reset-phone/current-phone/verification
Request
{
"current_phone_session_id": "f2b4a8f8-0f5f-4a8d-9b20-8f2a1f4f34c2",
"otp_code": "123456"
}
Success response
{
"status_code": 200,
"message": "Current phone verified successfully",
"data": {
"success": true,
"message": "Current phone verified successfully. You can now proceed to change phone number.",
"new_phone_session_id": "12dc8cb8-cdf5-4f1a-b5ec-c0fd7184bfe2"
}
}
Notes
- This consumes the OTP session from step 1.
- The service creates a
new_phone_session_idthat unlocks step 3. - That intermediate reset session is stored in Redis for 10 minutes.
3. Send OTP To New Phone
POST /api/v1/auth/reset-phone/new-phone/otp
Request
{
"phone_code": "855",
"country_code": "KH",
"new_phone_number": "098765432",
"new_phone_session_id": "12dc8cb8-cdf5-4f1a-b5ec-c0fd7184bfe2"
}
Success response
{
"status_code": 200,
"message": "OTP sent successfully",
"data": {
"new_phone_session_id": "12dc8cb8-cdf5-4f1a-b5ec-c0fd7184bfe2",
"expires_at": 300
}
}
Notes
country_codeis required on this step.- The
new_phone_session_idmust come from step 2 and must belong to the current user. - The new phone number is validated and must not already exist.
- The OTP for the new phone uses the same
new_phone_session_idvalue as the OTP session UUID. - Resending is limited to once per minute for the same
new_phone_session_id. When blocked, the response includesretry_after.
4. Verify New Phone OTP And Update
POST /api/v1/auth/reset-phone/new-phone/verification
Request
{
"new_phone_session_id": "12dc8cb8-cdf5-4f1a-b5ec-c0fd7184bfe2",
"otp_code": "123456"
}
Success response
{
"status_code": 200,
"message": "OTP verified successfully",
"data": {
"success": true,
"message": "Phone number updated successfully."
}
}
Notes
- The OTP session purpose must be
reset_phone. - If the user has a
cardholder_id, the service updates the cardholder phone on UQPay before saving the local phone. - The service updates
phoneandphone_codein the local database, then deletes the OTP session.
Common Failure Cases
400: invalid phone format, invalid OTP, expired session, or wrong session purpose403: resend requested too quickly, or reset session does not belong to the current user404: user not found409: new phone number already exists
Integration Notes
- Use
set-phoneonly for users who still need to verify or attach a phone. - Use
reset-phonewhen replacing an already registered phone. - The OTP steps here are route-specific and do not use
/connect/token.