
# Crea un'applicazione

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

Crea un'applicazione (un client OAuth/OIDC) nell'ambiente della chiave che effettua la chiamata. `key`, `name`, `app_type` e `party` sono obbligatori; ogni altro campo riceve un valore predefinito sicuro derivato dal tipo di applicazione. La risposta contiene un `ETag` che invii come `If-Match` quando aggiorni o elimini. Questa operazione non crea un client secret; i secret e le chiavi si gestiscono tramite gli endpoint delle credenziali dell'applicazione.

## Richiesta

**Body** (`application/json`). I campi sconosciuti vengono rifiutati. Solo `key`, `name`, `app_type` e `party` sono obbligatori.

| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
| `key` | string | sì | Chiave di configurazione stabile, `^[a-z0-9_-]{1,64}$`, unica per ambiente. Obbligatoria in creazione; non può essere modificata in seguito. |
| `name` | string | sì | Nome visualizzato, da 1 a 100 caratteri. |
| `app_type` | string | sì | `web`, `spa`, `native`, `m2m`, `device` o `management`. Obbligatorio in creazione; non può essere modificato in seguito. |
| `party` | string | sì | `first_party` o `third_party`. Obbligatorio in creazione; può passare solo da `first_party` a `third_party`. |
| `owner_org_id` | string o null | no | ID `org_…` dell'organizzazione proprietaria; solo per applicazioni `m2m`; non modificabile. |
| `status` | string | no | `active` o `suspended`. Un'applicazione sospesa non può ottenere nuovi token. |
| `allowed_web_origins` | string[] | no | Origini CORS consentite (`https://host[:port]`), massimo 20, senza wildcard. |
| `organization_usage` | string | no | `deny`, `allow` o `require`. Regola il parametro di autorizzazione `organization` (un ID `org_…` o lo slug dell'organizzazione): `deny` lo rifiuta, `allow` lo rende facoltativo, `require` lo rende obbligatorio. Il token contiene `org_id` solo dopo che l'appartenenza dell'utente è stata verificata. |
| `org_access_mode` | string | no | Accesso con organizzazione: `all_organizations` (predefinito; ogni membro di ogni organizzazione), `enabled_organizations` (solo organizzazioni in cui l'applicazione è abilitata) o `assigned_only` (inoltre solo appartenenze assegnate o gruppi di directory). Vedi [applicazioni dell'organizzazione](../organization-applications/get.md). |
| `registration_mode` | string o null | no | `open`, `invite_only` o `closed`; vuoto eredita l'impostazione dell'ambiente. |
| `registration_source` | string | no | `dashboard` o `management_api` in creazione (predefinito `management_api`); non modificabile. Le risposte possono mostrare anche `dcr` o `cimd`. |
| `verification_status` | string | no | `verified` o `unverified`. |
| `security_profile` | string | no | `baseline` (oggi l'unico profilo scrivibile). |
| `token_endpoint_auth_method` | string | no | `private_key_jwt`, `client_secret_basic`, `client_secret_post` o `none`; deve essere consentito per il `app_type`. |
| `grant_types` | string[] | no | Grant type consentiti; un sottoinsieme di quelli permessi dal `app_type`. |
| `default_api_id` | string o null | no | ID `api_…` dell'API usata quando una richiesta non ha `resource`. |
| `require_par` | boolean | no | Richiede le richieste di autorizzazione pushed. |
| `require_state` | boolean | no | Richiede `state`. |
| `require_nonce` | boolean | no | Richiede `nonce`. |
| `pkce_required` | boolean | no | Richiede PKCE; può essere disattivato solo per un'applicazione web confidential. Senza PKCE, `nonce` è l'unica difesa contro l'iniezione del codice di autorizzazione, quindi `require_nonce` deve restare attivo fuori dagli ambienti di sviluppo (altrimenti `validation_failed` su `/require_nonce`). |
| `skip_consent` | boolean | no | Salta la schermata di consenso; solo applicazioni first-party. |
| `token_binding_policy` | string | no | `none` o `dpop_required`. |
| `login_host` | string o null | no | Uno degli host di login dell'ambiente (nome DNS in minuscolo). |
| `default_max_age_s` | integer o null | no | `max_age` predefinito in secondi. |
| `min_acr` | string o null | no | Livello minimo di garanzia dell'autenticazione: `urn:idp:acr:1fa`, `urn:idp:acr:mfa` o `urn:idp:acr:phr`. |
| `access_token_lifetime_s` | integer o null | no | Durata dell'access token, da 60 a 86400 secondi. |
| `refresh_idle_s` | integer o null | no | Durata di inattività del refresh token in secondi; non superiore a `refresh_absolute_s`. |
| `refresh_absolute_s` | integer o null | no | Durata assoluta del refresh token in secondi. |
| `refresh_reuse_interval_s` | integer | no | Finestra di riutilizzo del refresh token, da 0 a 30 secondi (predefinito 5). |
| `backchannel_logout_uri` | string o null | no | URI di logout back-channel (`https`). |
| `frontchannel_logout_uri` | string o null | no | URI di logout front-channel (`https`). |
| `frontchannel_logout_session_required` | boolean | no | Aggiunge `iss` e `sid` all'URI di logout front-channel. Impostarlo a `true` mentre l'impostazione di logout front-channel dell'ambiente è disattivata restituisce 422. Predefinito `false`. |
| `initiate_login_uri` | string | no | URI di avvio del login OIDC (OpenID Connect Core 1.0 §4): dopo un accesso SAML avviato dall'IdP, il browser viene inviato qui con `iss`, e l'applicazione avvia il proprio flusso con codice di autorizzazione con `state` e PKCE. URL `https` assoluto con host DNS in minuscolo, senza fragment o informazioni utente, massimo 2048 byte; non consentito per applicazioni `m2m` e `management`. Solo un'applicazione con questo URI può essere destinazione avviata dall'IdP. |
| `id_token_org_claims` | boolean | no | Se `true` (predefinito), l'ID token di un accesso con organizzazione contiene `org_id`, `org_slug` e `org_roles`; se `false`, l'ID token non contiene claim dell'organizzazione. Gli access token non sono interessati, e gli ID token non contengono mai autorizzazioni. |
| `policy_uri` | string o null | no | URI della privacy policy (`https`), mostrato nella schermata di consenso. |
| `tos_uri` | string o null | no | URI dei termini di servizio (`https`). |
| `client_uri` | string o null | no | URI della home page dell'applicazione (`https`). |
| `jwks` | object o null | no | JWK Set inline (`{"keys":[…]}`): da 1 a 5 chiavi pubbliche, massimo 16 KiB; i membri di chiave privata vengono rifiutati. Si esclude a vicenda con `jwks_uri`. |
| `jwks_uri` | string o null | no | URI di un JWK Set remoto (`https`); si esclude a vicenda con `jwks`. |
| `software_id` | string o null | no | Solo per applicazioni DCR. |
| `software_version` | string o null | no | Solo per applicazioni DCR. |
| `m2m_token_lifetime_s` | integer o null | no | Durata del token per applicazioni `m2m`, da 60 a 86400 secondi. |
| `redirect_uris` | string[] | no | URI di redirect consentiti, massimo 50; deve essere vuoto per `m2m` e `management`. |
| `post_logout_redirect_uris` | string[] | no | URI di redirect post-logout consentiti, massimo 50. |
| `connection_ids` | string[] | no | Connessioni abilitate sull'applicazione (`conn_…`), ordinate; l'ordine è l'ordine dei pulsanti. Massimo 100. |
| `allowed_first_factors` | string[] | no | Primi fattori consentiti sull'applicazione: valori tra `password`, `passkey`, `email_otp`, `magic_link`, `sms_otp`, `social`, `enterprise`, senza duplicati; restituiti in questo ordine. Un elenco vuoto (predefinito) indica che l'applicazione non aggiunge restrizioni. L'insieme viene intersecato con `allowed_first_factors` dell'ambiente; se non resta alcun metodo, `422 policy_conflict`. |
| `allowed_response_modes` | string[] | no | I valori `response_mode` che l'applicazione può usare nelle richieste di autorizzazione e nelle richieste di autorizzazione pushed: `query`, `form_post` (uno o entrambi, senza duplicati); restituiti in questo ordine. Predefinito `["query"]`: un'applicazione che riceve la risposta di autorizzazione tramite form post aggiunge esplicitamente `form_post`. Una richiesta di autorizzazione il cui `response_mode` non è nell'elenco viene rifiutata; una richiesta senza `response_mode` usa `query`. Un elenco vuoto restituisce 422. Le modalità JARM (`jwt`, `query.jwt`, `fragment.jwt`, `form_post.jwt`) non sono ancora supportate. Le applicazioni registrate tramite dynamic client registration o un documento di metadati del client ID ricevono `["query"]`. |

## Risposta

`201 Created` con l'applicazione e un header `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"
}
```

## Errori

| HTTP | `code` | Quando |
|---|---|---|
| 401 | `unauthenticated` | La chiave manca, non è valida o è stata revocata. |
| 403 | `insufficient_permissions` | La chiave non ha l'autorizzazione richiesta. |
| 409 | `conflict` | Esiste già un'applicazione con questo `key`. |
| 422 | `validation_failed` | Un campo non è valido; `errors[].pointer` lo indica (per esempio `/redirect_uris/0`). |
| 422 | `policy_conflict` | `allowed_first_factors` non ha metodi in comune con l'insieme di primi fattori dell'ambiente. |
| 400 | `unknown_field` | Il body contiene un campo che non fa parte dello schema. |
| 403 | `quota_exceeded` | È stato raggiunto il limite del piano per le applicazioni. |

## Esempio

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

## Campi della risposta

`id` e `client_id` sono l'ID dell'applicazione (`app_…`); `version` viene restituito anche come `ETag`; `created_at`, `updated_at`, `last_token_issued_at` e `last_token_asn` sono in sola lettura. Vengono restituiti tutti i campi scrivibili sopra. I client secret non fanno mai parte di questa risorsa.
