
# Créer une application

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

Crée une application (un client OAuth/OIDC) dans l'environnement de la clé appelante. `key`, `name`, `app_type` et `party` sont obligatoires ; chaque autre champ reçoit une valeur par défaut sûre dérivée du type d'application. La réponse contient un en-tête `ETag` que vous envoyez comme `If-Match` lors de la mise à jour ou de la suppression. Cette opération ne crée pas de secret client ; les secrets et les clés sont gérés via les points de terminaison d'identifiants de l'application.

## Requête

**Corps** (`application/json`). Les champs inconnus sont rejetés. Seuls `key`, `name`, `app_type` et `party` sont obligatoires.

| Champ | Type | Obligatoire | Description |
|---|---|---|---|
| `key` | string | oui | Clé de configuration stable, `^[a-z0-9_-]{1,64}$`, unique par environnement. Obligatoire à la création ; ne peut pas être modifiée ensuite. |
| `name` | string | oui | Nom d'affichage, 1 à 100 caractères. |
| `app_type` | string | oui | `web`, `spa`, `native`, `m2m`, `device` ou `management`. Obligatoire à la création ; ne peut pas être modifié ensuite. |
| `party` | string | oui | `first_party` ou `third_party`. Obligatoire à la création ; ne peut passer que de `first_party` à `third_party`. |
| `owner_org_id` | string or null | non | Identifiant `org_…` de l'organisation propriétaire ; uniquement pour les applications `m2m` ; ne peut pas être modifié. |
| `status` | string | non | `active` ou `suspended`. Une application suspendue ne peut pas obtenir de nouveaux jetons. |
| `allowed_web_origins` | string[] | non | Origines CORS autorisées (`https://host[:port]`), 20 au maximum, sans caractères génériques. |
| `organization_usage` | string | non | `deny`, `allow` ou `require`. Régit le paramètre d'autorisation `organization` (un identifiant `org_…` ou le slug de l'organisation) : `deny` le refuse, `allow` le rend facultatif, `require` le rend obligatoire. Le jeton ne contient `org_id` qu'après vérification de l'appartenance de l'utilisateur. |
| `org_access_mode` | string | non | Accès à la connexion par organisation : `all_organizations` (par défaut ; chaque membre de chaque organisation), `enabled_organizations` (uniquement les organisations où l'application est activée) ou `assigned_only` (en plus, uniquement les appartenances attribuées ou les groupes d'annuaire). Voir [applications d'organisation](../organization-applications/get.md). |
| `registration_mode` | string or null | non | `open`, `invite_only` ou `closed` ; vide, hérite du paramètre de l'environnement. |
| `registration_source` | string | non | `dashboard` ou `management_api` à la création (par défaut `management_api`) ; ne peut pas être modifié. Les réponses peuvent aussi afficher `dcr` ou `cimd`. |
| `verification_status` | string | non | `verified` ou `unverified`. |
| `security_profile` | string | non | `baseline` (le seul profil modifiable actuellement). |
| `token_endpoint_auth_method` | string | non | `private_key_jwt`, `client_secret_basic`, `client_secret_post` ou `none` ; doit être autorisé pour le `app_type`. |
| `grant_types` | string[] | non | Types de octroi autorisés ; sous-ensemble de ce que le `app_type` permet. |
| `default_api_id` | string or null | non | Identifiant `api_…` de l'API utilisée lorsqu'une requête n'a pas de `resource`. |
| `require_par` | boolean | non | Exige des requêtes d'autorisation poussées (PAR). |
| `require_state` | boolean | non | Exige `state`. |
| `require_nonce` | boolean | non | Exige `nonce`. |
| `pkce_required` | boolean | non | Exige PKCE ; ne peut être désactivé que pour une application web confidentielle. Sans PKCE, `nonce` est la seule défense contre l'injection de code d'autorisation, donc `require_nonce` doit rester activé hors environnements de développement (sinon `validation_failed` sur `/require_nonce`). |
| `skip_consent` | boolean | non | Ignore l'écran de consentement ; applications de première partie uniquement. |
| `token_binding_policy` | string | non | `none` ou `dpop_required`. |
| `login_host` | string or null | non | L'un des hôtes de connexion de l'environnement (nom DNS en minuscules). |
| `default_max_age_s` | integer or null | non | `max_age` par défaut, en secondes. |
| `min_acr` | string or null | non | Niveau minimal d'assurance d'authentification : `urn:idp:acr:1fa`, `urn:idp:acr:mfa` ou `urn:idp:acr:phr`. |
| `access_token_lifetime_s` | integer or null | non | Durée de vie du jeton d'accès, 60 à 86400 secondes. |
| `refresh_idle_s` | integer or null | non | Durée d'inactivité du jeton de rafraîchissement, en secondes ; ne doit pas dépasser `refresh_absolute_s`. |
| `refresh_absolute_s` | integer or null | non | Durée de vie absolue du jeton de rafraîchissement, en secondes. |
| `refresh_reuse_interval_s` | integer | non | Fenêtre de réutilisation du jeton de rafraîchissement, 0 à 30 secondes (par défaut 5). |
| `backchannel_logout_uri` | string or null | non | URI de déconnexion back-channel (`https`). |
| `frontchannel_logout_uri` | string or null | non | URI de déconnexion front-channel (`https`). |
| `frontchannel_logout_session_required` | boolean | non | Ajoute `iss` et `sid` à l'URI de déconnexion front-channel. Le définir à `true` alors que le paramètre de déconnexion front-channel de l'environnement est désactivé renvoie 422. Par défaut `false`. |
| `initiate_login_uri` | string | non | URI d'initiation de connexion OIDC (OpenID Connect Core 1.0 §4) : après une connexion SAML initiée par le IdP, le navigateur y est redirigé avec `iss`, et l'application démarre son propre flux de code d'autorisation avec `state` et PKCE. URL `https` absolue avec un hôte DNS en minuscules, sans fragment ni informations utilisateur, 2048 octets au maximum ; non autorisée pour les applications `m2m` et `management`. Seule une application avec cet URI peut être une cible initiée par le IdP. |
| `id_token_org_claims` | boolean | non | Lorsqu'elle vaut `true` (par défaut), le jeton ID d'une connexion par organisation contient `org_id`, `org_slug` et `org_roles` ; lorsqu'elle vaut `false`, le jeton ID ne contient aucune revendication d'organisation. Les jetons d'accès ne sont pas affectés, et les jetons ID ne contiennent jamais d'autorisations. |
| `policy_uri` | string or null | non | URI de la politique de confidentialité (`https`), affichée sur l'écran de consentement. |
| `tos_uri` | string or null | non | URI des conditions d'utilisation (`https`). |
| `client_uri` | string or null | non | URI de la page d'accueil de l'application (`https`). |
| `jwks` | object or null | non | Ensemble de JWK intégré (`{"keys":[…]}`) : 1 à 5 clés publiques, 16 Kio au maximum ; les membres de clé privée sont rejetés. Mutuellement exclusif avec `jwks_uri`. |
| `jwks_uri` | string or null | non | URI d'un ensemble de JWK distant (`https`) ; mutuellement exclusif avec `jwks`. |
| `software_id` | string or null | non | Applications DCR uniquement. |
| `software_version` | string or null | non | Applications DCR uniquement. |
| `m2m_token_lifetime_s` | integer or null | non | Durée de vie des jetons pour les applications `m2m`, 60 à 86400 secondes. |
| `redirect_uris` | string[] | non | URI de redirection autorisées, 50 au maximum ; doit être vide pour `m2m` et `management`. |
| `post_logout_redirect_uris` | string[] | non | URI de redirection après déconnexion autorisées, 50 au maximum. |
| `connection_ids` | string[] | non | Connexions activées sur l'application (`conn_…`), ordonnées ; l'ordre correspond à l'ordre des boutons. 100 au maximum. |
| `allowed_first_factors` | string[] | non | Premiers facteurs autorisés sur l'application : valeurs parmi `password`, `passkey`, `email_otp`, `magic_link`, `sms_otp`, `social`, `enterprise`, sans doublons ; renvoyés dans cet ordre. Une liste vide (par défaut) signifie que l'application n'ajoute aucune restriction. L'ensemble est intersecté avec les `allowed_first_factors` de l'environnement ; si aucune méthode ne subsiste, `422 policy_conflict`. |
| `allowed_response_modes` | string[] | non | Valeurs de `response_mode` que l'application peut utiliser dans les requêtes d'autorisation et les requêtes d'autorisation poussées : `query`, `form_post` (un ou les deux, sans doublons) ; renvoyées dans cet ordre. Par défaut `["query"]` : une application qui reçoit la réponse d'autorisation par form post ajoute explicitement `form_post`. Une requête d'autorisation dont le `response_mode` ne figure pas dans la liste est rejetée ; une requête sans `response_mode` utilise `query`. Une liste vide renvoie 422. Les modes JARM (`jwt`, `query.jwt`, `fragment.jwt`, `form_post.jwt`) ne sont pas encore pris en charge. Les applications enregistrées par inscription dynamique de client ou par un document de métadonnées d'identifiant client reçoivent `["query"]`. |

## Réponse

`201 Created` avec l'application et un en-tête `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"
}
```

## Erreurs

| HTTP | `code` | Quand |
|---|---|---|
| 401 | `unauthenticated` | La clé est absente, invalide ou révoquée. |
| 403 | `insufficient_permissions` | La clé ne dispose pas de l'autorisation requise. |
| 409 | `conflict` | Une application avec cette `key` existe déjà. |
| 422 | `validation_failed` | Un champ est invalide ; `errors[].pointer` le désigne (par exemple `/redirect_uris/0`). |
| 422 | `policy_conflict` | `allowed_first_factors` ne contient aucune méthode en commun avec l'ensemble des premiers facteurs de l'environnement. |
| 400 | `unknown_field` | Le corps contient un champ qui ne fait pas partie du schéma. |
| 403 | `quota_exceeded` | La limite du forfait pour les applications est atteinte. |

## Exemple

```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"]}'
```

## Champs de la réponse

`id` et `client_id` correspondent à l'identifiant de l'application (`app_…`) ; `version` est également renvoyé comme `ETag` ; `created_at`, `updated_at`, `last_token_issued_at` et `last_token_asn` sont en lecture seule. Chaque champ modifiable ci-dessus est renvoyé. Les secrets client ne font jamais partie de cette ressource.
