
# Massenlöschung von Benutzern als Job anlegen

`POST /v1/jobs/user-deletions` · Berechtigungen `users:delete` und `jobs:write`

Löscht bis zu 10.000 Benutzer in einem asynchronen Job. Jeder Benutzer durchläuft dieselbe Löschung wie bei [`DELETE /v1/users/{user_id}`](/docs/api/management/users/delete): Der Benutzer wird `pending_deletion`, und die endgültige Löschung läuft anschließend; der Löschdatensatz vermerkt, dass er aus einem Massenjob stammt. Eine Löschung kann nicht rückgängig gemacht werden, daher läuft der Endpunkt in zwei Schritten ab:

1. Senden Sie die Anfrage mit `"dry_run": true`. Es wird nichts geschrieben; die Antwort enthält `matched_count`, die Anzahl der Benutzer, die die Anfrage löschen würde.
2. Senden Sie dieselbe Auswahl mit `"confirm_count"` auf diesen Wert gesetzt. Hat sich die Zahl der passenden Benutzer inzwischen geändert, schlägt die Anfrage mit `409 confirmation_mismatch` fehl, und es wird kein Job angelegt; führen Sie dann den Probelauf erneut aus.

Wählen Sie Benutzer auf eine von zwei Arten aus: `user_ids` (wiederholte IDs zählen einmal; die Ergebnisse behalten die Reihenfolge des ersten Auftretens) oder `organization_id` (die aktiven und gesperrten Mitglieder der Organisation zum Zeitpunkt der Job-Anlage). IDs, die keinem Benutzer entsprechen, bleiben im Job erhalten und werden als `not_found` gemeldet.

In einer Umgebung läuft jeweils nur ein Massenlöschjob; während einer läuft, wird ein neuer Job mit `429 rate_limited` und `Retry-After` abgelehnt. Der Job wird beim Anlegen und beim Abschluss in das Verwaltungs-Auditprotokoll geschrieben; jeder gelöschte Benutzer hat außerdem einen eigenen Löschauditeintrag. Verfolgen Sie den Job mit [Massenlöschjob abrufen](/docs/api/management/jobs/get-user-deletion) und lesen Sie die Ergebnisse je Benutzer mit [Ergebnisse der Massenlöschung auflisten](/docs/api/management/jobs/list-user-deletion-results).

## Anfrage

**Header**: `Idempotency-Key` (erforderlich, 16–64 Zeichen `A-Z a-z 0-9 _ -`). Wiederholen Sie die Anfrage mit demselben Schlüssel und demselben Body, wird der erste Job zurückgegeben; derselbe Schlüssel mit einem anderen Body schlägt mit `422 idempotency_key_reuse` fehl. Der Body darf bis zu 512 KiB groß sein.

| Feld | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
| `user_ids` | Array aus Zeichenketten | eines der beiden | Benutzer-IDs mit Präfix `usr_`, 1 bis 10.000. |
| `organization_id` | Zeichenkette | eines der beiden | Organisations-ID mit Präfix `org_`; höchstens 10.000 Mitglieder. |
| `dry_run` | Boolean | nein | `true`: nur Benutzer zählen; es wird nichts geschrieben. Standard `false`. |
| `confirm_count` | Ganzzahl | ja, sofern nicht `dry_run` | Das `matched_count` des Probelaufs (0–10.000). |

## Antwort

Probelauf: `200 OK` mit `{"dry_run": true, "matched_count": n}`.

Job angelegt: `202 Accepted` mit der Anzahl und dem Job.

```json
{
  "dry_run": false,
  "matched_count": 2,
  "job": {
    "id": "job_01h455vb4pex5vsknk084sn02q",
    "status": "running",
    "filter": "user_ids",
    "total": 3,
    "succeeded": 0,
    "not_found": 0,
    "failed": 0,
    "pending": 3,
    "created_at": "2026-01-15T09:30:00Z"
  }
}
```

## Fehler

Jeder Fehler ist ein `application/problem+json`-Body mit einem stabilen `code`.

| HTTP | `code` | Wann |
|---|---|---|
| 400 | `malformed_request`, `unknown_field` | Der Header `Idempotency-Key` fehlt oder ist ungültig, oder der Body ist kein gültiges JSON oder enthält ein unbekanntes Feld. |
| 401 | `unauthenticated` | Der API-Schlüssel fehlt, ist ungültig oder widerrufen. |
| 403 | `insufficient_permissions` | Dem Schlüssel fehlt `users:delete` oder `jobs:write`. |
| 409 | `confirmation_mismatch` | `confirm_count` ist nicht die aktuelle Anzahl passender Benutzer. |
| 409 | `idempotency_in_progress` | Eine Anfrage mit demselben `Idempotency-Key` wird noch verarbeitet. |
| 413 | `payload_too_large` | Der Body ist größer als 512 KiB. |
| 422 | `validation_failed` | Beide oder keines von `user_ids` und `organization_id`, eine fehlerhafte ID, mehr als 10.000 Benutzer (`too_many`, `too_many_users`), eine Organisation ohne Mitglieder (`no_users`) oder ein fehlendes `confirm_count` (`required`). |
| 422 | `idempotency_key_reuse` | Der `Idempotency-Key` wurde mit einem anderen Body verwendet. |
| 429 | `rate_limited` | Ein anderer Massenlöschjob läuft, oder das Ratenlimit wurde überschritten; beachten Sie `Retry-After`. |
| 503 | `service_unavailable` | Eine Abhängigkeit ist vorübergehend nicht verfügbar; versuchen Sie es später erneut. |

## Beispiel

```bash
curl -X POST https://api.eu.keenauth.com/v1/jobs/user-deletions \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"organization_id": "org_01h455vb4pex5vsknk084sn02q", "dry_run": true}'
```

CLI: `keenauth jobs user-deletions create --organization-id org_01h455vb4pex5vsknk084sn02q --dry-run --yes`, danach `keenauth jobs user-deletions create --organization-id org_01h455vb4pex5vsknk084sn02q --confirm-count 42 --yes`. Lange ID-Listen gehören in eine Datei: `--data @users.json`.
