Apikey
Apikey service API reference
Services
ApiKeyService Service
Service for managing API Keys in the GoodMem system.
Authentication: gRPC metadata authorization: Bearer <api-key>
Global errors: All RPCs may return DEADLINE_EXCEEDED, CANCELLED, UNAVAILABLE, RESOURCE_EXHAUSTED, INTERNAL.
Permissions model:
*_APIKEY_OWN: operate on caller-owned API keys*_APIKEY_ANY: operate on any user's API keys (requires elevated role)
CreateApiKey
Creates a new API key for the authenticated user.
| Type | |
|---|---|
| Request | goodmem.v1.CreateApiKeyRequest |
| Response | goodmem.v1.CreateApiKeyResponse |
Auth: gRPC metadata authorization: Bearer <api-key>
Permissions Required: CREATE_APIKEY_OWN or CREATE_APIKEY_ANY
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
- New keys start in
ACTIVEstatus 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: lacksCREATE_APIKEY_*INVALID_ARGUMENT:expires_atin the past; labels exceed limits or contain invalid charactersALREADY_EXISTS: client-providedapi_key_idalready existsINTERNAL: unexpected server error
Idempotency: Non-idempotent; clients SHOULD NOT blindly retry on unknown failures.
Examples:
grpcurl -plaintext \
-H 'authorization: Bearer gm_xxx' \
-d '{
"labels": {"env": "dev", "service": "backend"}
}' \
localhost:8080 goodmem.v1.ApiKeyService/CreateApiKeyNote: bytes fields in JSON must be base64.
ListApiKeys
Lists API keys belonging to the authenticated user.
| Type | |
|---|---|
| Request | goodmem.v1.ListApiKeysRequest |
| Response | goodmem.v1.ListApiKeysResponse |
Auth: gRPC metadata authorization: Bearer <api-key>
Permissions Required: LIST_APIKEY_OWN or LIST_APIKEY_ANY
Summary:
- Returns metadata for all API keys owned by the caller
- Raw key material and key hashes are never included in responses
- With
LIST_APIKEY_ANY, returns all keys in the system
Side Effects: None
Error Codes:
UNAUTHENTICATED: missing/invalid authPERMISSION_DENIED: lacksLIST_APIKEY_*INTERNAL: unexpected server error
Idempotency: Read-only; safe to retry; results may change over time.
Examples:
grpcurl -plaintext \
-H 'authorization: Bearer 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 authorization: Bearer <api-key>
Permissions Required: UPDATE_APIKEY_OWN or UPDATE_APIKEY_ANY
Summary:
- Mutable fields:
status,labels - Immutable fields:
api_key_id,user_id, key material,created_at,created_by_id - Label updates support replace (clear all, set new) or merge (upsert) strategies
Side Effects:
- Persists changes; updates
updated_atandupdated_by_id
Error Codes:
UNAUTHENTICATED: missing/invalid authPERMISSION_DENIED: lacksUPDATE_APIKEY_*INVALID_ARGUMENT: invalidapi_key_idformat; both label strategies set;STATUS_UNSPECIFIEDprovided; no updatable fieldsNOT_FOUND: API key does not existINTERNAL: unexpected server error
Idempotency: Idempotent with identical input; safe to retry.
Examples:
grpcurl -plaintext \
-H 'authorization: Bearer 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 deletes an API key.
| Type | |
|---|---|
| Request | goodmem.v1.DeleteApiKeyRequest |
| Response | google.protobuf.Empty |
Auth: gRPC metadata authorization: Bearer <api-key>
Permissions Required: DELETE_APIKEY_OWN or DELETE_APIKEY_ANY
Summary:
- This operation is irreversible and immediately invalidates the key
- Use
UpdateApiKeywithstatus=INACTIVEfor reversible deactivation
Side Effects:
- Permanently removes the API key record; invalidates key for all future authentication
Error Codes:
UNAUTHENTICATED: missing/invalid authPERMISSION_DENIED: lacksDELETE_APIKEY_*INVALID_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 'authorization: Bearer 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 are scoped to individual users and provide secure, token-based authentication for both gRPC and REST API endpoints. Each key includes metadata for identification and management, while the actual key material is securely hashed and stored separately.
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 both
status=ACTIVEandexpires_at(if set).
Lifecycle:
- Keys can be disabled by setting
statustoINACTIVE(reversible). - Keys can be permanently deleted using
DeleteApiKey(irreversible). - 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.user_idis set at creation 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 UUID (16 bytes); immutable primary identifier |
user_id | bytes | OUTPUT_ONLY UUID (16 bytes); owner of this key; immutable after creation |
key_prefix | string | OUTPUT_ONLY display prefix (format: "gm_" + 6 chars, e.g., "gm_1234ab") |
status | goodmem.v1.ApiKeyStatus | REQUIRED; current lifecycle status. See: goodmem.v1.ApiKeyStatus |
labels | goodmem.v1.ApiKey.LabelsEntry | OPTIONAL; ≤20 entries; keys/values ≤255 chars; keys [a-z0-9._-], case-sensitive |
expires_at | google.protobuf.Timestamp | OPTIONAL expiration time (UTC); if set, key becomes invalid after this time |
last_used_at | google.protobuf.Timestamp | OUTPUT_ONLY; may be sampled/delayed; not updated on every request |
created_at | google.protobuf.Timestamp | OUTPUT_ONLY creation timestamp (UTC). See: `google.protobuf.Timestamp` |
updated_at | google.protobuf.Timestamp | OUTPUT_ONLY last modification timestamp (UTC). See: `google.protobuf.Timestamp` |
created_by_id | bytes | OUTPUT_ONLY creator user UUID (16 bytes); typically the key owner |
updated_by_id | bytes | OUTPUT_ONLY last modifier user UUID (16 bytes); derived from auth context on update |
ApiKey.LabelsEntry
| Field | Type | Description |
|---|---|---|
key | string | |
value | string |
CreateApiKeyRequest
| Field | Type | Description |
|---|---|---|
api_key_id | bytes | Optional client-provided UUID (16 bytes); server generates if omitted; returns ALREADY_EXISTS if ID exists |
labels | ...reateApiKeyRequest.LabelsEntry | Optional labels (≤20 entries; keys/values ≤255 chars; keys [a-z0-9._-], case-sensitive) |
expires_at | google.protobuf.Timestamp | Optional expiration (UTC); `INVALID_ARGUMENT` if in the past |
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 | The created API key metadata (excludes raw key material and hash) |
raw_api_key | string | The actual generated API key; client MUST save this immediately |
ListApiKeysRequest
Future: user_id filter for admins with LIST_APIKEY_ANY permission
ListApiKeysResponse
| Field | Type | Description |
|---|---|---|
keys | goodmem.v1.ApiKey | List of API keys (metadata only; raw key material never included) |
UpdateApiKeyRequest
| Field | Type | Description |
|---|---|---|
api_key_id | bytes | Required: ID of the key to update (16 bytes UUID) |
replace_labels | goodmem.v1.StringMap | Replace all existing labels with this set. Empty StringMap clears all labels. See: goodmem.v1.StringMap |
merge_labels | goodmem.v1.StringMap | Merge with existing labels: upserts with overwrite. Labels not mentioned are preserved. See: goodmem.v1.StringMap |
status | goodmem.v1.ApiKeyStatus | Optional fields to update (if omitted → unchanged) Update status; `STATUS_UNSPECIFIED` → `INVALID_ARGUMENT`. See: goodmem.v1.ApiKeyStatus |
DeleteApiKeyRequest
| Field | Type | Description |
|---|---|---|
api_key_id | bytes | Required: ID of the key to delete (16 bytes UUID) |
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 is disabled and cannot be used for authentication (reversible revocation)
| 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 is disabled; authentication attempts are rejected |