GoodMemGoodMem
ReferenceClient SDKs.NET

Users

.NET SDK reference for human users: enrollment management, creation, lookup, listing, updates, and deletion.

User lookup by id, email, or me.

Namespace: Goodmem.Client.Api · Class: UsersApi

Reach this surface as client.Users on a GoodmemClient. Every network method is asynchronous — it returns a Task<T> (or an IAsyncEnumerable<T> for pagination and streaming) and accepts a CancellationToken; the Async suffix marks the standard .NET Task-based async pattern.

Methods

MethodSummary
CreateAsyncCreate a human user.
GetAsyncGet a user by ID.
ListAsyncList human users.
UpdateAsyncUpdate a human user.
DeleteAsyncDelete a human user.
CreateEnrollmentAsyncCreate a human-user enrollment.
GetByUsernameAsyncGet user by username.
GetEnrollmentAsyncGet a human-user enrollment.
ListEnrollmentsAsyncList a human user's enrollments.
MeAsyncGet current user profile.
RevokeEnrollmentAsyncRevoke a human-user enrollment.

CreateAsync

Creates one dormant human user after requiring instance-wide CREATE_USER authority. Creation does not issue a credential or create a role, grant, or authentication mapping.

Declaration

public Task<UserResponse> CreateAsync(CreateUserRequest request, CancellationToken ct = default)

HTTPPOST /v1/users

Parameters

TypeNameDescription
CreateUserRequestrequestThe request payload; the linked model lists every field and its JSON wire name.
CancellationTokenctCancellation / deadline signal for the call. (optional)

Returns

Task<UserResponse> — an awaitable that resolves to UserResponse.

Exceptions

TypeCondition
ArgumentNullExceptionrequest is null.
NetworkExceptionThe request could not reach the server (DNS, connection, or TLS failure).
ApiExceptionThe server returned a non-success (non-2xx) status. A status-specific subtype is thrown where it applies — e.g. NotFoundException (404), PermissionDeniedException (403), ConflictException (409).

Example

var createdUser = await client.Users.CreateAsync(
    new CreateUserRequest
    {
        Email = "[email protected]",
        Username = "alex",
        DisplayName = "Alex Example",
        Labels = new Dictionary<string, string> { ["team"] = "search" },
    }
);


GetAsync

Retrieves a user by ID or email address. Exactly one of id and email must be provided.

Declaration

public Task<UserResponse> GetAsync(UsersGetOptions options, CancellationToken ct = default)

HTTPGET /v1/users/&#123;id&#125;

Parameters

TypeNameDescription
UsersGetOptionsoptionsOptions bag carrying the lookup key(s) / convenience knobs; the linked type lists them all.
CancellationTokenctCancellation / deadline signal for the call. (optional)

Returns

Task<UserResponse> — an awaitable that resolves to UserResponse.

Exceptions

TypeCondition
ArgumentNullExceptionoptions is null.
NetworkExceptionThe request could not reach the server (DNS, connection, or TLS failure).
ApiExceptionThe server returned a non-success (non-2xx) status. A status-specific subtype is thrown where it applies — e.g. NotFoundException (404), PermissionDeniedException (403), ConflictException (409).

Examples

Example 1:

var user = await client.Users.GetAsync(new UsersGetOptions { Id = "your-user-id" });
Console.WriteLine(user.Email);

Example 2:

// Or look a user up by email instead of ID.
var user = await client.Users.GetAsync(
    new UsersGetOptions { Email = "[email protected]" }
);
Console.WriteLine(user.UserId);


ListAsync

Requires LIST_USER on the GoodMem instance and READ_USER on each returned row. Authorization, label filtering, lifecycle filtering, and keyset pagination run in PostgreSQL. includeDeleted expands the lifecycle view but grants no access. includeEnrollmentSummary requests non-secret bootstrap posture only on active rows where MANAGE_USER_ENROLLMENT is independently authorized.

LABEL FILTERS: Label filters accept either label.<key>=<value> or label[key]=value (for example, label.environment=production or label[environment]=production).

Declaration

public IAsyncEnumerable<UserResponse> ListAsync(UsersListOptions? options = null, CancellationToken ct = default)

HTTPGET /v1/users

Parameters

TypeNameDescription
UsersListOptionsoptionsOptions bag carrying the lookup key(s) / convenience knobs; the linked type lists them all. (optional)
CancellationTokenctCancellation / deadline signal for the call. (optional)

