Admin REST API
What is the Admin REST API?
Section titled “What is the 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>/....
Getting an admin access token
Section titled “Getting an admin access token”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.
Option 2 — a dedicated service account
Section titled “Option 2 — a dedicated service account”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'Calling an Admin REST API endpoint
Section titled “Calling an Admin REST API endpoint”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:
| Operation | Method | Path |
|---|---|---|
| List users | GET | /admin/realms/{realm}/users |
| Create user | POST | /admin/realms/{realm}/users |
| List clients | GET | /admin/realms/{realm}/clients |
| List realm roles | GET | /admin/realms/{realm}/roles |
kcadm.sh as an alternative
Section titled “kcadm.sh as an alternative”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:
# 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-appkcadm.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.
Trade-offs
Section titled “Trade-offs”| Option | Benefit | Cost |
|---|---|---|
admin-cli + master admin password | Works immediately with no extra setup — fine for a one-off experiment or debugging | Ties 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 pipeline | Requires creating and maintaining an extra client, and the roles must be assigned correctly up front |
kcadm.sh CLI | Shorter syntax than raw curl, and caches the token automatically for the session | Only works when you have shell access to the container/host — not suited to automation that runs outside the Keycloak environment |
Common mistakes
Section titled “Common mistakes”- 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-managementrole “just in case” when the script only needsmanage-usersincreases 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/keycloakprovider (github.com/keycloak/terraform-provider-keycloak, the successor to the now-archivedmrparkers/terraform-provider-keycloak) calls the Admin REST API behind the scenes with service-account credentials to create and manage realms, clients, and roles declaratively.