Skip to content

Admin REST API

Every button in the Keycloak admin console is backed by the Admin REST API. The same HTTP endpoints that the console uses are fully documented and available to you. This means you can:

  • Automate realm creation and configuration in a CI pipeline.
  • Provision users and assign roles from a bootstrap script.
  • Register clients programmatically instead of clicking through the wizard.

The API lives at https://<keycloak-host>/admin/realms/<realm>/....

Before calling any admin endpoint you need a Bearer token issued by Keycloak itself. There are two common approaches.

Option 1 — the built-in admin-cli client

Section titled “Option 1 — the built-in admin-cli client”

Keycloak ships with a client called admin-cli in the master realm. You can exchange the master-admin credentials for a token:

curl -s -X POST https://localhost:8080/realms/master/protocol/openid-connect/token \
  -d client_id=admin-cli \
  -d grant_type=password \
  -d username=admin \
  -d password=admin \
  | jq -r '.access_token'

Store the result in a variable, for example TOKEN=$(...). The token is short-lived (typically 60 seconds), so request a fresh one each time your script runs.

For automated pipelines, create a confidential client in the realm you are managing, enable Service accounts roles, and assign it the realm-management roles it needs (e.g., manage-users, manage-clients). Then exchange client credentials:

curl -s -X POST https://localhost:8080/realms/my-app/protocol/openid-connect/token \
  -d client_id=my-admin-client \
  -d client_secret=YOUR_CLIENT_SECRET \
  -d grant_type=client_credentials \
  | jq -r '.access_token'

Once you have a token, pass it as a Bearer header. Here is an example that lists all users in a realm:

curl -s https://localhost:8080/admin/realms/my-app/users \
  -H "Authorization: Bearer ${TOKEN}" \
  | jq .

Replace my-app with your realm name and \${TOKEN} with the access token you obtained above.

Common admin endpoints:

OperationMethodPath
List usersGET/admin/realms/{realm}/users
Create userPOST/admin/realms/{realm}/users
List clientsGET/admin/realms/{realm}/clients
List realm rolesGET/admin/realms/{realm}/roles

Keycloak ships with a CLI tool called kcadm.sh (inside the container at /opt/keycloak/bin/kcadm.sh). It wraps the Admin REST API with a friendlier syntax:

Terminal window
# Authenticate once
/opt/keycloak/bin/kcadm.sh config credentials \
--server http://localhost:8080 \
--realm master \
--user admin --password admin
# List users in a realm
/opt/keycloak/bin/kcadm.sh get users -r my-app

kcadm.sh caches the token locally, so you only need to authenticate once per session. For scripts that run inside the Keycloak container (e.g., in a Docker entrypoint), kcadm.sh is often simpler than raw curl.

What HTTP header do you use to authenticate Admin REST API calls?
Which grant type does a service account use to obtain a token?
What is the correct Admin REST API path to list users in a realm called "shop"?
Why is kcadm.sh sometimes simpler than raw curl for admin scripts?