Returns

IAsyncEnumerable<UserResponse> — an async stream; await foreach yields each UserResponse across pages / events.

Exceptions

TypeCondition
NetworkExceptionThe request could not reach the server (DNS, connection, or TLS failure).
ApiExceptionThe server returned a non-success (non-2xx) status. A status-specific subtype is thrown where it applies — e.g. NotFoundException (404), PermissionDeniedException (403), ConflictException (409).

Example

await foreach (var user in client.Users.ListAsync(new UsersListOptions { MaxResults = 25 }))
    Console.WriteLine($"{user.UserId} {user.Email}");


UpdateAsync

Updates only fields present in the request. Empty username or displayName values clear those optional fields. Updating a deleted user fails with 412.

Declaration

public Task<UserResponse> UpdateAsync(string id, UpdateUserRequest request, CancellationToken ct = default)

HTTPPUT /v1/users/&#123;id&#125;

Parameters

TypeNameDescription
stringidUser UUID
UpdateUserRequestrequestThe request payload; the linked model lists every field and its JSON wire name.
CancellationTokenctCancellation / deadline signal for the call. (optional)

Returns

Task<UserResponse> — an awaitable that resolves to UserResponse.

Exceptions

TypeCondition
ArgumentExceptionid is null or empty.
ArgumentNullExceptionrequest is null.
NetworkExceptionThe request could not reach the server (DNS, connection, or TLS failure).
ApiExceptionThe server returned a non-success (non-2xx) status. A status-specific subtype is thrown where it applies — e.g. NotFoundException (404), PermissionDeniedException (403), ConflictException (409).

Example

var updatedUser = await client.Users.UpdateAsync(
    "your-user-id",
    new UpdateUserRequest { DisplayName = "Alexandra Example" }
);


DeleteAsync

Permanently soft-deletes the user and invalidates credentials acting for that subject. The GoodMem instance owner cannot be deleted; transfer ownership first. Repeating an authorized delete succeeds without rewriting audit data.

Declaration

public Task DeleteAsync(string id, CancellationToken ct = default)

HTTPDELETE /v1/users/&#123;id&#125;

Parameters

TypeNameDescription
stringidUser UUID
CancellationTokenctCancellation / deadline signal for the call. (optional)

Returns

Task — completes when the operation finishes; there is no response body.

Exceptions

TypeCondition
ArgumentExceptionid is null or empty.
NetworkExceptionThe request could not reach the server (DNS, connection, or TLS failure).
ApiExceptionThe server returned a non-success (non-2xx) status. A status-specific subtype is thrown where it applies — e.g. NotFoundException (404), PermissionDeniedException (403), ConflictException (409).

Example

await client.Users.DeleteAsync("your-user-id");


CreateEnrollmentAsync

Creates a short-lived, one-time enrollment credential for an existing dormant human. Requires MANAGE_USER_ENROLLMENT with ANY or EXACT authority on the target user. The raw credential is returned only once. rotateExisting atomically revokes and replaces a live enrollment; an expired enrollment is replaced automatically.

Declaration

public Task<CreateUserEnrollmentResponse> CreateEnrollmentAsync(string userId, CreateUserEnrollmentRequest? request = null, CancellationToken ct = default)

HTTPPOST /v1/users/&#123;userId&#125;/enrollments

Parameters

TypeNameDescription
stringuserIdHuman-user UUID
CreateUserEnrollmentRequestrequestThe request payload; the linked model lists every field and its JSON wire name. (optional)
CancellationTokenctCancellation / deadline signal for the call. (optional)

Returns

Task<CreateUserEnrollmentResponse> — an awaitable that resolves to CreateUserEnrollmentResponse.

Exceptions

TypeCondition
ArgumentExceptionuserId is null or empty.
NetworkExceptionThe request could not reach the server (DNS, connection, or TLS failure).
ApiExceptionThe server returned a non-success (non-2xx) status. A status-specific subtype is thrown where it applies — e.g. NotFoundException (404), PermissionDeniedException (403), ConflictException (409).

Example

var createdEnrollment = await client.Users.CreateEnrollmentAsync(
    "your-user-id",
    new CreateUserEnrollmentRequest { RotateExisting = true }
);
// Save createdEnrollment.EnrollmentToken now; it is returned only once.


