
# Reemplazar las asignaciones de atributos de una conexión

`PUT /v1/connections/{connection_id}/attribute-mappings` · permiso `connections:write`

Reemplaza la lista completa de asignaciones de atributos de una conexión empresarial. El orden de las reglas no importa; la respuesta está ordenada por destino. `If-Match` es obligatorio: sin él, la solicitud falla con `428`; si la lista cambió desde su última lectura (o el valor no coincide), la solicitud falla con `412` y no se escribe nada. Enviar la misma lista no escribe nada. El cambio se aplica desde el siguiente inicio de sesión y no invalida la última prueba de conexión superada. La escritura se audita como `connection.attribute_mappings_replaced` (destinos añadidos, eliminados y cambiados); los valores de atributos de los inicios de sesión nunca se escriben en el registro de auditoría.

## Solicitud

| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
| `connection_id` | ruta | sí | ID de la conexión empresarial (`conn_…`). |
| `If-Match` | cabecera | sí | El `ETag` de la última lectura. Si falta: `428`; si está desactualizado: `412`. |
| `attribute_mappings` | array | sí | La lista nueva completa, con 28 reglas como máximo. |
| `attribute_mappings[].target` | string | sí | `email` (obligatorio en cualquier lista), `given_name`, `family_name`, `name`, `locale`, `zoneinfo`, `phone`, `groups` o `user_metadata.<key>` (clave `[a-z0-9_]{1,40}`; no se permiten los nombres de reclamaciones OIDC registrados ni el prefijo `idp_`; 20 claves como máximo). Una regla por destino. Una asignación no puede escribir `app_metadata`. |
| `attribute_mappings[].source_name` | string | sí | De 1 a 512 bytes, sin caracteres de control ni bidireccionales, sin espacios al inicio ni al final. |
| `attribute_mappings[].source_name_format` | string \| null | no | `NameFormat` de SAML (URI absoluta). Un mismo nombre de origen solo puede leerse con un formato. |
| `attribute_mappings[].overwrite` | string | sí | `always`, `if_empty` o `never`. |
| `attribute_mappings[].profile` | string | no | Nombre del perfil predefinido; `generic` si se omite. |

## Respuesta

`200 OK` con la lista guardada (véase [Obtener las asignaciones de atributos](get.md)) y el nuevo `ETag`.

## Errores

| HTTP | código | Cuándo |
|---|---|---|
| 404 | `not_found` | La conexión no existe en este entorno o no es una conexión empresarial. |
| 409 | `conflict` | El protocolo de la conexión no tiene asignaciones de atributos (LDAP). |
| 412 | `precondition_failed` | `If-Match` no coincide con la versión actual, o la lista cambió concurrentemente. |
| 422 | `validation_failed` | Una regla incumple las reglas anteriores. Cada regla incumplida es un elemento de `errors[]` que apunta a `/attribute_mappings/<index>/<field>`, o a `/attribute_mappings` para reglas de lista (`email_required`, `too_many_metadata_keys`). |
| 428 | `precondition_required` | Falta la cabecera `If-Match`. |
| 400 | `unknown_field` | El cuerpo contiene un campo desconocido. |
| 401 | `unauthenticated` | La credencial falta, no es válida o fue revocada. |
| 403 | `insufficient_permissions` | La credencial no tiene el permiso requerido. |
| 429 | `rate_limited` | Se superó el límite de tasa; reintente después del tiempo indicado en `Retry-After`. |
| 503 | `service_unavailable` | Una dependencia no está disponible temporalmente; reintente después del tiempo indicado en `Retry-After`. |

## Ejemplo

```bash
curl -X PUT "https://api.eu.keenauth.com/v1/connections/conn_01j9xp6q0r1s5t7v9w1x3y5z7b/attribute-mappings" \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -H 'If-Match: "6f1c…"' \
  -d '{"attribute_mappings":[{"target":"email","source_name":"email","overwrite":"always"},{"target":"user_metadata.department","source_name":"department","overwrite":"if_empty"}]}'
```

```bash
keenauth connections attribute-mappings put conn_01j9xp6q0r1s5t7v9w1x3y5z7b --data @mappings.json --if-match '"6f1c…"'
```
