`POST /users/{id}/password-resets` — admin-initiated password reset.
/users/{id}/password-resetsTargets a single user identified by (auth.org_id, path id),
kills their existing Cognito password with a random plaintext
the admin never sees, and emails a fresh setup link so the user
can pick a new one. Different from
POST /account/forgot-password in two ways:
- The admin is the actor; the target user might not know it
happened until they read the email. We therefore use a
distinct email copy (
SetupFlow::AdminPasswordReset) that tells the user their old password is dead, not "you can ignore this and keep using your old one." - The endpoint is admin-only and not anti-enumeration: the
admin can already enumerate their own org's users via
GET /users, so opaque error responses would add nothing.
Returns:
200 { userId, sentTo, resetAt }on success.400if the target is a federated or app user (federated → "use your IdP"; service → "no password").403if the caller is not an admin.404if the target user doesn't exist in the caller's org.500if the org row, Cognito pool, or signing key are missing — these are operator-visible misconfigs, not user errors.
Path Parameters
Target user id
Response Body
application/json
curl -X POST "https://example.com/users/string/password-resets"{ "reset_at": "string", "sent_to": "string", "user_id": "string"}`POST /users/{id}/mfa-resets` — admin recovery for a native user who lost their second factor (`rh-kk6vbu`). Authz and target rules are `/users/{id}/password-resets`': admin only, 404 outside the caller's org, 400 for a federated or app target. POST
Turns the user's TOTP off in Cognito and marks the row `mfa_reset_pending`. From that moment a passkey sign-in is refused; the user's next password sign-in deletes their passkeys and security keys (Cognito has no admin API for that) and asks them to set a factor up again.
`POST /account/forgot-password`. Unauthenticated. Always returns 202 — the response shape is identical whether the email matches a real user, matches a federated user, or matches nothing. Anti-enumeration is the whole point: callers learn nothing from the response except "we accepted your request". POST
When the email matches a non-federated user, we generate a fresh setup token (the same machinery signup and invitation use) and email the user a `<slug>.<apex>/set-password#<token>` link. Since rh-j4af1x the user's row is **not** touched: this request proves nothing about who sent it, and `POST /account/passwords` accepts the token on the token row rather than on the user's status. Federated users (`provisioned_by.is_some()`) never get a token — their credentials live in their IdP, not in Cognito. Auditing distinguishes every outcome (`sent` / `skipped_federated` / `skipped_unknown` / …) so operators can spot enumeration attempts.