Skip to main content
Back to iOS

iOS Management API

ThunderIDClient exposes the ThunderID management API through three accessors: 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.

swift
import ThunderID

let page = try await client.applications.list(limit: 20)

var request = ApplicationRequest(name: "My App")
request.url = "https://app.example.com"
let application = try await client.applications.create(request)

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

The accessors throw .sdkNotInitialized until initialize(config:) has run.

Operations​

AccessorMethodRequestReturns
applicationslist(limit:offset:fetcher:)GET /applicationsApplicationListResponse
get(id:fetcher:)GET /applications/{id}Application
create(_:fetcher:)POST /applicationsApplication
update(id:_:fetcher:)PUT /applications/{id}Application
delete(id:fetcher:)DELETE /applications/{id}Nothing
userslist(limit:offset:filter:fetcher:)GET /users?include=displayManagedUserListResponse
get(id:fetcher:)GET /users/{id}?include=displayManagedUser
create(_:fetcher:)POST /usersManagedUser
update(id:_:fetcher:)PUT /users/{id}ManagedUser
delete(id:fetcher:)DELETE /users/{id}Nothing
agentslist(limit:offset:fetcher:)GET /agents?include=displayAgentListResponse
get(id:fetcher:)GET /agents/{id}?include=displayAgent
create(_:fetcher:)POST /agentsAgent
update(id:_:fetcher:)PUT /agents/{id}Agent
delete(id:fetcher:)DELETE /agents/{id}Nothing

All methods are async throws.

Models​

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

Application holds the server-generated id, createdAt, and updatedAt, plus an ApplicationRequest in its request property. Every ApplicationRequest field reads directly on the application, as in application.name. To update an application, edit application.request and pass it to update(id:_:), because an update replaces the application's mutable fields.

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.

swift
public typealias ThunderIDFetcher = (URLRequest) async throws -> (Data, URLResponse)

ThunderIDConfig(
baseUrl: "https://localhost:8090",
clientId: "<your-client-id>",
http: ThunderIDHttpConfig(fetcher: { request in try await URLSession.shared.data(for: request) })
)

The request passed to the fetcher already carries the Authorization header. Without a fetcher, requests use the SDK's URLSession. 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:

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

SwiftUI​

ThunderIDState builds observable wrappers for each operation. Queries are ResourceQuery objects with data, error, and isLoading; call refetch() to load them. Mutations are ResourceMutation objects with mutate(_:), which never throws, and mutateThrowing(_:), which does. Hold either one as a @StateObject so the view updates when it changes:

swift
struct ApplicationsView: View {
@EnvironmentObject private var thunderID: ThunderIDState

var body: some View {
ApplicationsList(query: thunderID.applicationsQuery(limit: 20))
}
}

struct ApplicationsList: View {
@StateObject private var query: ResourceQuery<ApplicationListResponse>

init(query: @autoclosure @escaping () -> ResourceQuery<ApplicationListResponse>) {
_query = StateObject(wrappedValue: query())
}

var body: some View {
List(query.data?.applications ?? [], id: \.id) { application in
Text(application.name)
}
.task { await query.refetch() }
}
}
ResourceQueriesMutations
ApplicationsapplicationsQuery(limit:offset:fetcher:), applicationQuery(id:fetcher:)createApplicationMutation, updateApplicationMutation, deleteApplicationMutation
UsersusersQuery(limit:offset:filter:fetcher:), userQuery(id:fetcher:)createUserMutation, updateUserMutation, deleteUserMutation
AgentsagentsQuery(limit:offset:fetcher:), agentQuery(id:fetcher:)createAgentMutation, updateAgentMutation, deleteAgentMutation

A successful mutation refetches the queries it changed, once they have loaded: a create or delete refetches the resource's list queries, and an update also refetches the query for that resource. Mutations produce no alert or log entry.

Error Handling​

The methods throw ThunderIDError. Catch it and switch on code:

swift
do {
let application = try await client.applications.get(id: applicationId)
} catch let error as ThunderIDError where error.code == .notFound {
// Show a "not found" state.
} catch let error as ThunderIDError where error.code == .forbidden {
// The signed-in user cannot read applications.
}

Management requests add two codes:

CodeValueDescription
.forbiddenFORBIDDENThe server returned HTTP 403. The access token lacks permission for the operation.
.notFoundNOT_FOUNDThe server returned HTTP 404. The resource does not exist.
.invalidInputINVALID_INPUTThe resource identifier is empty, 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.