GoodMemGoodMem

API Keys

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

Methods on this page are called as client.apikeys.<method>(...) where client is either a synchronous Goodmem or asynchronous AsyncGoodmem instance initialized below:

from goodmem import Goodmem
client = Goodmem(base_url='http://localhost:8080', api_key='gm_...')
from goodmem import AsyncGoodmem
client = AsyncGoodmem(base_url='http://localhost:8080', api_key='gm_...')

Create a new API key

apikeys.create(*, api_key_id: str = None, authority_mode: ApiKeyAuthorityMode = None, ceiling: list[AccessPolicyRule] = None, expires_at: int = None, labels: dict[str, str] = None, subject_principal_id: str = None, valid_from: int = None) → CreateApiKeyResponse

Issues a new API key and returns its raw value exactly once. Omitted subject and authority_mode 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.

Parameters:

  • api_key_id (str, format: uuid, optional) — Optional client-provided UUID for idempotent creation. If not provided, server generates a new UUID. Returns ALREADY_EXISTS if ID is already in use.
  • authority_mode (ApiKeyAuthorityMode, optional, server default='INHERIT_SUBJECT') — Authority mode. Omit to create a self-issued human key that inherits live authority. A scoped issuing credential may create only SCOPED children.
  • ceiling (list[AccessPolicyRule], optional) — Immutable 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.
  • expires_at (int, format: int64, optional) — Exclusive expiration timestamp in milliseconds since epoch. It must be later than valid_from, which defaults to issuance time; if omitted, the key does not expire.
  • labels (dict[str, str], optional) — Key-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._-].
  • subject_principal_id (str, format: uuid, optional) — Principal authenticated by this key. Omit to use the authenticated principal.
  • valid_from (int, format: int64, optional) — Inclusive activation time in epoch milliseconds. Omit to activate at issuance time.

Returns:

CreateApiKeyResponse

Raises:

  • PermissionDeniedError — The caller lacks the permission the operation requires.
  • ConflictError — The resource already exists or conflicts with existing state.
  • APIError — Any other non-2xx HTTP response (base class; exposes status_code and body).

Example

key = client.apikeys.create(
    labels={"env": "docs", "purpose": "sdk-doc-test"},
)


Get an API key

apikeys.get(*, id: str) → ApiKeyResponse

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

Parameters:

  • id (str) — API-key UUID

Returns:

ApiKeyResponse — Returns the API key metadata.

Raises:

  • APIError — Any other non-2xx HTTP response (base class; exposes status_code and body).

Example

key = client.apikeys.get(id="your-api-key-id")
print(key.api_key_id, key.lifecycle_state)

List API keys

apikeys.list(*, lifecycle_state: str = None, max_results: int = None, next_token: str = None, owner_principal_id: str = None, subject_principal_id: str = None, view: str = None) → Page[ApiKeyResponse]

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 ceiling_omitted=true, and permits larger pages. Raw key values and key hashes are never returned.

Parameters:

  • lifecycle_state (str, optional) — Filter by precise lifecycle state
  • max_results (int, format: int32, optional) — Page size; FULL defaults to 10 and permits at most 20, while BASIC defaults to 50 and permits at most 1,000
  • next_token (str, optional) — Opaque continuation token returned by the preceding page
  • owner_principal_id (str, optional) — Filter by exact administrative-owner UUID
  • subject_principal_id (str, optional) — Filter by exact subject-principal UUID
  • view (str, optional, server default='FULL') — Metadata projection; omission defaults to FULL

Returns:

Page[ApiKeyResponse]

Raises:

  • PermissionDeniedError — The caller lacks the permission the operation requires.
  • APIError — Any other non-2xx HTTP response (base class; exposes status_code and body).

Example

for key in client.apikeys.list():
    print(key.api_key_id, key.status)


Update an API key

apikeys.update(*, id: str, request: UpdateApiKeyRequest | dict) → ApiKeyResponse

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.

Parameters:

  • id (str) — The unique identifier of the resource to update.
  • request (UpdateApiKeyRequest | dict) — The update payload. Accepts a UpdateApiKeyRequest instance or a plain dict with the same fields. Only specified fields will be modified.

Returns:

ApiKeyResponse — Returns the API key metadata.

Raises:

  • PermissionDeniedError — The caller lacks the permission the operation requires.
  • APIError — Any other non-2xx HTTP response (base class; exposes status_code and body).

Example

from goodmem.types import UpdateApiKeyRequest
# Option 1: typed request object
updated = client.apikeys.update(id="your-api-key-id", request=UpdateApiKeyRequest(
    merge_labels={"updated": "true"},
))
assert updated.api_key_id == "your-api-key-id"
# Option 2: plain dict (validated via pydantic)
updated = client.apikeys.update(id="your-api-key-id", request={
    "merge_labels": {"updated": "true"},
})
assert updated.api_key_id == "your-api-key-id"


Delete an API key

apikeys.delete(*, id: str) → None

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.

Parameters:

  • id (str) — The UUID of the API key to delete

Returns:

None

Raises:

  • PermissionDeniedError — The caller lacks the permission the operation requires.
  • APIError — Any other non-2xx HTTP response (base class; exposes status_code and body).

Example

client.apikeys.delete(id="your-api-key-id")


Async usage: client.apikeys exposes the same methods on AsyncGoodmem; use await / async for as needed.


Data Models

All data models are pydantic v2 models. Fields are shown with their Python attribute names; JSON responses use camelCase aliases (e.g., owner_idownerId).

CreateApiKeyResponse

Response returned when creating a new API key.

  • api_key_metadata (ApiKeyResponse, optional) — Metadata for the created API key.
  • raw_api_key (str, optional) — The actual API key value. This is only returned once and cannot be retrieved again.

UpdateApiKeyRequest

Request parameters for updating an API key.

  • status (Literal['ACTIVE', 'INACTIVE'], optional) — New status for the API key. INACTIVE is permanent; revoked keys cannot be reactivated.
  • replace_labels (dict[str, str], optional) — Replace all existing labels with this set. Mutually exclusive with merge_labels. The stored map may contain at most 20 entries; keys and values contain at most 255 characters; keys use [a-z0-9._-].
  • merge_labels (dict[str, str], optional) — Merge these labels with existing ones. Mutually exclusive with replace_labels. The final stored map may contain at most 20 entries; keys and values contain at most 255 characters; keys use [a-z0-9._-].