
# Crear una aplicación

`POST /v1/applications` · permiso `applications:write`

Crea una aplicación (un cliente OAuth/OIDC) en el entorno de la clave que realiza la llamada. `key`, `name`, `app_type` y `party` son obligatorios; cada uno de los demás campos recibe un valor predeterminado seguro derivado del tipo de aplicación. La respuesta incluye un `ETag` que usted envía como `If-Match` al actualizar o eliminar. Esta operación no crea un secreto de cliente; los secretos y las claves se gestionan a través de los endpoints de credenciales de la aplicación.

## Solicitud

**Cuerpo** (`application/json`). Los campos desconocidos se rechazan. Solo `key`, `name`, `app_type` y `party` son obligatorios.

| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
| `key` | string | sí | Clave de configuración estable, `^[a-z0-9_-]{1,64}$`, única por entorno. Obligatoria al crear; no puede cambiarse después. |
| `name` | string | sí | Nombre para mostrar, de 1 a 100 caracteres. |
| `app_type` | string | sí | `web`, `spa`, `native`, `m2m`, `device` o `management`. Obligatorio al crear; no puede cambiarse después. |
| `party` | string | sí | `first_party` o `third_party`. Obligatorio al crear; solo puede cambiar de `first_party` a `third_party`. |
| `owner_org_id` | string o null | no | Id `org_…` de la organización propietaria; solo para aplicaciones `m2m`; no puede cambiarse. |
| `status` | string | no | `active` o `suspended`. Una aplicación suspendida no puede obtener nuevos tokens. |
| `allowed_web_origins` | string[] | no | Orígenes CORS permitidos (`https://host[:port]`), como máximo 20, sin comodines. |
| `organization_usage` | string | no | `deny`, `allow` o `require`. Regula el parámetro de autorización `organization` (un id `org_…` o el slug de la organización): `deny` lo rechaza, `allow` lo hace opcional y `require` lo hace obligatorio. El token incluye `org_id` solo después de verificar la membresía del usuario. |
| `org_access_mode` | string | no | Acceso de inicio de sesión a organizaciones: `all_organizations` (predeterminado; todos los miembros de todas las organizaciones), `enabled_organizations` (solo organizaciones donde la aplicación está habilitada) o `assigned_only` (además, solo membresías asignadas o grupos de directorio). Consulte [aplicaciones de organización](../organization-applications/get.md). |
| `registration_mode` | string o null | no | `open`, `invite_only` o `closed`; vacío hereda la configuración del entorno. |
| `registration_source` | string | no | `dashboard` o `management_api` al crear (predeterminado `management_api`); no puede cambiarse. Las respuestas también pueden mostrar `dcr` o `cimd`. |
| `verification_status` | string | no | `verified` o `unverified`. |
| `security_profile` | string | no | `baseline` (el único perfil editable actualmente). |
| `token_endpoint_auth_method` | string | no | `private_key_jwt`, `client_secret_basic`, `client_secret_post` o `none`; debe estar permitido para el `app_type`. |
| `grant_types` | string[] | no | Tipos de concesión permitidos; un subconjunto de lo que permite el `app_type`. |
| `default_api_id` | string o null | no | Id `api_…` de la API que se usa cuando una solicitud no tiene `resource`. |
| `require_par` | boolean | no | Exige solicitudes de autorización enviadas por push. |
| `require_state` | boolean | no | Exige `state`. |
| `require_nonce` | boolean | no | Exige `nonce`. |
| `pkce_required` | boolean | no | Exige PKCE; solo puede desactivarse para una aplicación web confidencial. Sin PKCE, `nonce` es la única defensa contra la inyección de código de autorización, por lo que `require_nonce` debe permanecer activado fuera de los entornos de desarrollo (de lo contrario, `validation_failed` en `/require_nonce`). |
| `skip_consent` | boolean | no | Omite la pantalla de consentimiento; solo para aplicaciones de primera parte. |
| `token_binding_policy` | string | no | `none` o `dpop_required`. |
| `login_host` | string o null | no | Uno de los hosts de inicio de sesión del entorno (nombre DNS en minúsculas). |
| `default_max_age_s` | integer o null | no | `max_age` predeterminado en segundos. |
| `min_acr` | string o null | no | Garantía mínima de autenticación: `urn:idp:acr:1fa`, `urn:idp:acr:mfa` o `urn:idp:acr:phr`. |
| `access_token_lifetime_s` | integer o null | no | Duración del token de acceso, de 60 a 86400 segundos. |
| `refresh_idle_s` | integer o null | no | Duración de inactividad del token de actualización en segundos; no puede superar `refresh_absolute_s`. |
| `refresh_absolute_s` | integer o null | no | Duración absoluta del token de actualización en segundos. |
| `refresh_reuse_interval_s` | integer | no | Ventana de reutilización del token de actualización, de 0 a 30 segundos (predeterminado 5). |
| `backchannel_logout_uri` | string o null | no | URI de cierre de sesión por canal de fondo (`https`). |
| `frontchannel_logout_uri` | string o null | no | URI de cierre de sesión por canal frontal (`https`). |
| `frontchannel_logout_session_required` | boolean | no | Añade `iss` y `sid` a la URI de cierre de sesión por canal frontal. Si se establece en `true` mientras la configuración de cierre de sesión por canal frontal del entorno está desactivada, devuelve 422. Predeterminado `false`. |
| `initiate_login_uri` | string | no | URI de inicio de sesión iniciado por OIDC (OpenID Connect Core 1.0 §4): tras un inicio de sesión SAML iniciado por el IdP, el navegador se envía aquí con `iss`, y la aplicación inicia su propio flujo de código de autorización con `state` y PKCE. URL `https` absoluta con host DNS en minúsculas, sin fragmento ni información de usuario, de como máximo 2048 bytes; no permitida para aplicaciones `m2m` y `management`. Solo una aplicación con esta URI puede ser destino iniciado por el IdP. |
| `id_token_org_claims` | boolean | no | Cuando es `true` (predeterminado), el ID token de un inicio de sesión en organización incluye `org_id`, `org_slug` y `org_roles`; cuando es `false`, el ID token no incluye reclamaciones de organización. Los tokens de acceso no se ven afectados, y los ID tokens nunca incluyen permisos. |
| `policy_uri` | string o null | no | URI de la política de privacidad (`https`), mostrada en la pantalla de consentimiento. |
| `tos_uri` | string o null | no | URI de las condiciones del servicio (`https`). |
| `client_uri` | string o null | no | URI de la página principal de la aplicación (`https`). |
| `jwks` | object o null | no | Conjunto de claves JWK en línea (`{"keys":[…]}`): de 1 a 5 claves públicas, como máximo 16 KiB; se rechazan los miembros de clave privada. Mutuamente excluyente con `jwks_uri`. |
| `jwks_uri` | string o null | no | URI remota de conjunto JWK (`https`); mutuamente excluyente con `jwks`. |
| `software_id` | string o null | no | Solo para aplicaciones DCR. |
| `software_version` | string o null | no | Solo para aplicaciones DCR. |
| `m2m_token_lifetime_s` | integer o null | no | Duración del token para aplicaciones `m2m`, de 60 a 86400 segundos. |
| `redirect_uris` | string[] | no | URI de redirección permitidas, como máximo 50; deben estar vacías para `m2m` y `management`. |
| `post_logout_redirect_uris` | string[] | no | URI de redirección posterior al cierre de sesión permitidas, como máximo 50. |
| `connection_ids` | string[] | no | Conexiones habilitadas en la aplicación (`conn_…`), ordenadas; el orden es el orden de los botones. Como máximo 100. |
| `allowed_first_factors` | string[] | no | Primeros factores permitidos en la aplicación: valores de `password`, `passkey`, `email_otp`, `magic_link`, `sms_otp`, `social`, `enterprise`, sin duplicados; se devuelven en este orden. Una lista vacía (predeterminado) significa que la aplicación no añade restricción. El conjunto se intersecta con los `allowed_first_factors` del entorno; si no queda ningún método, `422 policy_conflict`. |
| `allowed_response_modes` | string[] | no | Los valores de `response_mode` que la aplicación puede usar en las solicitudes de autorización y en las solicitudes de autorización enviadas por push: `query`, `form_post` (uno o ambos, sin duplicados); se devuelven en este orden. Predeterminado `["query"]`: una aplicación que recibe la respuesta de autorización mediante form post añade `form_post` explícitamente. Una solicitud de autorización cuyo `response_mode` no esté en la lista se rechaza; una solicitud sin `response_mode` usa `query`. Una lista vacía devuelve 422. Los modos JARM (`jwt`, `query.jwt`, `fragment.jwt`, `form_post.jwt`) aún no son compatibles. Las aplicaciones registradas mediante registro dinámico de clientes o un documento de metadatos de ID de cliente reciben `["query"]`. |

