
# Crea o sostituisci una policy dell'organizzazione

`PUT /v1/organizations/{org_id}/policies/{policy_kind}` · autorizzazione `organizations:write`

Sostituisce l'intero oggetto delle impostazioni di un tipo di policy. Una policy dell'organizzazione può essere solo più restrittiva dell'impostazione dell'ambiente. Il controllo del piano è applicato dal server: i tipi `session` e `ip_allowlist` e la allowlist AAGUID richiedono Enterprise (sempre aperti negli ambienti di sviluppo). Il contenuto delle impostazioni viene scritto nel log di audit di gestione; l'evento `organization.updated` non lo include.

## Richiesta

| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
| `org_id` | path | sì | ID dell'organizzazione (`org_…`). |
| `policy_kind` | path | sì | Tipo di policy: `authentication_methods`, `mfa`, `phishing_resistant`, `sso_enforcement`, `session` o `ip_allowlist`. Qualsiasi altro valore restituisce `404`. |
| `If-Match` | header | no | Obbligatorio quando la policy esiste (`ETag` dell'ultima lettura); omettilo per creare la policy. `*` corrisponde a una policy esistente. |
| `settings` | object | sì | L'oggetto delle impostazioni del tipo. Campi per tipo: `authentication_methods`: `allowed_connection_ids` (`conn_…`), `allow_passkey`, `allow_password`; `mfa`: `required_for` (`none`, `admins`, `all`), `allowed_factors` (`totp`, `webauthn`, `sms`, `email`), `enrollment_grace_days` (0-30); `phishing_resistant`: `required_for`, `aaguid_allowlist` (al massimo 500); `sso_enforcement`: `mode` (`off`, `org_context`, `verified_domains`), `connection_ids` (`conn_…`), `bypass_user_ids` (`usr_…`, al massimo 2); `session`: `idle_minutes`, `absolute_minutes`, `refresh_idle_days`, `refresh_absolute_days`; `ip_allowlist`: `cidrs` (al massimo 100), `applies_to` (`admins`, `all`). |

Corpo della richiesta:

```json
{
  "settings": {
    "required_for": "all",
    "allowed_factors": [
      "totp",
      "webauthn"
    ],
    "enrollment_grace_days": 7
  }
}
```

## Risposta

`201 Created` quando la policy è stata creata, `200 OK` quando è stata sostituita; il corpo è la policy e la risposta contiene il suo nuovo `ETag`.

```json
{
  "organization_id": "org_01j9xk3m7q8r2s4t6v8w0y2z4a",
  "policy_kind": "mfa",
  "schema_version": 1,
  "settings": {
    "required_for": "all",
    "allowed_factors": [
      "totp",
      "webauthn"
    ],
    "enrollment_grace_days": 7
  },
  "updated_at": "2026-10-12T09:30:00.123456Z",
  "version": 1
}
```

## Errori

| HTTP | code | Quando |
|---|---|---|
| 400 | `unknown_field` | Il corpo contiene un campo che non è nello schema o è di sola lettura. |
| 403 | `plan_feature_unavailable` | Il tipo o la allowlist AAGUID richiede un piano superiore; il problem contiene `feature` e `required_plan`. |
| 404 | `not_found` | L'organizzazione non esiste oppure il tipo è sconosciuto. |
| 409 | `domain_not_verified` | `sso_enforcement` con `mode` `verified_domains` richiede un dominio verificato sull'organizzazione. |
| 409 | `connection_test_required` | Attivare `sso_enforcement` (da `off` o senza policy) richiede un test di accesso riuscito della configurazione attuale di almeno uno dei `connection_ids` nelle ultime 24 ore. Esegui un test di connessione (`POST /v1/connections/{connection_id}:test`) e riprova. |
| 409 | `organization_pending_deletion` | L'organizzazione è in attesa di eliminazione self-service; annulla prima l'eliminazione. |
| 412 | `precondition_failed` | `If-Match` non corrisponde alla versione attuale, oppure è stato inviato mentre non esiste alcuna policy di questo tipo, oppure un'altra richiesta ha creato la policy mentre questa la stava creando; rileggi la policy. |
| 422 | `validation_failed` | Un campo delle impostazioni è sconosciuto o non valido; `errors[]` punta a `/settings/…`. |
| 422 | `policy_weaker_than_parent` | L'impostazione è più debole di quella dell'ambiente; `errors[]` punta al campo più debole. |
| 422 | `at_least_one_method` | `authentication_methods` non lascia alcun metodo di accesso. |
| 428 | `precondition_required` | `If-Match` manca mentre la policy esiste. |
| 401 | `unauthenticated` | La credenziale è mancante, non valida o revocata. |
| 403 | `insufficient_permissions` | La credenziale non ha l'autorizzazione richiesta. |
| 429 | `rate_limited` | È stato superato il limite di richieste; riprova dopo il periodo indicato in `Retry-After`. |
| 503 | `service_unavailable` | Una dipendenza non è disponibile temporaneamente; riprova dopo il periodo indicato in `Retry-After`. |

## Esempio

```bash
curl -X PUT https://api.eu.keenauth.com/v1/organizations/org_01j9xk3m7q8r2s4t6v8w0y2z4a/policies/mfa \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"settings":{"required_for":"all","allowed_factors":["totp","webauthn"]}}'
```
