GoodMemGoodMem
ReferenceClient SDKs.NET

API Keys

.NET SDK reference for API keys: creation, lookup, listing, updates, and deletion.

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

MethodSummary
CreateAsyncCreate a new API key.
GetAsyncGet an API key.
ListAsyncList API keys.
UpdateAsyncUpdate an API key.
DeleteAsyncDelete an API key.

CreateAsync

Issues a new API key and returns its raw value exactly once. Omitted subject and authorityMode create a self-issued human key that inherits the subject's live authority. A SCOPED key requires a nonempty immutable ceiling, and every ceiling rule must be conservatively covered by both the subject's live authority and the issuing credential's effective authority. A scoped issuer can create only scoped children. SERVICE subjects require SCOPED mode and MANAGE_ACCESS on the service identity.

AUTHORIZATION: Requires CREATE_API_KEY on the proposed credential; subject and ceiling checks are repeated by the final insertion statement.

Declaration

public Task<CreateApiKeyResponse> CreateAsync(CreateApiKeyRequest request, CancellationToken ct = default)

HTTPPOST /v1/apikeys

Parameters

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

Returns

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

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 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 creation


GetAsync

Returns complete non-secret metadata for one existing credential after requiring effective READ_API_KEY authority. The immutable ceiling is always complete and ceilingOmitted is false. Raw key material and hashes are never returned.

Declaration

public Task<ApiKeyResponse> GetAsync(string id, CancellationToken ct = default)

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

Parameters

TypeNameDescription
stringidAPI-key UUID
CancellationTokenctCancellation / deadline signal for the call. (optional)

Returns

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

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

var key = await client.ApiKeys.GetAsync("your-api-key-id");
Console.WriteLine($"{key.ApiKeyId} {key.LifecycleState}");


ListAsync

Requires LIST_API_KEY on the singleton instance, then retrieves one UUID-ordered page containing only credentials that independently pass READ_API_KEY. Both gates use the authenticated principal's live authority and any scoped-key ceiling. Subject, owner, and lifecycle filters are applied after authorization. FULL includes complete immutable ceilings; BASIC omits them, sets ceilingOmitted=true, and permits larger pages. Raw key values and key hashes are never returned.

Declaration

public IAsyncEnumerable<ApiKeyResponse> ListAsync(ApiKeysListOptions? options = null, CancellationToken ct = default)

HTTPGET /v1/apikeys

Parameters

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

Returns

IAsyncEnumerable<ApiKeyResponse> — an async stream; await foreach yields each ApiKeyResponse 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 key in client.ApiKeys.ListAsync())
    Console.WriteLine($"{key.ApiKeyId} {key.Status}");


UpdateAsync

Updates an existing API key's labels or lifecycle status. Key ID, subject, ownership, key material, validity window, and creation audit fields remain immutable. Label changes require UPDATE_API_KEY; setting status=INACTIVE permanently revokes the key and requires DELETE_API_KEY; a request doing both requires both operations. Revoked keys cannot be reactivated. Side effects include updating administrative audit fields and, for revocation, recording the revocation time and actor.

Declaration

public Task<ApiKeyResponse> UpdateAsync(string id, UpdateApiKeyRequest request, CancellationToken ct = default)

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

Parameters

TypeNameDescription
stringidThe UUID of the API key to update
UpdateApiKeyRequestrequestThe request payload; the linked model lists every field and its JSON wire name.
CancellationTokenctCancellation / deadline signal for the call. (optional)

Returns

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

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 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 revokes an API key and immediately rejects it for future authentication. The durable credential and audit history remain stored. This operation requires DELETE_API_KEY and records the revocation time and actor; it cannot be undone. PUT /v1/apikeys/{id} with status=INACTIVE performs the same permanent revocation.

Declaration

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

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

Parameters

TypeNameDescription
stringidThe UUID of the API key to delete
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.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.

PropertyTypeJSON (wire)Description
LabelsIReadOnlyDictionary<string, string>labelsKey-value pairs of metadata associated with the API key. Used for organization and filtering. At most 20 entries; keys and values contain at most 255 characters; keys use [a-z0-9._-]. (optional)
ExpiresAtDateTimeOffsetexpiresAtExclusive expiration timestamp in milliseconds since epoch. It must be later than validFrom, which defaults to issuance time; if omitted, the key does not expire. (optional)
ApiKeyIdstringapiKeyIdOptional client-provided UUID for idempotent creation. If not provided, server generates a new UUID. Returns ALREADY_EXISTS if ID is already in use. (optional)
SubjectPrincipalIdstringsubjectPrincipalIdPrincipal authenticated by this key. Omit to use the authenticated principal. (optional)
AuthorityModeApiKeyAuthorityModeauthorityModeAuthority mode. Omit to create a self-issued human key that inherits live authority. A scoped issuing credential may create only SCOPED children. (optional)
CeilingIReadOnlyList<AccessPolicyRule>ceilingImmutable authorization ceiling. Required and nonempty for SCOPED; omitted for INHERIT_SUBJECT, with at most 1,000 rules. Every rule must be covered by both the subject's live authority and the issuing credential's effective authority. (optional)
ValidFromDateTimeOffsetvalidFromInclusive activation time in epoch milliseconds. Omit to activate at issuance time. (optional)

CreateApiKeyResponse

Response returned when creating a new API key.

PropertyTypeJSON (wire)Description
ApiKeyMetadataApiKeyResponseapiKeyMetadataMetadata for the created API key. (optional)
RawApiKeystringrawApiKeyThe actual API key value. This is only returned once and cannot be retrieved again. (optional)

ListApiKeysResponse

One page of API keys discoverable to the authenticated principal.

PropertyTypeJSON (wire)Description
KeysIReadOnlyList<ApiKeyResponse>keysAPI keys in stable UUID order.
NextTokenstringnextTokenOpaque token for retrieving the next page; omitted on the last page. (optional)

UpdateApiKeyRequest

Request parameters for updating an API key.

PropertyTypeJSON (wire)Description
StatusstringstatusNew status for the API key. INACTIVE is permanent; revoked keys cannot be reactivated. (optional)
ReplaceLabelsIReadOnlyDictionary<string, string>replaceLabelsReplace all existing labels with this set. Mutually exclusive with mergeLabels. The stored map may contain at most 20 entries; keys and values contain at most 255 characters; keys use [a-z0-9._-]. (optional)
MergeLabelsIReadOnlyDictionary<string, string>mergeLabelsMerge these labels with existing ones. 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)