
# Aggiorna una connessione

`PATCH /v1/connections/{connection_id}` · autorizzazione `connections:write`

Aggiorna una connessione con un merge patch JSON (`application/merge-patch+json`, RFC 7396). `If-Match` è obbligatorio. `key`, `type`, `strategy` e `org_id` non possono essere modificati. Una patch che non cambia nulla non scrive nulla e mantiene la versione. Le impostazioni non devono contenere segreti.

## Richiesta

| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
| `connection_id` | string | sì | Identificatore della connessione (`conn_…`). |
| `If-Match` | header | sì | Il `ETag` della connessione come letto l'ultima volta. Se manca: `428`; se obsoleto: `412`. |
| `key` | string | no | Non può essere modificato; viene accettato lo stesso valore. |
| `type` | string | no | Non può essere modificato. |
| `strategy` | string | no | Non può essere modificato. |
| `name` | string | no | Da 1 a 128 caratteri. |
| `display_name` | string \| null | no | `null` lo cancella. |
| `status` | string | no | `active` o `inactive`. |
| `org_id` | string \| null | no | Non può essere modificato; viene accettato lo stesso valore. |
| `allowed_email_domains` | array di string \| null | no | Sostituisce la lista; `null` o `[]` la cancella. Stesse regole della creazione; su una connessione di organizzazione vengono verificati solo i domini appena aggiunti rispetto ai domini verificati dell'organizzazione. |
| `allow_external_domains` | boolean | no | Solo `enterprise`. |
| `jit_mode` | string | no | `create`, `create_and_update` o `off`. Solo `enterprise`. |
| `email_trust` | boolean | no | Solo `enterprise`. Attivarlo per una connessione di organizzazione richiede un `allowed_email_domains` non vuoto in cui ogni dominio sia un dominio verificato dell'organizzazione. |
| `default_role_ids` | array di string \| null | no | Sostituisce la lista; `null` o `[]` la cancella. Stesse regole della creazione; vengono verificati solo i ruoli appena aggiunti, quindi un ruolo già presente nella lista che è stato eliminato in seguito non blocca l'aggiornamento (viene saltato all'accesso). |
| `trust_idp_mfa` | boolean | no | Solo `enterprise`. |
| `settings` | object \| null | no | Unito ricorsivamente (RFC 7396); un membro `null` elimina quella chiave; `null` cancella tutte le impostazioni. Nessun segreto. |

## Risposta

`200 OK` con la connessione aggiornata e il nuovo `ETag`.

```json
{
  "id": "conn_0k3v8m1q2x9dz4h7s5t6w0y1ab",
  "key": "google",
  "type": "social",
  "strategy": "google",
  "name": "Google",
  "display_name": "Sign in with Google",
  "status": "active",
  "org_id": null,
  "allowed_email_domains": [],
  "allow_external_domains": false,
  "jit_mode": null,
  "email_trust": null,
  "default_role_ids": [],
  "trust_idp_mfa": null,
  "allow_idp_initiated": null,
  "idp_initiated_default_application_id": null,
  "idp_initiated_allowed_application_ids": [],
  "settings": {},
  "created_at": "2026-10-05T09:30:00.123456Z",
  "updated_at": "2026-10-05T09:30:00.123456Z"
}
```

## Impostazioni passkey

Per `type: "passkey"` l'oggetto `settings` accetta solo le chiavi sotto elencate. Qualsiasi altra chiave, un tipo errato o un valore fuori intervallo viene rifiutato con `422 validation_failed` e un `errors[].pointer` come `/settings/max_credentials_per_user`. Il valore `null` indica il default. Gli errori di forma vengono segnalati prima degli errori di piano.

