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.

OptionBenefitCost
admin-cli + master admin passwordWorks immediately with no extra setup — fine for a one-off experiment or debuggingTies every automation script to a single super-user credential; a leak affects the whole system, and rotating it is hard
Dedicated service account (confidential client)Scoped to only the realm-management roles it needs; the secret can be rotated independently per pipelineRequires creating and maintaining an extra client, and the roles must be assigned correctly up front
kcadm.sh CLIShorter syntax than raw curl, and caches the token automatically for the sessionOnly works when you have shell access to the container/host — not suited to automation that runs outside the Keycloak environment
  • Automating everything with the master admin username/password — widens the blast radius if the credential leaks, and is hard to rotate because every script depends on it. Create a dedicated service account instead.
  • Granting a service account broader roles than it needs — assigning every realm-management role “just in case” when the script only needs manage-users increases the risk if the client secret leaks.
  • Forgetting that admin tokens are very short-lived — caching the token in a variable and reusing it across script runs without requesting a new one causes automation to fail mid-run with a 401 once the token expires (about 60 seconds by default).

Real-world example

CI/CD pipelines for config-as-code — many platform teams use a service-account client to import/export realm configuration as part of a deployment pipeline, instead of an engineer clicking through the admin console by hand.

The Keycloak Terraform provider — the community-maintained keycloak/keycloak provider (github.com/keycloak/terraform-provider-keycloak, the successor to the now-archived mrparkers/terraform-provider-keycloak) calls the Admin REST API behind the scenes with service-account credentials to create and manage realms, clients, and roles declaratively.

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?