GetByUsernameAsync

Returns a user selected by exact username after applying READ_USER authority. includeDeleted permits an authorized caller to inspect a permanent tombstone; it does not grant additional authority. Missing and unauthorized matches both return 404 so this guessable identifier cannot reveal whether a user exists.

Declaration

public Task<UserResponse> GetByUsernameAsync(string username, UsersGetByUsernameOptions? options = null, CancellationToken ct = default)

HTTPGET /v1/users/username/&#123;username&#125;

Parameters

TypeNameDescription
stringusernameExact username
UsersGetByUsernameOptionsoptionsOptions bag carrying the lookup key(s) / convenience knobs; the linked type lists them all. (optional)
CancellationTokenctCancellation / deadline signal for the call. (optional)

Returns

Task<UserResponse> — an awaitable that resolves to UserResponse.

Exceptions

TypeCondition
ArgumentExceptionusername is null or empty.
NetworkExceptionThe request could not reach the server (DNS, connection, or TLS failure).
ApiExceptionThe server returned a non-success (non-2xx) status. A status-specific subtype is thrown where it applies — e.g. NotFoundException (404), PermissionDeniedException (403), ConflictException (409).

Example

var userByUsername = await client.Users.GetByUsernameAsync("alex");
Console.WriteLine(userByUsername.Email);


GetEnrollmentAsync

Returns non-secret metadata for one current or historical enrollment. The target user is resolved before the enrollment, and MANAGE_USER_ENROLLMENT with ANY or EXACT authority on that user is required. Raw enrollment tokens are never returned.

Declaration

public Task<UserEnrollmentResponse> GetEnrollmentAsync(string userId, string enrollmentId, CancellationToken ct = default)

HTTPGET /v1/users/&#123;userId&#125;/enrollments/&#123;enrollmentId&#125;

Parameters

TypeNameDescription
stringuserIdHuman-user UUID
stringenrollmentIdEnrollment UUID
CancellationTokenctCancellation / deadline signal for the call. (optional)

Returns

Task<UserEnrollmentResponse> — an awaitable that resolves to UserEnrollmentResponse.

Exceptions

TypeCondition
ArgumentExceptionuserId is null or empty.
ArgumentExceptionenrollmentId is null or empty.
NetworkExceptionThe request could not reach the server (DNS, connection, or TLS failure).
ApiExceptionThe server returned a non-success (non-2xx) status. A status-specific subtype is thrown where it applies — e.g. NotFoundException (404), PermissionDeniedException (403), ConflictException (409).

Example

var enrollment = await client.Users.GetEnrollmentAsync(
    "your-user-id",
    "your-enrollment-id"
);


ListEnrollmentsAsync

Returns one newest-first page containing pending, expired, consumed, and revoked enrollment metadata. MANAGE_USER_ENROLLMENT with ANY or EXACT authority on the target user is required. The page never contains raw credentials.

Declaration

public IAsyncEnumerable<UserEnrollmentResponse> ListEnrollmentsAsync(string userId, UsersListEnrollmentsOptions? options = null, CancellationToken ct = default)

HTTPGET /v1/users/&#123;userId&#125;/enrollments

Parameters

TypeNameDescription
stringuserIdHuman-user UUID
UsersListEnrollmentsOptionsoptionsOptions bag carrying the lookup key(s) / convenience knobs; the linked type lists them all. (optional)
CancellationTokenctCancellation / deadline signal for the call. (optional)

Returns

IAsyncEnumerable<UserEnrollmentResponse> — an async stream; await foreach yields each UserEnrollmentResponse across pages / events.

Exceptions

TypeCondition
ArgumentExceptionuserId is null or empty.
NetworkExceptionThe request could not reach the server (DNS, connection, or TLS failure).
ApiExceptionThe server returned a non-success (non-2xx) status. A status-specific subtype is thrown where it applies — e.g. NotFoundException (404), PermissionDeniedException (403), ConflictException (409).

Example

await foreach (var item in client.Users.ListEnrollmentsAsync("your-user-id"))
    Console.WriteLine($"{item.EnrollmentId} {item.Status}");


MeAsync

Returns the human-user profile associated with the authenticated principal. Service principals do not have a human-user profile.

Declaration

public Task<UserResponse> MeAsync(CancellationToken ct = default)

