Skip to content

Forgot password flow ​

Branches on whether the entered email belongs to a registered user. Three calls in sequence — request the OTP, confirm the OTP, then set the new password — all brand-authenticated, since the user has no session yet.

Play the flow ​

Both branches — the address is registered, or it is not. Press Play to watch either one; the steps name the three calls that chain through the app.

1 / 8

Space plays and pauses, ← and → step. Screens marked not designed yet are ones the documented flow requires but that have no design — they are drawn from the steps, not invented.

Stages ​

API calls by stage ​

StageActionAPI callAuth
1–2Page loads, email typedNo call—
3Tap Reset PasswordPOST /api/v1/mobile/resetPassword — payload takes exactly one of email / phoneNumber (xor), and phone_prefix is required with a phone numberBrand
3a"Email not registered"Same call. The branch is not a separate endpoint — it is success: false on the response body, at HTTP 200Brand
4–5Submit the OTPPOST /api/v1/mobile/resetPassword/confirm — otp plus exactly one of email / phoneNumber. Returns { message, token }; that token is the passwordToken for stages 6–7Brand
6–7New password + ConfirmPOST /api/v1/mobile/changePassword/:passwordToken — payload.password (min 8)Brand
8SuccessNo call. changePassword is not documented as returning a session, so a landing on the home page needs POST /api/v1/mobile/login afterwardsBrand

The whole reset happens in-app

resetPassword/confirm returns { message, token }, and that token is what goes in changePassword/:passwordToken. No email link, no deep link, no universal-link handling — the three calls chain through the app.

One caution: the token is a full customer JWT, signed with the same config as a login token. Use it as the path parameter and discard it. Storing it would "sign in" someone who never proved a password.

The single-identifier rule ​

resetPassword uses Joi's xor, so sending both email and phoneNumber fails just as surely as sending neither. If the design ever offers "reset by email or SMS" on one screen, the client must send only the chosen one.

Paths ​

Email not registered Login Page → More login options → Email & Password Login Page → Forgot password → Forgot Password Page → enter email → Reset Password button → user not found → "Email not registered" popup

Email registered Login Page → More login options → Email & Password Login Page → Forgot password → Forgot Password Page → enter email → Reset Password button → user found → OTP popup → enter OTP → new password + re-enter password → Confirm → Success

Open questions ​

  • After the "email not registered" popup — does it return to the form, or offer a link to Signup?
  • Where does Success land? Back to the login page, or straight into the home page with a session? If it is the home page, the app has to log in again (see stage 8).
  • OTP wrong / expired handling and resend not defined. resetPassword can be called again to reissue; no retry limit is documented.
  • Revealing whether an email is registered is a user-enumeration signal. Common alternative is a neutral "if this email exists, we've sent a code" message. Worth a deliberate decision rather than a default — and note the decision is server-side: the popup exists because the endpoint distinguishes the two cases in its response.
  • New password vs re-entered password mismatch: no path defined. Client-side only — changePassword takes one password.

Batch platform, Shopify app and API documentation