
# Actualizar un permiso

`PATCH /v1/permissions/{permission_id}` · permiso `apis:write`

Actualiza un permiso con un JSON merge patch (RFC 7396, `application/merge-patch+json`): los campos que envíe cambian, los demás se mantienen. Los permisos no tienen versión, así que no hay `If-Match`.

## Solicitud

| Parámetro | En | Descripción |
|---|---|---|
| `permission_id` | path | Id del permiso (`perm_…`). |

Cuerpo: cualquiera de los campos siguientes (todos opcionales, al menos uno).

| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
| `value` | cadena | no | Se acepta solo si es igual al valor actual; nunca cambia. |
| `display_name` | cadena \| null | no | Nombre corto que se muestra en la pantalla de consentimiento en lugar del valor del scope. Como máximo 128 caracteres. |
| `description` | cadena \| null | no | Línea de detalle que se muestra debajo del nombre en la pantalla de consentimiento. Como máximo 1024 caracteres. |
| `consent_text_i18n` | objeto \| null | no | Etiqueta de idioma → texto de la pantalla de consentimiento, por ejemplo `{"en": "Read your orders"}`. Como máximo 30 idiomas, cada texto de 1 a 1024 caracteres, 16 KiB en total. |
| `sensitivity` | cadena | no | `normal` (predeterminado) o `sensitive`. |

`display_name`, `description` y `consent_text_i18n` se borran con `null`; `sensitivity` no puede borrarse. `consent_text_i18n` se reemplaza por completo: los idiomas que omita se eliminan, así que envíe todos los idiomas que desee conservar.

### Textos de la pantalla de consentimiento

La pantalla de consentimiento alojada muestra cada scope solicitado así: la entrada de `consent_text_i18n` para el idioma de la página (etiqueta exacta; si no, su subetiqueta principal), si no, `display_name`, si no, el `value` del scope; `description` se muestra como línea de detalle. Los tres son texto plano. Los caracteres de control (incluidos saltos de línea y tabulaciones), los separadores de línea y de párrafo, y los caracteres de incrustación, anulación y aislamiento bidireccional (U+202A-U+202E, U+2066-U+2069) se rechazan con `422`. Los espacios al principio y al final se recortan, y un texto que queda vacío tras el recorte se guarda como `null`. El HTML no se interpreta: la pantalla de consentimiento lo escapa.

## Respuesta

`200 OK`

```json
{
  "id": "perm_01h455vb4pex5vsknk084sn02s",
  "api_id": "api_01h455vb4pex5vsknk084sn02q",
  "value": "read:orders",
  "display_name": "Read orders",
  "description": "See your past orders and their status",
  "consent_text_i18n": {
    "en": "Read your orders",
    "tr": "Siparişlerinizi okuyun"
  },
  "sensitivity": "normal"
}
```

## Errores

| HTTP | código | Cuándo |
|---|---|---|
| 400 | `unknown_field` | El parche contiene `api_id` o un campo desconocido. |
| 404 | `not_found` | No existe tal permiso en este entorno. |
| 409 | `conflict` | El permiso pertenece a la API del sistema. |
| 415 | `unsupported_media_type` | El tipo de contenido no es `application/merge-patch+json`. |
| 422 | `validation_failed` | El parche está vacío, un valor no es válido o no es texto plano, `sensitivity` es `null`, o `value` es distinto (`immutable`). |

## Ejemplo

```bash
curl -X PATCH https://api.eu.keenauth.com/v1/permissions/perm_01h455vb4pex5vsknk084sn02s \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
  -H "Content-Type: application/merge-patch+json" \
  -d '{"description":"See your past orders and their status","consent_text_i18n":{"en":"Read your orders","tr":"Siparişlerinizi okuyun"}}'
```