| Chiave | Tipo | Note |
|---|---|---|
| `rp_id` | string | Assente, `null` o vuoto: ogni host di accesso è il proprio rpId. Altrimenti il nome host di un dominio personalizzato `active` dell'ambiente (minuscolo, etichetta A IDNA); qualsiasi altro valore dà `422 validation_failed` (`/settings/rp_id`). Quando l'ambiente ha passkey, modificalo con [Cambia il rpId della passkey](change-rp-id.md). |
| `rp_name` | string | Fino a 128 caratteri. |
| `passkey_first_factor_enabled`, `security_key_second_factor_enabled` | boolean | Default `true`. |
| `user_verification` | string | `preferred` (default) o `required`. |
| `max_credentials_per_user` | integer | Da 1 a 20, default 20; le frazioni vengono rifiutate. |
| `require_device_bound_passkeys` | boolean | Vincolato al piano: `true` richiede Startup. |
| `attestation_required` | boolean | Vincolato al piano: `true` richiede Enterprise. |
| `aaguid_allowlist`, `aaguid_blocklist` | array di stringhe UUID | Al massimo 500 voci uniche ciascuna (gli errori puntano a `/settings/<key>/<index>`). Vincolato al piano: una lista non vuota richiede Enterprise. |
| `related_origins` | array di string | Origini `https://host[:port]`. Vincolato al piano: una lista non vuota richiede Enterprise. |
| `passkey_enrollment_prompt` | string | `off` o `after_login` (default). |

Scrivere un valore non predefinito di una chiave vincolata al piano fallisce con `403 plan_feature_unavailable` e i membri `feature` e `required_plan`. Finché le autorizzazioni del piano non sono disponibili, queste chiavi non possono essere impostate in nessun ambiente; scrivere un valore predefinito (`false`, `[]`, `null`) o rimuovere la chiave è sempre consentito. Quando la funzione è disponibile, ogni voce di `related_origins` deve essere un dominio personalizzato verificato e attivo dell'ambiente, altrimenti la richiesta fallisce con `422 related_origin_not_verified`. Le impostazioni vengono validate dopo l'applicazione della merge patch, solo quando `settings` fa parte della patch.

## Errori

| HTTP | code | Quando |
|---|---|---|
| 400 | `unknown_field` | La patch contiene un campo sconosciuto o di sola lettura. |
| 404 | `not_found` | La connessione non esiste o appartiene a un altro ambiente. |
| 409 | `connection_test_required` | La patch imposta una connessione `enterprise` su `active`, oppure aggiunge un dominio a `allowed_email_domains` di una connessione `active`, senza un test riuscito della configurazione risultante nelle ultime 24 ore (vedi Attiva una connessione); non viene scritto nulla. La rimozione di domini non viene verificata. |
| 409 | `rp_id_change_requires_migration` | La patch modifica `settings.rp_id` di una connessione passkey mentre l'ambiente ha passkey che smetterebbero di funzionare; usa [Cambia il rpId della passkey](change-rp-id.md). Non viene scritto nulla. |
| 412 | `precondition_failed` | `If-Match` non corrisponde alla versione corrente. |
| 415 | `unsupported_media_type` | Il tipo di contenuto non è `application/merge-patch+json`. |
| 422 | `validation_failed` | Un valore non è valido oppure un campo immutabile è stato modificato (`code: immutable`). |
| 422 | `related_origin_not_verified` | Un'origine correlata non è un dominio personalizzato verificato dell'ambiente. |
| 403 | `plan_feature_unavailable` | Il piano non include un'impostazione che hai impostato (membri `feature`, `required_plan`), ad esempio `attestation_required`. |
| 428 | `precondition_required` | L'header `If-Match` manca. |
| 401 | `unauthenticated` | La credenziale manca, non è valida o è stata 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 è temporaneamente disponibile (ad esempio, il controllo della passkey per una modifica di `rp_id` non è potuto essere eseguito, quindi non viene scritto nulla); riprova dopo il periodo indicato in `Retry-After`. |

## Esempio

```bash
curl -X PATCH https://api.eu.keenauth.com/v1/connections/conn_0k3v8m1q2x9dz4h7s5t6w0y1ab \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
  -H "Content-Type: application/merge-patch+json" \
  -H 'If-Match: "1"' \
  -d '{"display_name":"Sign in with Google"}'
```