## Respuesta

`201 Created` con la aplicación y un encabezado `ETag`.

```json
{
  "id": "app_6f8d0cjgbmf0gtn2rg6pscp3cg",
  "client_id": "app_6f8d0cjgbmf0gtn2rg6pscp3cg",
  "version": 1,
  "created_at": "2026-10-05T10:00:01Z",
  "updated_at": "2026-10-05T10:00:01Z",
  "key": "portal",
  "name": "Portal",
  "app_type": "web",
  "party": "first_party",
  "status": "active",
  "redirect_uris": ["https://portal.example.com/cb"],
  "...": "all other fields from the field reference"
}
```

## Errores

| HTTP | `code` | Cuándo |
|---|---|---|
| 401 | `unauthenticated` | La clave falta, no es válida o ha sido revocada. |
| 403 | `insufficient_permissions` | La clave no tiene el permiso requerido. |
| 409 | `conflict` | Ya existe una aplicación con esta `key`. |
| 422 | `validation_failed` | Un campo no es válido; `errors[].pointer` lo indica (por ejemplo `/redirect_uris/0`). |
| 422 | `policy_conflict` | `allowed_first_factors` no tiene ningún método en común con el conjunto de primeros factores del entorno. |
| 400 | `unknown_field` | El cuerpo tiene un campo que no forma parte del esquema. |
| 403 | `quota_exceeded` | Se ha alcanzado el límite del plan para aplicaciones. |

## Ejemplo

```bash
curl -X POST https://api.eu.keenauth.com/v1/applications \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"key":"portal","name":"Portal","app_type":"web","party":"first_party","redirect_uris":["https://portal.example.com/cb"]}'
```

## Campos de la respuesta

`id` y `client_id` son el id de la aplicación (`app_…`); `version` también se devuelve como `ETag`; `created_at`, `updated_at`, `last_token_issued_at` y `last_token_asn` son de solo lectura. Se devuelve cada campo editable indicado arriba. Los secretos de cliente nunca forman parte de este recurso.
