Create a bulk password reset job

POST /v1/jobs/password-resets · permission user-credentials:write

Forces many users to choose a new password in one asynchronous job, for example after a suspected leak or to move users off weak imported hash formats. The response returns the job at once; the users are flagged in the background. Follow the job with Get a bulk password reset job. For a single user use Force a password reset.

Select users in one of two ways (not both):

The connection_id filter is not available yet; a request that sends it is refused with 422 validation_failed (not_supported at /connection_id).

Choose the mode:

Idempotency-Key is required. The same credential, key and request return the same job (with Idempotent-Replayed: true); the same key with a different request is refused with 422 idempotency_key_reuse. An environment can have at most 20 jobs that are not completed; a lazy job stays open until its deadline. The job creation is written to the management audit log (password_reset_job.created) and emits the password_reset.scheduled event.

Request

Field Type Required Description
mode string yes on_login or lazy_then_bulk_reset.
user_ids string[] one of 1–100,000 user ids (usr_…).
hash_algos string[] one of Stored hash algorithms: argon2id, argon2i, bcrypt, scrypt, firebase_scrypt, pbkdf2_sha1, pbkdf2_sha256, pbkdf2_sha512, django_pbkdf2_sha256, django_bcrypt_sha256, phpass, ldap_ssha, ldap_ssha256, sha512_crypt, hmac_sha256, salted_sha256, salted_sha512, md5.
deadline_days integer no lazy_then_bulk_reset only: 1–365, default 30.

Response

202 Accepted with the job.

{
  "id": "job_01h455vb4pex5vsknk084sn02q",
  "mode": "lazy_then_bulk_reset",
  "filter": "hash_algo",
  "hash_algos": ["md5", "phpass"],
  "status": "marking",
  "deadline_at": "2026-02-14T09:30:00Z",
  "total": 0,
  "marked": 0,
  "not_found": 0,
  "passwords_deleted": 0,
  "emailed": 0,
  "created_at": "2026-01-15T09:30:00Z"
}

Errors

Every error is an application/problem+json body with a stable code.

HTTP code When
400 malformed_request, unknown_field The Idempotency-Key header is missing or malformed, the body is not valid JSON, or it has an unknown field.
401 unauthenticated The API key is missing, invalid or revoked.
403 insufficient_permissions The key lacks the user-credentials:write permission.
409 conflict The environment already has 20 jobs that are not completed.
413 payload_too_large The body is larger than 4 MiB.
422 validation_failed A field is missing or invalid; errors[].pointer names it.
422 idempotency_key_reuse The Idempotency-Key was used with a different request.
429 rate_limited The rate limit was exceeded; honor Retry-After.
503 service_unavailable A dependency is temporarily unavailable; retry later.

Example

curl -X POST https://api.eu.keenauth.com/v1/jobs/password-resets \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"mode": "lazy_then_bulk_reset", "hash_algos": ["md5", "phpass"], "deadline_days": 30}'

CLI: keenauth jobs password-resets create --mode lazy_then_bulk_reset --hash-algos md5,phpass --deadline-days 30 --yes