
# Creare un job di reimpostazione della password in blocco

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

Obbliga molti utenti a scegliere una nuova password in un unico job asincrono, per esempio dopo una sospetta fuga di dati o per spostare gli utenti da formati di hash importati e deboli. La risposta restituisce subito il job; gli utenti vengono contrassegnati in background. Seguire il job con [Ottenere un job di reimpostazione della password in blocco](/docs/api/management/jobs/get-password-reset). Per un singolo utente usare [Forzare una reimpostazione della password](/docs/api/management/users/force-password-reset).

Selezionare gli utenti in uno dei due modi (non entrambi):

- `user_ids`: fino a 100.000 ID utente; gli ID ripetuti contano una volta. Gli ID che non sono utenti di questo ambiente, e gli utenti senza password, sono contati come `not_found`.
- `hash_algos`: ogni utente la cui password è memorizzata con uno di questi algoritmi e che l'ha cambiata per l'ultima volta prima della creazione del job (per esempio `["md5", "phpass"]`). Una password impostata dopo la creazione del job non viene selezionata.

Il filtro `connection_id` non è ancora disponibile; una richiesta che lo invia viene rifiutata con `422 validation_failed` (`not_supported` su `/connection_id`).

Scegliere il `mode`:

- `on_login`: ogni utente selezionato deve impostare una nuova password dopo il suo prossimo accesso riuscito con password.
- `lazy_then_bulk_reset`: lo stesso, fino alla scadenza (`deadline_days`, da 1 a 365, predefinito 30). Alla scadenza, l'hash della password di ogni utente selezionato che non ha ancora cambiato password viene eliminato e viene inviata un'e-mail di reimpostazione all'indirizzo e-mail principale verificato (gli utenti senza uno possono comunque richiedere una reimpostazione da soli). `deadline_days` è accettato solo in questa modalità.

`Idempotency-Key` è obbligatoria. Stessa credenziale, stessa chiave e stessa richiesta restituiscono lo stesso job (con `Idempotent-Replayed: true`); la stessa chiave con una richiesta diversa viene rifiutata con `422 idempotency_key_reuse`. Un ambiente può avere al massimo 20 job non completati; un job lazy resta aperto fino alla sua scadenza. La creazione del job viene scritta nel log di audit di gestione (`password_reset_job.created`) e genera l'evento `password_reset.scheduled`.

## Richiesta

| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
| `mode` | string | sì | `on_login` oppure `lazy_then_bulk_reset`. |
| `user_ids` | string[] | uno dei due | Da 1 a 100.000 ID utente (`usr_…`). |
| `hash_algos` | string[] | uno dei due | Algoritmi di hash memorizzati: `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 | Solo `lazy_then_bulk_reset`: da 1 a 365, predefinito 30. |

## Risposta

`202 Accepted` con il job.

```json
{
  "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"
}
```

## Errori

Ogni errore è un corpo `application/problem+json` con un `code` stabile.

| HTTP | `code` | Quando |
|---|---|---|
| 400 | `malformed_request`, `unknown_field` | L'intestazione `Idempotency-Key` è mancante o non valida, il corpo non è JSON valido oppure ha un campo sconosciuto. |
| 401 | `unauthenticated` | La chiave API è mancante, non valida o revocata. |
| 403 | `insufficient_permissions` | La chiave non ha il permesso `user-credentials:write`. |
| 409 | `conflict` | L'ambiente ha già 20 job non completati. |
| 413 | `payload_too_large` | Il corpo supera 4 MiB. |
| 422 | `validation_failed` | Un campo manca o non è valido; `errors[].pointer` lo indica. |
| 422 | `idempotency_key_reuse` | La `Idempotency-Key` è stata usata con una richiesta diversa. |
| 429 | `rate_limited` | È stato superato il limite di frequenza; rispettare `Retry-After`. |
| 503 | `service_unavailable` | Una dipendenza non è temporaneamente disponibile; riprovare più tardi. |

## Esempio

```bash
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`
