Kyndex
Guides

User Profile

Fetch and update your authenticated user profile. The server stores your display name as an encrypted blob it cannot read.

Two endpoints manage the authenticated user's profile. One fetches it; one updates the encrypted display name. Both require authentication.

For token setup, see Authentication.

Server-Visible vs. Client-Encrypted Fields

The server stores two types of data in your profile:

FieldVisibilityNotes
user_idServer-visibleUUID, used as a stable foreign key
email_encryptedOpaque blobAES-256-GCM ciphertext — server never sees the email address
email_verifiedServer-visibleBoolean flag, not the address itself
key_versionServer-visibleIncrements on credential rotation
created_atServer-visibleAccount creation timestamp
last_login_atServer-visibleLast successful login timestamp
display_name_encryptedOpaque blobAES-256-GCM ciphertext — server never sees the display name

Zero-Knowledge Note: The server cannot read your display name or email address. It stores whatever encrypted blob you send and echoes it back verbatim. Decryption happens on your device using your personal master key (UMK).

GET /v1/users/me

Returns the authenticated user's profile. All encrypted fields are returned as opaque base64 blobs.

Request

curl https://api.kyndex.co/v1/users/me \
  -H 'Authorization: Bearer <access_token>'

Cookie auth is also accepted if you have an active session cookie.

Response

200 OK

{
  "user_id": "d9b7c8a9-e0f1-4627-b3c4-d5e6f7a8b9c0",
  "email_encrypted": "ZW1haWxlbmNyeXB0ZWR3aXRoVU1L",
  "key_version": 0,
  "email_verified": true,
  "created_at": "2026-01-15T10:30:00.000Z",
  "last_login_at": "2026-04-03T08:15:00.000Z",
  "display_name_encrypted": "ZGlzcGxheW5hbWVlbmNyeXB0ZWQ="
}

Response Fields

FieldTypeDescription
user_idstring (UUID)Stable identifier for the authenticated user.
email_encryptedstring (base64)Email address encrypted client-side with UMK. Decrypt locally for display.
key_versionintegerKey rotation epoch. Increments on credential rotation events (e.g. recovery).
email_verifiedbooleanWhether the account's email address has been verified.
created_atstring (ISO 8601)Account creation timestamp.
last_login_atstring (ISO 8601) | nullTimestamp of the most recent successful login. null if no login recorded.
display_name_encryptedstring (base64) | nullAES-256-GCM ciphertext of the display name. null if not yet set. Decrypt with UMK.

PATCH /v1/users/me

Replaces the display_name_encrypted field. This is a replace, not a partial merge — the server overwrites the stored blob with whatever you send.

You encrypt the new display name on your device using AES-256-GCM with your UMK before sending. The server stores the ciphertext as-is.

Request

curl -X PATCH https://api.kyndex.co/v1/users/me \
  -H 'Authorization: Bearer <access_token>' \
  -H 'Content-Type: application/json' \
  -d '{
    "display_name_encrypted": "<base64-AES-GCM-ciphertext>"
  }'

Request Fields

FieldRequiredDescription
display_name_encryptedYesAES-256-GCM ciphertext of the new display name, base64-encoded. Encrypted client-side with your UMK before sending.

Response

200 OK — returns the full updated profile in the same shape as the GET response.

{
  "user_id": "d9b7c8a9-e0f1-4627-b3c4-d5e6f7a8b9c0",
  "email_encrypted": "ZW1haWxlbmNyeXB0ZWR3aXRoVU1L",
  "key_version": 0,
  "email_verified": true,
  "created_at": "2026-01-15T10:30:00.000Z",
  "last_login_at": "2026-04-03T08:15:00.000Z",
  "display_name_encrypted": "<your-new-ciphertext>"
}

Encrypt the display name before sending. Sending plaintext will result in the server storing it verbatim — the server applies no encryption on your behalf. All encryption happens client-side.

Error Responses

All errors follow RFC 9457 Problem Details with Content-Type: application/problem+json.

StatusEndpointWhen
400PATCHRequest body failed validation — display_name_encrypted missing or not valid base64.
401BothExpired or invalid session — re-authenticate.
404BothNo user record found for the authenticated user_id. Should not occur for active accounts.
429BothRate limit exceeded. Back off and retry.
500BothInternal server error. Retry with exponential backoff.
  • Authentication — how to obtain and refresh access tokens.
  • Key Hierarchy — how the UMK protects your display name and email at rest.

On this page