HTTPGET /v1/users/me

Parameters

TypeNameDescription
CancellationTokenctCancellation / deadline signal for the call. (optional)

Returns

Task<UserResponse> — an awaitable that resolves to UserResponse.

Exceptions

TypeCondition
NetworkExceptionThe request could not reach the server (DNS, connection, or TLS failure).
ApiExceptionThe server returned a non-success (non-2xx) status. A status-specific subtype is thrown where it applies — e.g. NotFoundException (404), PermissionDeniedException (403), ConflictException (409).

Example

var user = await client.Users.MeAsync();
Console.WriteLine($"{user.Email} {user.UserId}");


RevokeEnrollmentAsync

Permanently revokes one outstanding enrollment after requiring MANAGE_USER_ENROLLMENT on its target user. Repeating an authorized revocation succeeds without replacing its original audit provenance. Consumed enrollments cannot be revoked.

Declaration

public Task RevokeEnrollmentAsync(string userId, string enrollmentId, CancellationToken ct = default)

HTTPDELETE /v1/users/&#123;userId&#125;/enrollments/&#123;enrollmentId&#125;

Parameters

TypeNameDescription
stringuserIdHuman-user UUID
stringenrollmentIdEnrollment UUID
CancellationTokenctCancellation / deadline signal for the call. (optional)

Returns

Task — completes when the operation finishes; there is no response body.

Exceptions

TypeCondition
ArgumentExceptionuserId is null or empty.
ArgumentExceptionenrollmentId is null or empty.
NetworkExceptionThe request could not reach the server (DNS, connection, or TLS failure).
ApiExceptionThe server returned a non-success (non-2xx) status. A status-specific subtype is thrown where it applies — e.g. NotFoundException (404), PermissionDeniedException (403), ConflictException (409).

Example

await client.Users.RevokeEnrollmentAsync("your-user-id", "your-enrollment-id");


Data Models

Types in the Goodmem.Client.Models namespace. Each row lists the C# property, its type, the JSON wire name, and a description.

CreateUserRequest

Creates a human user without creating a credential, role assignment, grant, or external authentication mapping.

PropertyTypeJSON (wire)Description
UserIdstringuserIdOptional client-provided user UUID; generated by the server when omitted. (optional)
EmailstringemailUnique, nonempty email address.
UsernamestringusernameOptional unique username. (optional)
DisplayNamestringdisplayNameOptional human-facing display name. (optional)
LabelsIReadOnlyDictionary<string, string>labelsOptional labels for organization and filtering. At most 20 entries; keys and values contain at most 255 characters; keys use [a-z0-9._-]. (optional)

UserResponse

A durable human user profile and its lifecycle metadata.

PropertyTypeJSON (wire)Description
UserIdstringuserIdOUTPUT_ONLY; immutable user UUID.
EmailstringemailOUTPUT_ONLY; unique email address.
DisplayNamestringdisplayNameOUTPUT_ONLY; optional human-facing display name. (optional)
UsernamestringusernameOUTPUT_ONLY; optional unique username. (optional)
LabelsIReadOnlyDictionary<string, string>labelsOUTPUT_ONLY; mutable labels attached to the user principal. At most 20 entries; keys and values contain at most 255 characters; keys use [a-z0-9._-].
EnrollmentSummaryUserEnrollmentSummaryenrollmentSummaryOUTPUT_ONLY; enrollment posture when requested and independently authorized. (optional)
DeletedAtDateTimeOffsetdeletedAtOUTPUT_ONLY; permanent deletion time in milliseconds, absent while active. (optional)
DeletedByIdstringdeletedByIdOUTPUT_ONLY; exact deleting actor UUID, absent while active. (optional)
CreatedAtDateTimeOffsetcreatedAtOUTPUT_ONLY; creation time in milliseconds since the epoch.
UpdatedAtDateTimeOffsetupdatedAtOUTPUT_ONLY; most recent mutation time in milliseconds since the epoch.
CreatedByIdstringcreatedByIdOUTPUT_ONLY; exact creating actor UUID.
UpdatedByIdstringupdatedByIdOUTPUT_ONLY; exact actor UUID for the most recent mutation.

UserEnrollmentSummary

Non-secret enrollment posture for one active human user.

