Managing your applications: disable, delete & rotate the secret

This guide shows how a tenant looks after the lifecycle of its own OAuth application registrations — without a platform-operator ticket and without touching the database. It is the answer to the common incident: "a client secret leaked and we need to deal with it ourselves."

You can do everything here two ways, with identical effect:

  • Admin API — using your tenant's admin API key (the key must carry the applications:write scope; the bootstrap admin key already does).
  • Hosted Admin console — as a signed-in tenant admin, at …/t/<your-slug>/hosted/admin/applications. No API key needed.

The application's own client credentials are not accepted for these operations. That is deliberate: if a secret has leaked, whoever holds it must not be able to rotate it or lock you out.

What you can do

ActionWhat it doesReversible?
Rotate secretIssues a new client secret (shown once) and retires the old one.n/a — issue a new one again if lost
DisableImmediate kill switch: the client can no longer complete any sign-in or token call.Yes — re-enable any time
DeletePermanently retires the registration; the client_id is never reused.No — terminal

The revocation cascade (important)

Disabling, deleting, or rotating immediately (no overlap window) does more than block new logins — it revokes the credentials already issued for that application within a few seconds:

  • the application's outstanding access tokens stop validating,
  • its refresh tokens stop working, and
  • its per-application access grants are removed.

This is scoped to the one application. A user's tenant-wide single sign-on session is left intact — disabling one app does not sign them out of the others.

Rotate a leaked secret

The old secret dies at once and anything minted with it is revoked.

curl -sX POST "$HAP/v1/applications/$APP/rotate-secret" \
  -H "X-Admin-Key: $KEY" -H "X-Tenant-Id: $TENANT" \
  -H 'content-type: application/json' -d '{}'
# → {"client_id":"hap_…","client_secret":"<NEW — copy now>","mode":"immediate","overlap_expires_at":null,…}

Zero-downtime (routine rotation)

Keep the previous secret working for a short grace period (the overlap window) so a running deployment can pick up the new secret with no failed requests. The window is bounded by the platform maximum of 2 hours (a request above the max is clamped); existing user credentials are not revoked in this mode.

curl -sX POST "$HAP/v1/applications/$APP/rotate-secret" \
  -H "X-Admin-Key: $KEY" -H "X-Tenant-Id: $TENANT" \
  -H 'content-type: application/json' -d '{"overlap_seconds": 3600}'
# → {"client_secret":"<NEW>","mode":"overlap","overlap_expires_at":"…+1h", …}

The secret is shown once. If you lose it, just rotate again. Rotation is only for confidential clients — a public (PKCE-only) client has no secret, so rotate returns secret_rotation_not_applicable.

Disable / re-enable (kill switch)

# Stop the application now (revokes its tokens & sessions within ~5s):
curl -sX POST "$HAP/v1/applications/$APP/disable" -H "X-Admin-Key: $KEY" -H "X-Tenant-Id: $TENANT"

# Bring it back when the situation is resolved:
curl -sX POST "$HAP/v1/applications/$APP/enable" -H "X-Admin-Key: $KEY" -H "X-Tenant-Id: $TENANT"

Re-enabling restores the ability to sign in again, but it does not un-revoke the tokens and sessions the cascade already killed — affected users simply sign in again.

Delete an orphan application

curl -sX DELETE "$HAP/v1/applications/$APP" -H "X-Admin-Key: $KEY" -H "X-Tenant-Id: $TENANT"
# → 204. The app disappears from GET /v1/applications, all its flows are refused, and its
#   client_id is never handed out to a new application. A second DELETE returns 404.

From the Hosted Admin console

Sign in as a tenant admin and open Admin → Applications (…/t/<your-slug>/hosted/admin/applications). Each application row has Disable / Enable / Rotate secret / Delete controls; rotating shows the new secret once. Non-admin users cannot see or use these controls.

Good to know

  • Audit trail. Every disable, enable, delete, and rotate is written to the audit log (who, which application, and when). Secrets are never logged.
  • Find the application id. GET /v1/applications lists your live applications with their client_id, enabled state, and secret_rotated_at; deleted apps are not listed and secrets are never returned.
  • Errors. An unknown, other-tenant, or already-deleted application returns application_not_found (404). A caller lacking applications:write (or a non-admin in the console) is refused.