Creare un link di Admin Portal
POST /v1/admin-portal-links · permesso admin-portal-links:write
Crea un link che consente all'amministratore IT di una delle tue organizzazioni clienti di configurare SSO, la sincronizzazione della directory, la verifica del dominio e altro ancora nell'Admin Portal ospitato, senza passare dal tuo team di supporto. Genera un link nuovo ogni volta che il tuo amministratore fa clic su «Configura SSO» nella tua applicazione e reindirizzalo subito a url: il link è valido per 5 minuti e apre una sola sessione del portale, una volta sola. url viene restituita solo in questa risposta, una volta; nessun endpoint la restituisce in seguito. La risposta contiene Cache-Control: no-store, e una risposta riprodotta per lo stesso Idempotency-Key omette url e contiene secret_redacted: true. La sessione del portale dura 60 minuti di inattività, al massimo 8 ore; revocala con DELETE /v1/admin-portal-links/{link_id}. La creazione viene registrata come admin_portal_link.created (l'URL non entra mai nel log di audit).
audit_logs richiede il piano Business e log_streams il piano Enterprise; gli altri intent sono disponibili in tutti i piani. delivery: email invia invece un invito: è valido 7 giorni e viene inviato via e-mail a recipient_email; la risposta non contiene né url né l'indirizzo. Quando il destinatario lo apre, un codice a 6 cifre (valido 10 minuti) viene inviato allo stesso indirizzo, e solo il codice verificato apre la sessione del portale. Se l'e-mail di invito non può essere inviata, la chiamata risponde 503 service_unavailable con Retry-After e non crea nulla. Revoca un invito con DELETE /v1/admin-portal-links/{link_id}. L'indirizzo del destinatario non compare mai in una risposta, in un elenco, nel log di audit o in un log.
Richiesta
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
organization_id |
string | sì | ID dell'organizzazione (org_…); deve esistere in questo ambiente. |
intents |
string[] | sì | Da 1 a 6 valori tra sso, dsync, domain_verification, certificate_renewal, audit_logs (Business), log_streams (Enterprise), senza duplicati. |
return_url |
string | sì | URL https assoluto di al massimo 2048 byte, senza informazioni utente né frammento. La sua origine deve coincidere con l'origine di un redirect_uri di un'applicazione attiva registrata in questo ambiente. |
delivery |
string | no | link (predefinito; url monouso valida 5 minuti nella risposta) oppure email (invito valido 7 giorni inviato via e-mail a recipient_email; senza url). |
recipient_email |
string | no | Solo con delivery: email, e obbligatorio in quel caso; al massimo 320 caratteri. Se manca: 422 /recipient_email required; con delivery: link: not_allowed; indirizzo non valido: invalid_value. |
Risposta
201 Created con il link e la sua url monouso.
{
"id": "apl_01j9xv2c4d6e8f0g2h4j6k8m0n",
"organization_id": "org_01j9xk3m7q8r2s4t6v8w0y2z4a",
"intents": [
"dsync",
"sso"
],
"delivery": "link",
"return_url": "https://app.example.com/settings/sso",
"expires_at": "2026-10-12T09:36:00.123456Z",
"consumed_at": null,
"revoked_at": null,
"created_at": "2026-10-12T09:31:00.123456Z",
"url": "https://acme.eu.keenauth.app/portal/l/<token>"
}
Errori
| HTTP | code | Quando |
|---|---|---|
| 403 | plan_feature_unavailable |
Un intent richiede un piano superiore; feature e required_plan lo indicano. |
| 404 | not_found |
L'organizzazione non esiste in questo ambiente. |
| 409 | organization_disabled |
L'organizzazione non è attiva (disabilitata); non viene creato alcun link. |
| 409 | organization_pending_deletion |
L'organizzazione è programmata per l'eliminazione; non viene creato alcun link. |
| 422 | validation_failed |
Un campo manca o non è valido; /return_url origin_not_registered quando la sua origine non è quella di un'applicazione registrata; /recipient_email required, not_allowed o invalid_value. |
| 401 | unauthenticated |
La credenziale manca, non è valida o è stata revocata. |
| 403 | insufficient_permissions |
La credenziale non ha il permesso richiesto. |
| 429 | rate_limited |
È stato superato il limite di frequenza; riprova dopo il periodo indicato da Retry-After. |
| 503 | service_unavailable |
Una dipendenza è temporaneamente non disponibile, oppure (delivery: email) l'e-mail di invito non può essere inviata; non viene creato nulla. Riprova dopo il periodo indicato da Retry-After. |
Esempio
curl -i -X POST "https://api.eu.keenauth.com/v1/admin-portal-links" \
-H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{"organization_id":"org_01j9xk3m7q8r2s4t6v8w0y2z4a","intents":["sso","dsync"],"return_url":"https://app.example.com/settings/sso"}'
Inviare un invito via e-mail
curl -i -X POST "https://api.eu.keenauth.com/v1/admin-portal-links" \
-H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"organization_id":"org_01j9xk3m7q8r2s4t6v8w0y2z4a","intents":["sso"],"return_url":"https://app.example.com/settings/sso","delivery":"email","recipient_email":"it@customer.example"}'
201 Created; la risposta non contiene né url né l'indirizzo:
{
"id": "apl_01j9xv2c4d6e8f0g2h4j6k8m0n",
"organization_id": "org_01j9xk3m7q8r2s4t6v8w0y2z4a",
"intents": [
"sso"
],
"delivery": "email",
"return_url": "https://app.example.com/settings/sso",
"expires_at": "2026-10-19T09:31:00.123456Z",
"consumed_at": null,
"revoked_at": null,
"created_at": "2026-10-12T09:31:00.123456Z"
}
Con la CLI: keenauth admin-portal-links create --organization-id org_01j9xk3m7q8r2s4t6v8w0y2z4a --intents sso --return-url https://app.example.com/settings/sso --delivery email --recipient-email it@customer.example.