Apikey
gRPC ApiKeyService reference for CreateApiKey, GetApiKey, ListApiKeys, UpdateApiKey and other RPCs, with request messages, response types, and service documentation.
Services
ApiKeyService Service
Service for managing API Keys in the GoodMem system.
Authentication: gRPC metadata x-api-key: <api-key>
Global errors: All RPCs may return DEADLINE_EXCEEDED, CANCELLED, UNAVAILABLE, RESOURCE_EXHAUSTED, INTERNAL.
Authorization model:
- Create, update, and delete RPCs evaluate a typed authorization operation against the target API key and its administrative owner.
- Listing first requires
LIST_API_KEYon the singleton instance, then returns only credentials passingREAD_API_KEYunder the authenticated principal's effective authorization policy.
CreateApiKey
Creates a new API key for an active principal.
| Type | |
|---|---|
| Request | goodmem.v1.CreateApiKeyRequest |
| Response | goodmem.v1.CreateApiKeyResponse |
Auth: gRPC metadata x-api-key: <api-key>
Authorization Required: CREATE_API_KEY on the proposed credential, evaluated using its
proposed administrative owner.
Summary:
- The raw API key is returned ONLY in this response; client MUST save it immediately
- Once the response is processed, the raw key material is never accessible again
- Omitted subject and mode preserve the self-issued human inheriting-key behavior
- SERVICE subjects require
SCOPEDplus a nonempty immutable ceiling - Every ceiling descriptor must be conservatively covered by both the subject's live authority and the issuing credential's effective authority
- A scoped issuing credential may issue only another scoped credential; it cannot mint an inheriting credential that escapes its immutable ceiling
- New keys start in
ACTIVEstatus unless their validity window says otherwise ALREADY_EXISTS: if client-providedapi_key_idis already in use
Side Effects:
- Persists API key; generates cryptographically secure key material; sets audit fields
Error Codes:
UNAUTHENTICATED: missing/invalid authPERMISSION_DENIED: lacks create/subject authority, exceeds the issuing credential's effective authority, or a scoped credential attempts to issue an inheriting credentialINVALID_ARGUMENT: malformed mode, ceiling, validity window, or labelsNOT_FOUND: requested subject or assigned ceiling resource does not existFAILED_PRECONDITION: deleted subject or unsupported subject/mode combinationALREADY_EXISTS: client-providedapi_key_idalready existsINTERNAL: unexpected server error
Idempotency: Non-idempotent; clients SHOULD NOT blindly retry on unknown failures.
Examples:
grpcurl -plaintext \
-H 'x-api-key: gm_xxx' \
-d '{
"labels": {"env": "dev", "service": "backend"}
}' \
localhost:8080 goodmem.v1.ApiKeyService/CreateApiKeyNote: bytes fields in JSON must be base64.
GetApiKey
Retrieves one API key by UUID with its complete immutable ceiling.
| Type | |
|---|---|
| Request | goodmem.v1.GetApiKeyRequest |
| Response | goodmem.v1.GetApiKeyResponse |
Auth: gRPC metadata x-api-key: <api-key>
Authorization Required: READ_API_KEY on the existing credential, evaluated under the
caller's live authority and any scoped-key ceiling.
Response: Complete non-secret metadata with ceiling_omitted=false. Raw and hashed key
material are never returned.
Side Effects: None.
Error Codes:
UNAUTHENTICATED: Missing or invalid authentication.INVALID_ARGUMENT:api_key_idis not one UUID.NOT_FOUND: The credential does not exist. Existence is resolved before authorization.PERMISSION_DENIED: Caller lacks effectiveREAD_API_KEYon the existing credential.INTERNAL: Unexpected authorization or database failure.
Idempotency: Read-only and safe to retry.
ListApiKeys
Lists API keys discoverable to the authenticated principal.
| Type | |
|---|---|
| Request | goodmem.v1.ListApiKeysRequest |
| Response | goodmem.v1.ListApiKeysResponse |
Auth: gRPC metadata x-api-key: <api-key>
Authorization: Requires LIST_API_KEY on the singleton instance. Each returned row must
independently pass READ_API_KEY on that credential. Both gates use the caller's live
authority intersected with any scoped authenticating-key ceiling.
Summary:
- Returns one page of metadata for API keys discoverable to the caller
- Results use stable API-key UUID order
- FULL is the default view and includes complete ceilings; its page size defaults to 10 and may not exceed 20. BASIC omits ceilings, defaults to 50, and may not exceed 1,000.
- Subject, owner, and lifecycle filters are applied in PostgreSQL after authorization and never broaden result visibility.
- Lifecycle is evaluated at current server time independently for each page. Credentials can cross lifecycle boundaries between page requests; clients must tolerate the resulting change in filter membership.
next_tokenis opaque and binds every stable filter, the resolved view, and the complete authentication context. It never accepts a caller-controlled lifecycle evaluation instant.- Raw key material and key hashes are never included in responses
Side Effects: None
Error Codes:
UNAUTHENTICATED: missing/invalid authINVALID_ARGUMENT: malformed UUID filter, unspecified/unknown lifecycle or view, invalid page size for the resolved view, or mismatched/malformed continuation tokenPERMISSION_DENIED: caller lacks effectiveLIST_API_KEYon the singleton instanceINTERNAL: unexpected server error
Idempotency: Read-only; safe to retry; results may change over time.
Examples:
grpcurl -plaintext \
-H 'x-api-key: gm_xxx' \
-d '{}' \
localhost:8080 goodmem.v1.ApiKeyService/ListApiKeysUpdateApiKey
Updates mutable properties of an API key.
| Type | |
|---|---|
| Request | goodmem.v1.UpdateApiKeyRequest |
| Response | goodmem.v1.ApiKey |
Auth: gRPC metadata x-api-key: <api-key>
Permissions Required:
- Label changes require
UPDATE_API_KEY - Setting
status=INACTIVErequiresDELETE_API_KEY - A combined label-and-deactivation request requires both operations
Summary:
- Mutable fields:
status,labels - Immutable fields:
api_key_id,subject_principal_id, key material,created_at, andcreated_by_id - Label updates support replace (clear all, set new) or merge (upsert) strategies
- Revocation is one-way;
status=ACTIVEcannot reactivate an inactive key
Side Effects:
- Persists changes; updates
updated_atandupdated_by_id
Error Codes:
UNAUTHENTICATED: missing/invalid authPERMISSION_DENIED: lacks an operation represented by the requested fieldsINVALID_ARGUMENT: invalidapi_key_idformat; both label strategies set;STATUS_UNSPECIFIEDprovided; no updatable fieldsFAILED_PRECONDITION: attempts to reactivate a revoked keyNOT_FOUND: API key does not existINTERNAL: unexpected server error
Idempotency: Idempotent with identical input; safe to retry.
Examples:
grpcurl -plaintext \
-H 'x-api-key: gm_xxx' \
-d '{
"api_key_id": "BASE64_UUID_BYTES_HERE",
"status": "INACTIVE"
}' \
localhost:8080 goodmem.v1.ApiKeyService/UpdateApiKeyNote: bytes fields in JSON must be base64.
DeleteApiKey
Permanently revokes an API key.
| Type | |
|---|---|
| Request | goodmem.v1.DeleteApiKeyRequest |
| Response | google.protobuf.Empty |
Auth: gRPC metadata x-api-key: <api-key>
Permissions Required: DELETE_API_KEY
Summary:
- This operation is irreversible and immediately invalidates the key
- The durable credential and audit history remain stored
UpdateApiKeywithstatus=INACTIVEperforms the same protected lifecycle transition
Side Effects:
- Records permanent revocation time and actor; invalidates future authentication
Error Codes:
UNAUTHENTICATED: missing/invalid authPERMISSION_DENIED: lacksDELETE_API_KEYINVALID_ARGUMENT: invalidapi_key_idformatNOT_FOUND: API key does not existINTERNAL: unexpected server error
Idempotency: Safe to retry; may return NOT_FOUND if already deleted or never existed.
Examples:
grpcurl -plaintext \
-H 'x-api-key: gm_xxx' \
-d '{ "api_key_id": "BASE64_UUID_BYTES_HERE" }' \
localhost:8080 goodmem.v1.ApiKeyService/DeleteApiKeyNote: bytes fields in JSON must be base64.
Messages
ApiKey
Represents an API key for authenticating requests to the GoodMem service.
API keys authenticate durable HUMAN or SERVICE principals and provide secure, token-based authentication for both gRPC and REST API endpoints. Each key separates its authenticated subject from its administrative owner and immutable issuance authority.
Security:
key_hashand raw key material are never included in API responses.- The raw API key is only returned once during creation via
CreateApiKeyResponse. - Key material is cryptographically hashed using secure algorithms.
- Authentication validates
valid_from,expires_at, and permanent revocation state.
Lifecycle:
- Setting
statustoINACTIVEpermanently revokes a key. DeleteApiKeyperforms the same permanent revocation while retaining durable audit metadata.- Keys automatically become invalid after
expires_at(if set). - Active keys with no expiration remain valid indefinitely.
Immutability:
api_key_idis the immutable primary identifier.- Subject, authority mode, validity window, and ceiling are fixed at issuance and cannot be modified.
Notes:
- All timestamps are UTC (
google.protobuf.Timestamp).
See also: goodmem.v1.ApiKeyStatus
| Field | Type | Description |
|---|---|---|
api_key_id | bytes | OUTPUT_ONLY; immutable primary UUID (16 bytes). |
key_prefix | string | OUTPUT_ONLY; display prefix (format: "gm_" + 6 chars, e.g., "gm_1234ab"). |
status | goodmem.v1.ApiKeyStatus | OUTPUT_ONLY; compatibility usability status. ACTIVE means currently usable; INACTIVE combines not-yet-valid, expired, and revoked credentials. See lifecycle_state for the precise state. |
labels | goodmem.v1.ApiKey.LabelsEntry | OUTPUT_ONLY; at most 20 labels; keys/values at most 255 characters; keys use [a-z0-9._-]. |
expires_at | google.protobuf.Timestamp | OUTPUT_ONLY; exclusive expiration time (UTC), when one is configured. |
last_used_at | google.protobuf.Timestamp | OUTPUT_ONLY; sampled or delayed latest-use time; not updated on every request. |
subject_principal_id | bytes | OUTPUT_ONLY; UUID (16 bytes) of the principal authenticated by this key. |
owner_principal_id | bytes | OUTPUT_ONLY; UUID (16 bytes) of the current administrative owner. |
authority_mode | goodmem.v1.ApiKeyAuthorityMode | OUTPUT_ONLY; immutable authority-derivation mode. |
valid_from | google.protobuf.Timestamp | OUTPUT_ONLY; inclusive lower validity bound. |
revoked_at | google.protobuf.Timestamp | OUTPUT_ONLY; permanent revocation time, when revoked. |
revoked_by_id | bytes | OUTPUT_ONLY; exact audit actor UUID, when revoked. |
ceiling | goodmem.v1.AccessPolicyRule | OUTPUT_ONLY; immutable ceiling. When ceiling_omitted is false, this is nonempty exactly for SCOPED keys. A BASIC list projection intentionally leaves it empty and sets ceiling_omitted. |
lifecycle_state | ...oodmem.v1.ApiKeyLifecycleState | OUTPUT_ONLY; precise lifecycle at the response's evaluation instant. |
ceiling_omitted | bool | OUTPUT_ONLY; true only when a BASIC projection intentionally omitted `ceiling`. When false, SCOPED keys have a nonempty complete ceiling and inheriting keys have an empty ceiling. When true, `ceiling` is empty and clients must not infer whether persisted ceiling rules exist. |
created_at | google.protobuf.Timestamp | OUTPUT_ONLY; creation timestamp (UTC). |
updated_at | google.protobuf.Timestamp | OUTPUT_ONLY; last modification timestamp (UTC). |
created_by_id | bytes | OUTPUT_ONLY; exact creator actor UUID (16 bytes). |
updated_by_id | bytes | OUTPUT_ONLY; exact last-modifier actor UUID (16 bytes). |
ApiKey.LabelsEntry
| Field | Type | Description |
|---|---|---|
key | string | |
value | string |
CreateApiKeyRequest
| Field | Type | Description |
|---|---|---|
api_key_id | bytes | OPTIONAL; client-provided UUID (16 bytes). The server generates one when omitted. |
labels | ...reateApiKeyRequest.LabelsEntry | OPTIONAL; at most 20 labels; keys/values at most 255 characters; keys use [a-z0-9._-]. |
expires_at | google.protobuf.Timestamp | OPTIONAL; exclusive expiration time (UTC). Must be later than valid_from, which defaults to issuance time when omitted. |
subject_principal_id | bytes | OPTIONAL; active HUMAN or SERVICE subject; defaults to the request principal. |
authority_mode | goodmem.v1.ApiKeyAuthorityMode | OPTIONAL; UNSPECIFIED defaults to INHERIT_SUBJECT. A scoped issuer may request only SCOPED. |
ceiling | goodmem.v1.AccessPolicyRule | OPTIONAL; required and nonempty for SCOPED; prohibited for INHERIT_SUBJECT; at most 1,000 rules. Every rule must be covered by both the subject's live authority and the issuer's effective authority. |
valid_from | google.protobuf.Timestamp | OPTIONAL; inclusive activation time; defaults to issuance time. |
CreateApiKeyRequest.LabelsEntry
| Field | Type | Description |
|---|---|---|
key | string | |
value | string |
CreateApiKeyResponse
Response for CreateApiKey containing the one-time raw key.
Security:
raw_api_keyis returned ONLY in this response- Client MUST save the raw key immediately; it cannot be retrieved again
| Field | Type | Description |
|---|---|---|
api_key_metadata | goodmem.v1.ApiKey | OUTPUT_ONLY; created API-key metadata, excluding raw and hashed key material. |
raw_api_key | string | OUTPUT_ONLY; one-time raw API key. The client must save it immediately. |
GetApiKeyRequest
Request to retrieve one API-key resource by UUID.
| Field | Type | Description |
|---|---|---|
api_key_id | bytes | REQUIRED; UUID (16 bytes) of the credential to retrieve. |
GetApiKeyResponse
Response containing complete non-secret API-key metadata.
| Field | Type | Description |
|---|---|---|
api_key | goodmem.v1.ApiKey | OUTPUT_ONLY; requested credential with ceiling_omitted=false. |
ListApiKeysRequest
| Field | Type | Description |
|---|---|---|
max_results | int32 | OPTIONAL; FULL defaults to 10 and permits at most 20; BASIC defaults to 50 and permits 1,000. |
next_token | string | OPTIONAL; opaque token returned by the preceding page. Do not construct or parse it. |
subject_principal_id | bytes | OPTIONAL; exact subject-principal UUID filter. An absent principal produces an empty page. |
owner_principal_id | bytes | OPTIONAL; exact administrative-owner UUID filter. An absent principal produces an empty page. |
lifecycle_state | ...oodmem.v1.ApiKeyLifecycleState | OPTIONAL; precise lifecycle at the current page's server-selected evaluation instant. An explicitly supplied UNSPECIFIED value is invalid; omission includes every lifecycle state. |
view | goodmem.v1.ApiKeyView | OPTIONAL; response projection. Omission defaults to FULL; explicitly supplied UNSPECIFIED is invalid. |
ListApiKeysResponse
| Field | Type | Description |
|---|---|---|
keys | goodmem.v1.ApiKey | OUTPUT_ONLY; one stable UUID-ordered page; raw key material is never included. |
next_token | string | OUTPUT_ONLY; opaque continuation token, absent after the final page. |
ListApiKeysNextPageToken
Opaque API-key page cursor encoded and validated by the server.
| Field | Type | Description |
|---|---|---|
requestor_id | bytes | |
authenticating_api_key_id | bytes | |
last_api_key_id | bytes | |
subject_principal_id | bytes | |
owner_principal_id | bytes | |
lifecycle_state | ...oodmem.v1.ApiKeyLifecycleState | |
view | goodmem.v1.ApiKeyView |
UpdateApiKeyRequest
| Field | Type | Description |
|---|---|---|
api_key_id | bytes | REQUIRED; UUID (16 bytes) of the key to update. |
replace_labels | goodmem.v1.StringMap | OPTIONAL; replaces all labels. An empty StringMap clears all labels. The replacement may contain at most 20 entries; keys/values may contain at most 255 characters; keys use [a-z0-9._-]. See: goodmem.v1.StringMap |
merge_labels | goodmem.v1.StringMap | OPTIONAL; upserts labels with overwrite while preserving unmentioned labels. The final stored map may contain at most 20 entries; keys/values may contain at most 255 characters; keys use [a-z0-9._-]. See: goodmem.v1.StringMap |
status | goodmem.v1.ApiKeyStatus | OPTIONAL; status mutation. UNSPECIFIED is rejected; omission preserves status. |
DeleteApiKeyRequest
| Field | Type | Description |
|---|---|---|
api_key_id | bytes | REQUIRED; UUID (16 bytes) of the key to revoke permanently. |
Enums
ApiKeyStatus
API key status for lifecycle management.
STATUS_UNSPECIFIED= 0: Invalid status; never used in practiceACTIVE= 1: Key is valid and can be used for authenticationINACTIVE= 2: Key cannot authenticate at the response evaluation instant because it is not yet valid, has expired, or was permanently revoked
| Name | Value | Description |
|---|---|---|
STATUS_UNSPECIFIED | 0 | Invalid status; `INVALID_ARGUMENT` on writes |
ACTIVE | 1 | Key is valid and can be used for authentication |
INACTIVE | 2 | Key cannot authenticate now: scheduled, expired, or permanently revoked |
ApiKeyLifecycleState
Precise API-key lifecycle derived at one server-selected evaluation instant.
Precedence is REVOKED, then NOT_YET_VALID, then EXPIRED, then USABLE. valid_from is
inclusive and expires_at is exclusive. This enum supplements the compatibility ApiKeyStatus,
whose INACTIVE value combines every currently unusable state.
| Name | Value | Description |
|---|---|---|
API_KEY_LIFECYCLE_STATE_UNSPECIFIED | 0 | |
API_KEY_LIFECYCLE_STATE_NOT_YET_VALID | 1 | |
API_KEY_LIFECYCLE_STATE_USABLE | 2 | |
API_KEY_LIFECYCLE_STATE_EXPIRED | 3 | |
API_KEY_LIFECYCLE_STATE_REVOKED | 4 |
ApiKeyView
Metadata projection returned by ListApiKeys.
| Name | Value | Description |
|---|---|---|
API_KEY_VIEW_UNSPECIFIED | 0 | Invalid when explicitly supplied. An omitted view defaults to FULL. |
API_KEY_VIEW_FULL | 1 | Complete metadata, including the immutable scoped-key ceiling. |
API_KEY_VIEW_BASIC | 2 | Lean metadata with the ceiling deliberately omitted. |
ApiKeyAuthorityMode
Determines how an API key derives its effective authorization.
An inheriting key follows the live authority of its HUMAN subject. A scoped key intersects the subject's live authority with the immutable, nonempty ceiling selected when the key is issued.
| Name | Value | Description |
|---|---|---|
API_KEY_AUTHORITY_MODE_UNSPECIFIED | 0 | Create defaults to INHERIT_SUBJECT for compatibility. |
API_KEY_AUTHORITY_MODE_INHERIT_SUBJECT | 1 | |
API_KEY_AUTHORITY_MODE_SCOPED | 2 |