Changing your password while signed in
PasswordsStep-up with the current password; all sessions are revoked (including the current one), but the caller's current device stays trusted.
- POST /v1/auth/password/change → password replaced; all sessions revoked; every device trust revoked EXCEPT the caller's current device
- POST /v1/auth/login → re-authenticate (no device challenge on this machine; one appears on any other)
/v1/auth/password/changeauthChange passwordA wrong current password → 401, and NOTHING is revoked. Because all sessions are revoked, your existing access/refresh tokens stop working right after this call — plan the re-login into the UX. The CURRENT device is kept trusted (unlike a reset, scenario 23) — the caller just proved the old password from it; it is resolved from the session BEFORE the sessions are revoked, and if it cannot be identified, all devices are untrusted (fail-closed).
Field guide — what each value means & where it comes from2 fields
Changes the authenticated user's password. The tester/gateway supply Authorization and x-gateway-context automatically; you only provide the two body fields. The current password acts as step-up re-auth, and on success all of the user's sessions are revoked (forcing re-login everywhere). No path/query params or required custom headers (no Idempotency-Key).
currentPasswordbodystringrequiredyou choosenewPasswordbodystringrequiredyou choosePOST https://api.kerja.team/v1/auth/password/changeResponse guide — what comes back & what each value meansno body
Success is 200 OK with the standard { data } envelope, where data is an empty object ({ "data": {} }) — there are no response body properties. The 200 confirms the password was changed; as a side effect the server replaces the password hash, revokes ALL of the user's sessions (forcing re-login everywhere), and audits password_changed. No notable response headers (no Set-Cookie / Cache-Control documented).
/v1/auth/loginpublicLog in (identifier + password)identifier is an email OR an E.164 phone — the shape decides the lookup ({ email } is still accepted as a deprecated alias) — and it is OPTIONAL on a recognised device, where the device_token cookie names the account and the body needs only { password }. Three possible answers: { accessToken, … } (nothing left to prove — auto-captured as the active bearer), { challengeToken, challenge, remaining } (a device and/or MFA hop is pending — continue at scenario 11/12/13), or the legacy { mfaRequired, method, mfaToken } shape when DEVICE_TRUST_ENABLED is off (scenario 12). Gated by the LOGIN policy before the credential is even checked → 403 login_method_disabled (scenario 7).
Field guide — what each value means & where it comes from4 fields
Public, unauthenticated login. No Authorization header; send only the JSON body below. Throttled per credential/IP; response is no-store. The answer is one of three shapes — tokens, a challenge chain, or the legacy MFA challenge — and which one you get is NOT checkable beforehand (there is no pre-login MFA-status endpoint, by anti-enumeration design). Before the credential is examined at all, the active LOGIN policy is checked: if the channel this attempt uses is off, the answer is 403 login_method_disabled for a right and a wrong password alike (which discloses nothing — GET /v1/auth/login-policy publishes the same fact unauthenticated). Read that policy first in scenario 7.
identifierbodystringconditionalyou chooseemailbodystringconditionalyou chooseclientIdbodystringoptionalyou choosepasswordbodystringrequiredyou choosePOST https://api.kerja.team/v1/auth/loginResponse guide — what comes back & what each value means16 fields
200 OK, { data } envelope, Cache-Control: no-store. THREE possible shapes, and the login response itself is the only way to learn which branch applies (there is no pre-login MFA-status endpoint, by anti-enumeration design): (1) tokens — nothing more to prove; (2) a CHALLENGE CHAIN { challengeToken, challenge, remaining } when a device and/or MFA hop is pending, continued at POST /v1/auth/login/challenge/verify; (3) the LEGACY single-hop { mfaRequired, method, phoneHint, mfaToken } when DEVICE_TRUST_ENABLED is off. Only the token branch sets Set-Cookie: refresh_token.
data.accessTokenstringconditionaldata.tokenTypestringconditionalBearer— Send the accessToken as 'Authorization: Bearer <accessToken>'.
data.expiresInnumberconditionaldata.user.idstringconditionaldata.user.emailstringconditionaldata.user.displayNamestringconditionaldata.user.tenantIdstringconditionaldata.challengeTokenstringconditionaldata.challenge.typeenumconditionaldevice_email_code— New browser, email-mode account (LN2) — a code was emailed. Continue at scenario 11.device_phone_otp— New browser, phone-mode account (LN1) — an OTP went out on the account's primary channel.mfa_phone_otp— An enrolled phone-OTP second factor (LE3) — the OTP is sent as the challenge is issued. A recognised device never skips this hop.mfa_totp— An enrolled authenticator app — nothing is sent; the code comes from the app, so no resend applies.
data.challenge.hintstringconditionaldata.challenge.expiresInnumberconditionaldata.remainingnumberconditionaldata.methodenumconditionalphone_otp— Send/resend the OTP with POST /v1/auth/mfa/otp/request, then verify. phone_otp is the method advertised when both are confirmed.totp— Read the code from the authenticator app — there is nothing to send, so skip the otp/request step.
data.phoneHintstringconditionaldata.mfaRequiredbooleanconditionaltrue— MFA challenge pending; proceed to /v1/auth/mfa/verify carrying mfaToken. No access token or refresh cookie issued yet.
data.mfaTokenstringconditional