The User Profile Management API covers four areas of per-account functionality: retrieving and updating a user profile, inspecting per-account activity logs (including usage stats), checking and claiming beta free-tier server entitlement, and managing the encrypted user vault. Use these endpoints whenever you need to read a profile, modify account fields (alias, password, public key), audit request history, gate new server claims on invite codes, or store and retrieve secrets per-user or per-realm.
Authentication is a JWT in the Authorization header as Bearer <token> (or an auth token with the appropriate permissions). Note that tokens lacking the resources.read_account permission receive a reduced profile response in which email and other account PII are omitted.
Retrieve a user profile by ID. Admins can view any user; regular users can only view their own profile. This endpoint works even for banned users (read-only access). When authenticated with an auth token that lacks the resources.read_account permission, the response is reduced to identity fields; email and other account PII are omitted.
Update a user profile. Regular users can update their own alias and password (with current_password verification). Admins can update any user and set is_admin / is_banned flags. When authenticated with an auth token that lacks the resources.read_account permission, the returned profile is reduced to identity fields; email and other account PII are omitted.
Idempotently records a per-account onboarding/UI milestone (key -> ISO timestamp). Used by the /auth/home first-run tour (milestone hub_tour_v1) and reusable for any future onboarding step. Setting an already-present milestone is a no-op (the original timestamp is kept).
Returns whether the beta gate is enabled, whether this account is unlocked, whether it already owns a free server, and an advisory, point-in-time reason a claim is currently blocked. Never attempts a claim. Auth-token callers must hold the resources.read_account permission (account-level status); tokens without it receive 403. JWT/owner callers are unaffected.
The claim_blocked_reason field is an advisory snapshot and follows the priority: already_claimed -> invite_required -> pool_empty -> none. The signup_code_failed flag is true only while invite_required AND the invite code memorized from the signup link definitively failed to redeem (already used, disabled, expired, or unknown) — the UI should explain the dead link and offer manual entry.
{
"statusCode":401,
"error":"Unauthorized",
"message":"Authentication token required"
}
Error Code
Title
Description
Resolution
MISSING_TOKEN
Authentication token missing
No authentication token was provided in the request
Include a valid JWT token in the Authorization header as Bearer <token>
INVALID_TOKEN
Invalid authentication token
The provided authentication token is malformed or invalid
Obtain a new token by logging in again or using a valid auth token
{
"statusCode":403,
"error":"Forbidden",
"message":"Insufficient permissions"
}
Error Code
Title
Description
Resolution
INSUFFICIENT_PERMISSIONS
Insufficient permissions
You do not have the required permissions to perform this action
Contact the resource owner or administrator to request access
{
"statusCode":429,
"error":"Too Many Requests",
"message":"Rate limit exceeded"
}
Error Code
Title
Description
Resolution
RATE_LIMIT_EXCEEDED
Rate limit exceeded
You have exceeded the rate limit for this endpoint
Wait before making additional requests, or upgrade your plan for higher limits
Redeem a single-use invite code to unlock free-tier server claiming during the beta, then immediately provision a free server. Idempotent if already unlocked. No-op (no code consumed) when the beta gate is disabled. Requires a first-party JWT; auth tokens, HTTP Basic, and impersonation are rejected.
"message":"Invite code redeemed. Your free server is being prepared.",
"data":{
"unlocked":true,
"required":true,
"claim_blocked_reason":"none",
"server":{
"id":"srv_01HZ8J9YEXAMPLE",
"name":"free-tier-507f1f77bcf86cd799439011",
"region":"us-east-1"
},
"project":{
"id":"507f1f77bcf86cd799439012",
"name":"Default Project"
},
"container":null
}
}
The container field is created asynchronously and may be null at the time of redemption. claim_blocked_reason is pool_empty if the account was unlocked but no server could be claimed yet (retry shortly); otherwise none.
{
"statusCode":400,
"error":"Bad Request",
"message":"This invite code is invalid, expired, or already used."
}
Error Code
Title
Description
Resolution
VALIDATION_ERROR
Invalid input parameters
One or more request parameters failed validation
Check the error message for specific field requirements and correct your input
INVALID_INVITE_CODE
Invalid invite code
The submitted invite code could not be redeemed because it is unknown, already used, disabled, or expired
Check the code for typos, or request a new invite code from an administrator
{
"statusCode":401,
"error":"Unauthorized",
"message":"Authentication token required"
}
Error Code
Title
Description
Resolution
MISSING_TOKEN
Authentication token missing
No authentication token was provided in the request
Include a valid JWT token in the Authorization header as Bearer <token>
INVALID_TOKEN
Invalid authentication token
The provided authentication token is malformed or invalid
Obtain a new token by logging in again or using a valid auth token
{
"statusCode":403,
"error":"Forbidden",
"message":"Insufficient permissions"
}
Error Code
Title
Description
Resolution
INSUFFICIENT_PERMISSIONS
Insufficient permissions
You do not have the required permissions to perform this action
Contact the resource owner or administrator to request access
{
"statusCode":429,
"error":"Too Many Requests",
"message":"Rate limit exceeded"
}
Error Code
Title
Description
Resolution
RATE_LIMIT_EXCEEDED
Rate limit exceeded
You have exceeded the rate limit for this endpoint
Wait before making additional requests, or upgrade your plan for higher limits
Manually claim a free-tier server and create the default project and container. Idempotent — safe to call if already provisioned. If the beta gate is enabled and the account has not been unlocked, this endpoint returns 403 with FREE_TIER_INVITE_REQUIRED; redeem an invite code at POST /api/v1/users/me/redeem-invite first.
The blocked_reason field is set when automatic repair cannot proceed: admin_recovery_required indicates that the default container is quarantined (needs_reclaim) and only an admin reclaim can replace it.
{
"statusCode":403,
"error":"Forbidden",
"message":"An invite code is required to claim your free server during the beta."
}
Error Code
Title
Description
Resolution
FREE_TIER_INVITE_REQUIRED
Invite code required
The beta access gate is enabled and this account has not been unlocked, so it cannot claim a free server yet
Redeem your invite code at POST /api/v1/users/me/redeem-invite, or ask an administrator to validate your account by email
INSUFFICIENT_PERMISSIONS
Insufficient permissions
You do not have the required permissions to perform this action
Contact the resource owner or administrator to request access
The encrypted vault stores per-user or per-realm key-value pairs. Values can be any UTF-8 string (JSON, encrypted data, plain text) — the API does not validate content, so encrypt sensitive data before storing it. Per-realm scoping is controlled via the realm_id query parameter (a 24-character hex ID). When omitted and not on a realm subdomain, the vault defaults to global scope (realm_id = ""). The realm_id value is case-insensitive; uppercase is normalized to lowercase.
List all keys in your encrypted vault with metadata (key names, sizes, timestamps). Values are not included in this response — use GET /api/v1/vault/keys/{key} to retrieve individual values.
Target a specific realm (24-char hex). When omitted and not on a realm subdomain, defaults to global scope (realm_id = ""). Case-insensitive — uppercase is normalized to lowercase.
Vault key name (alphanumeric, dots, underscores, hyphens)
realm_id
query
string
No
Target a specific realm (24-char hex). When omitted and not on a realm subdomain, defaults to global scope (realm_id = ""). Case-insensitive — uppercase is normalized to lowercase.
Create or update a key-value pair in your personal encrypted vault. Values can be any UTF-8 string — the API does not validate content, so encrypt sensitive data before storing it. Returns 200 if the key was updated, 201 if it was created.
Vault key name (alphanumeric, dots, underscores, hyphens)
realm_id
query
string
No
Target a specific realm (24-char hex). When omitted and not on a realm subdomain, defaults to global scope (realm_id = ""). Case-insensitive — uppercase is normalized to lowercase.
Vault key name (alphanumeric, dots, underscores, hyphens)
realm_id
query
string
No
Target a specific realm (24-char hex). When omitted and not on a realm subdomain, defaults to global scope (realm_id = ""). Case-insensitive — uppercase is normalized to lowercase.
Retrieve statistics about your vault usage. total_keys and total_size_bytes are scoped to the current realm. limit_mb, remaining_mb, and used_percentage reflect global vault usage across all realms.
Target a specific realm (24-char hex). When omitted and not on a realm subdomain, defaults to global scope (realm_id = ""). Case-insensitive — uppercase is normalized to lowercase.
Target a specific realm (24-char hex). When omitted and not on a realm subdomain, defaults to global scope (realm_id = ""). Case-insensitive — uppercase is normalized to lowercase.