API Keys
API key lifecycle — create, list, update, soft-delete.
Namespace: Goodmem.Client.Api · Class: ApiKeysApi
Reach this surface as client.ApiKeys 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
| Method | Summary |
|---|---|
CreateAsync | Create a new API key. |
ListAsync | List API keys. |
UpdateAsync | Update an API key. |
DeleteAsync | Delete an API key. |
CreateAsync
Creates a new API key for authenticating with the API. New keys start in ACTIVE status and can be used immediately for authentication. The response includes the one-time raw API key value which will not be retrievable later - clients must save this value as it cannot be recovered. Requires CREATE_APIKEY_OWN permission (or CREATE_APIKEY_ANY for admin users). Side effects include generating cryptographically secure key material, recording creation timestamp, and tracking creator ID. Returns INVALID_ARGUMENT if expires_at is set to a time in the past.
Declaration
public Task<CreateApiKeyResponse> CreateAsync(CreateApiKeyRequest request, CancellationToken ct = default)
HTTP — POST /v1/apikeys
Parameters
| Type | Name | Description |
|---|---|---|
CreateApiKeyRequest | request | The request payload; the linked model lists every field and its JSON wire name. |
CancellationToken | ct | Cancellation / deadline signal for the call. (optional) |
Returns
Task<CreateApiKeyResponse> — an awaitable that resolves to CreateApiKeyResponse.
Exceptions
| Type | Condition |
|---|---|
ArgumentNullException | request is null. |
NetworkException | The request could not reach the server (DNS, connection, or TLS failure). |
ApiException | The 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 key = await client.ApiKeys.CreateAsync(
new CreateApiKeyRequest
{
Labels = new Dictionary<string, string>
{
["env"] = "docs",
["purpose"] = "sdk-doc-test",
},
}
);
Console.WriteLine(key.RawApiKey); // returned only once, at creationListAsync
Retrieves a list of API keys belonging to the authenticated user. The list includes metadata about each key but not the actual key values or key hashes for security reasons. Requires LIST_APIKEY_OWN permission (or LIST_APIKEY_ANY for admin users to view keys from any user). This is a read-only operation with no side effects.
Declaration
public Task<ListApiKeysResponse> ListAsync(CancellationToken ct = default)
HTTP — GET /v1/apikeys
Parameters
| Type | Name | Description |
|---|---|---|
CancellationToken | ct | Cancellation / deadline signal for the call. (optional) |
Returns
Task<ListApiKeysResponse> — an awaitable that resolves to ListApiKeysResponse.
Exceptions
| Type | Condition |
|---|---|
NetworkException | The request could not reach the server (DNS, connection, or TLS failure). |
ApiException | The 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 resp = await client.ApiKeys.ListAsync();
foreach (var key in resp.Keys)
Console.WriteLine($"{key.ApiKeyId} {key.Status}");UpdateAsync
Updates an existing API key with new values for status or labels. IMPORTANT: Key ID, user ownership, key material, and audit fields cannot be modified - only status (ACTIVE/INACTIVE) and labels are mutable. Requires UPDATE_APIKEY_OWN permission for keys you own (or UPDATE_APIKEY_ANY for admin users to modify any user's keys). Side effects include updating the updated_at timestamp and recording the updater's user ID. This operation is idempotent - repeated identical requests have no additional effect.
Declaration
public Task<ApiKeyResponse> UpdateAsync(string id, UpdateApiKeyRequest request, CancellationToken ct = default)
HTTP — PUT /v1/apikeys/{id}
Parameters
| Type | Name | Description |
|---|---|---|
string | id | The UUID of the API key to update |
UpdateApiKeyRequest | request | The request payload; the linked model lists every field and its JSON wire name. |
CancellationToken | ct | Cancellation / deadline signal for the call. (optional) |
Returns
Task<ApiKeyResponse> — an awaitable that resolves to ApiKeyResponse.
Exceptions
| Type | Condition |
|---|---|
ArgumentException | id is null or empty. |
ArgumentNullException | request is null. |
NetworkException | The request could not reach the server (DNS, connection, or TLS failure). |
ApiException | The 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 updated = await client.ApiKeys.UpdateAsync(
"your-api-key-id",
new UpdateApiKeyRequest
{
MergeLabels = new Dictionary<string, string> { ["updated"] = "true" },
}
);
Console.WriteLine(updated.ApiKeyId);DeleteAsync
Delete an API key
Permanently deletes an API key. This operation cannot be undone and immediately invalidates the key for all future authentication attempts. TIP: For reversible deactivation, use PUT /v1/apikeys/{id} with status=INACTIVE instead. Requires DELETE_APIKEY_OWN permission for keys you own (or DELETE_APIKEY_ANY for admin users to delete any user's keys). Side effects include permanently removing the key record from the database and immediate authentication invalidation.
Declaration
public Task DeleteAsync(string id, CancellationToken ct = default)
HTTP — DELETE /v1/apikeys/{id}
Parameters
| Type | Name | Description |
|---|---|---|
string | id | The UUID of the API key to delete |
CancellationToken | ct | Cancellation / deadline signal for the call. (optional) |
Returns
Task — completes when the operation finishes; there is no response body.
Exceptions
| Type | Condition |
|---|---|
ArgumentException | id is null or empty. |
NetworkException | The request could not reach the server (DNS, connection, or TLS failure). |
ApiException | The 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.ApiKeys.DeleteAsync("your-api-key-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.
CreateApiKeyRequest
Request parameters for creating a new API key.
| Property | Type | JSON (wire) | Description |
|---|---|---|---|
Labels | IReadOnlyDictionary<string, string> | labels | Key-value pairs of metadata associated with the API key. Used for organization and filtering. (optional) |
ExpiresAt | DateTimeOffset | expiresAt | Expiration timestamp in milliseconds since epoch. If not provided, the key does not expire. (optional) |
ApiKeyId | string | apiKeyId | Optional client-provided UUID for idempotent creation. If not provided, server generates a new UUID. Returns ALREADY_EXISTS if ID is already in use. (optional) |
CreateApiKeyResponse
Response returned when creating a new API key.
| Property | Type | JSON (wire) | Description |
|---|---|---|---|
ApiKeyMetadata | ApiKeyResponse | apiKeyMetadata | Metadata for the created API key. (optional) |
RawApiKey | string | rawApiKey | The actual API key value. This is only returned once and cannot be retrieved again. (optional) |
ApiKeyResponse
API key metadata without sensitive information.
| Property | Type | JSON (wire) | Description |
|---|---|---|---|
ApiKeyId | string | apiKeyId | Unique identifier for the API key. |
UserId | string | userId | ID of the user that owns this API key. |
KeyPrefix | string | keyPrefix | First few characters of the key for display/identification purposes. |
Status | string | status | Current status of the API key: ACTIVE, INACTIVE, or STATUS_UNSPECIFIED. |
Labels | IReadOnlyDictionary<string, string> | labels | User-defined labels for organization and filtering. |
ExpiresAt | DateTimeOffset | expiresAt | Expiration timestamp in milliseconds since epoch. If not provided, the key does not expire. (optional) |
LastUsedAt | DateTimeOffset | lastUsedAt | Last time this API key was used, in milliseconds since epoch. (optional) |
CreatedAt | DateTimeOffset | createdAt | When the API key was created, in milliseconds since epoch. |
UpdatedAt | DateTimeOffset | updatedAt | When the API key was last updated, in milliseconds since epoch. |
CreatedById | string | createdById | ID of the user that created this API key. |
UpdatedById | string | updatedById | ID of the user that last updated this API key. |
ListApiKeysResponse
Response containing a list of API keys.
| Property | Type | JSON (wire) | Description |
|---|---|---|---|
Keys | IReadOnlyList<ApiKeyResponse> | keys | List of API keys belonging to the authenticated user. |
UpdateApiKeyRequest
Request parameters for updating an API key.
| Property | Type | JSON (wire) | Description |
|---|---|---|---|
Status | string | status | New status for the API key. Allowed values: ACTIVE, INACTIVE. (optional) |
ReplaceLabels | IReadOnlyDictionary<string, string> | replaceLabels | Replace all existing labels with this set. Mutually exclusive with mergeLabels. (optional) |
MergeLabels | IReadOnlyDictionary<string, string> | mergeLabels | Merge these labels with existing ones. Mutually exclusive with replaceLabels. (optional) |