Skip to main content
Back to Android

Android Management API

ThunderIDClient exposes the ThunderID management API through three clients: applications, users, and agents. Each lists, reads, creates, updates, and deletes its resource. Requests are authorized with the signed-in user's access token, and the token needs the permissions the server requires for each resource.

kotlin
import dev.thunderid.android.management.ApplicationRequest

val page = client.applications.list(limit = 20)

val application = client.applications.create(
ApplicationRequest(name = "My App", url = "https://app.example.com")
)

client.users.delete("<user-id>")

The models and clients live in the dev.thunderid.android.management package. Accessing applications, users, or agents throws SDK_NOT_INITIALIZED until initialize has run.

Operations​

ClientFunctionRequestReturns
applicationslist(limit, offset, fetcher)GET /applicationsApplicationListResponse
get(id, fetcher)GET /applications/{id}Application
create(application, fetcher)POST /applicationsApplication
update(id, application, fetcher)PUT /applications/{id}Application
delete(id, fetcher)DELETE /applications/{id}Unit
userslist(limit, offset, filter, fetcher)GET /users?include=displayManagedUserListResponse
get(id, fetcher)GET /users/{id}?include=displayManagedUser
create(user, fetcher)POST /usersManagedUser
update(id, user, fetcher)PUT /users/{id}ManagedUser
delete(id, fetcher)DELETE /users/{id}Unit
agentslist(limit, offset, fetcher)GET /agents?include=displayAgentListResponse
get(id, fetcher)GET /agents/{id}?include=displayAgent
create(agent, fetcher)POST /agentsAgent
update(id, agent, fetcher)PUT /agents/{id}Agent
delete(id, fetcher)DELETE /agents/{id}Unit

All functions are suspend functions, and every parameter other than id and the payload is optional.

Models​

PayloadUsed byRequired fields
ApplicationRequestapplications.create, applications.updatename
CreateManagedUserRequestusers.createouId, type
UpdateManagedUserRequestusers.updateNone
CreateAgentRequestagents.createouId, type, name
UpdateAgentRequestagents.updateNone

An update replaces the application's mutable fields. Call Application.toRequest() to get the full payload, then change the fields you need with copy:

kotlin
val current = client.applications.get("<application-id>")
client.applications.update(current.id, current.toRequest().copy(description = "Updated"))

A ManagedUser is a user record on the server, with id, ouId, type, attributes, and the resolved display value. It is a different type from User, which describes the signed-in user.

Transport​

Set ThunderIDConfig.http.fetcher to route management requests through your own transport. A fetcher passed to a single call takes precedence over the configured one.

kotlin
fun interface ThunderIDFetcher {
suspend fun fetch(request: ThunderIDHttpRequest): ThunderIDHttpResponse
}

ThunderIDConfig(
baseUrl = "https://localhost:8090",
clientId = "<your-client-id>",
http = ThunderIDHttpConfig(fetcher = myFetcher),
)

ThunderIDHttpRequest carries method, url, headers, and the JSON body. The headers already include Authorization. Return a ThunderIDHttpResponse with the statusCode and response body; the SDK maps non-2xx statuses to IAMException. Without a fetcher, requests use the SDK's built-in HTTP transport. http.fetcher applies to management operations only; sign-in, token, and flow requests keep using the SDK's own transport.

Management API on a Separate Host​

Requests go to {baseUrl}/applications, {baseUrl}/users, and {baseUrl}/agents. When the management API runs on a different host, set the collection URL through ThunderIDConfig.endpoints:

kotlin
ThunderIDConfig(
baseUrl = "https://idp.example.com",
clientId = "<your-client-id>",
endpoints = ThunderIDEndpoints(
applications = "https://rs.example.com/applications",
users = "https://rs.example.com/users",
agents = "https://rs.example.com/agents",
),
)

Jetpack Compose​

The dev.thunderid.compose.management package provides composables for each operation. They read the client from ThunderIDProvider. Query composables load on first composition and return a ResourceQueryState with data, error, and isLoading. Mutation composables return a ResourceMutationState with mutate, which never throws, and mutateThrowing, which does.

kotlin
@Composable
fun Applications() {
val applications = rememberGetApplications(limit = 20)
val deleteApplication = rememberDeleteApplication()
val scope = rememberCoroutineScope()

LazyColumn {
items(applications.data?.applications.orEmpty()) { application ->
Row {
Text(application.name)
Button(onClick = { scope.launch { deleteApplication.mutate(application.id) } }) {
Text("Delete")
}
}
}
}
}
ResourceQueriesMutations
ApplicationsrememberGetApplications, rememberGetApplicationrememberCreateApplication, rememberUpdateApplication, rememberDeleteApplication
UsersrememberGetUsers, rememberGetUserrememberCreateUser, rememberUpdateUser, rememberDeleteUser
AgentsrememberGetAgents, rememberGetAgentrememberCreateAgent, rememberUpdateAgent, rememberDeleteAgent

A single-resource query does not load while its id is null. A successful mutation refetches the queries it changed: a create or delete refetches the resource's list queries, and an update also refetches the query for that resource. Mutations produce no snackbar or log entry.

Error Handling​

The functions throw IAMException. Management requests add two codes:

CodeDescription
FORBIDDENThe server returned HTTP 403. The access token lacks permission for the operation.
NOT_FOUNDThe server returned HTTP 404. The resource does not exist.
INVALID_INPUTThe resource identifier is blank, or the server rejected the payload with HTTP 400.

See Error Codes for the full list.

Explore with AI

ThunderID LogoThunderID Logo

Product

DocsAPIsSDKs
© Copyright Linux Foundation Europe.For web site terms of use, trademark policy and other project policies please see https://linuxfoundation.eu/en/policies.