PropertyTypeJSON (wire)Description
BootstrapEligibleboolbootstrapEligibleWhether no enrollment has been consumed and the user has no subject API key.
OpenEnrollmentStatusstringopenEnrollmentStatusState of the open enrollment, when one exists; present exactly with openEnrollmentExpiresAt. (optional)
OpenEnrollmentExpiresAtDateTimeOffsetopenEnrollmentExpiresAtExclusive open-enrollment completion deadline in epoch milliseconds; present exactly with openEnrollmentStatus. (optional)

CreateUserEnrollmentRequest

Options for issuing a one-time enrollment credential to the user named by the request path.

PropertyTypeJSON (wire)Description
EnrollmentIdstringenrollmentIdOptional client-provided enrollment UUID; generated when omitted. (optional)
RotateExistingboolrotateExistingWhether an existing live enrollment may be revoked and atomically replaced. (optional)

CreateUserEnrollmentResponse

New enrollment metadata and its one-time raw enrollment credential.

PropertyTypeJSON (wire)Description
EnrollmentUserEnrollmentResponseenrollmentOUTPUT_ONLY; non-secret metadata for the created enrollment.
EnrollmentTokenstringenrollmentTokenOUTPUT_ONLY; one-time raw enrollment credential. Save and deliver it securely.

UserEnrollmentResponse

Non-secret lifecycle metadata for a human user's one-time enrollment credential.

PropertyTypeJSON (wire)Description
EnrollmentIdstringenrollmentIdOUTPUT_ONLY; immutable enrollment UUID.
UserIdstringuserIdOUTPUT_ONLY; UUID of the human user invited to enroll.
CredentialPrefixstringcredentialPrefixOUTPUT_ONLY; non-secret prefix that identifies the enrollment credential safely.
StatusstringstatusOUTPUT_ONLY; current derived enrollment lifecycle state.
ExpiresAtDateTimeOffsetexpiresAtOUTPUT_ONLY; exclusive completion deadline in milliseconds since epoch.
ConsumedApiKeyIdstringconsumedApiKeyIdOUTPUT_ONLY; initial API-key UUID, present after consumption. (optional)
CreatedAtDateTimeOffsetcreatedAtOUTPUT_ONLY; enrollment issuance time in milliseconds since epoch.
ConsumedAtDateTimeOffsetconsumedAtOUTPUT_ONLY; first-completion time, absent before consumption. (optional)
RevokedAtDateTimeOffsetrevokedAtOUTPUT_ONLY; permanent revocation time, absent while unrevoked. (optional)
CreatedByIdstringcreatedByIdOUTPUT_ONLY; exact principal or API-key actor that issued the enrollment.
RevokedByIdstringrevokedByIdOUTPUT_ONLY; exact revoking actor UUID, absent while unrevoked. (optional)

ListUsersResponse

One authorization-filtered page of human users.

PropertyTypeJSON (wire)Description
UsersIReadOnlyList<UserResponse>usersOUTPUT_ONLY; users in stable keyset order.
NextTokenstringnextTokenOUTPUT_ONLY; opaque continuation token, omitted after the final page. (optional)

ListUserEnrollmentsResponse

One stable page of a human user's enrollment history.

PropertyTypeJSON (wire)Description
EnrollmentsIReadOnlyList<UserEnrollmentResponse>enrollmentsOUTPUT_ONLY; enrollments ordered newest first.
NextTokenstringnextTokenOUTPUT_ONLY; opaque continuation token, absent after the final page. (optional)

UpdateUserRequest

Updates explicitly present profile fields. Empty username or displayName clears that optional field; an omitted field remains unchanged.

PropertyTypeJSON (wire)Description
EmailstringemailReplacement email. A present empty value is invalid. (optional)
UsernamestringusernameReplacement username. An empty string clears the username. (optional)
DisplayNamestringdisplayNameReplacement display name. An empty string clears the display name. (optional)
ReplaceLabelsIReadOnlyDictionary<string, string>replaceLabelsComplete replacement label map; an empty map clears all labels and is mutually exclusive with mergeLabels. At most 20 entries; keys and values contain at most 255 characters; keys use [a-z0-9._-]. (optional)
MergeLabelsIReadOnlyDictionary<string, string>mergeLabelsLabels to upsert; must contain at least one entry and is mutually exclusive with replaceLabels. The final stored map may contain at most 20 entries; keys and values contain at most 255 characters; keys use [a-z0-9._-]. (optional)