> For the complete documentation index, see [llms.txt](https://docs.kiiglobal.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.kiiglobal.io/docs/kiichain-pay/api-reference/users.md).

# Users

## CreateApiKey creates a new API Key

> priv\_key is returned only once, in this response. It isn't stored and\
> can't be retrieved again, only rotated via RotateApiKey

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"name":"UsersMsgService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["users.api.write"]},{"BearerAuth":["users.api.write"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"v1CreateApiKeyRequest":{"properties":{"expiresAt":{"format":"date-time","title":"expires_at is the date RFC 3339 (ISO 8601) when the Api key will expire","type":"string"},"name":{"title":"name is the user-assigned name of the api key","type":"string"},"scopes":{"items":{"type":"string"},"title":"scopes is the list of scopes asociated to the Api key","type":"array"}},"required":["name","scopes"],"title":"CreateApiKeyRequest represents the request body of the CreateApi endpoint","type":"object"},"v1CreateApiKeyResponse":{"properties":{"apiKey":{"title":"api_key represents the api key returned after successfully creation","type":"string"},"privKey":{"title":"priv_key is the base64 generated private key","type":"string"}},"required":["apiKey","privKey"],"title":"CreateApiKeyResponse represents the response body from the CreateApi endpoint","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/users/v1/api/create":{"post":{"description":"priv_key is returned only once, in this response. It isn't stored and\ncan't be retrieved again, only rotated via RotateApiKey","operationId":"UsersMsgService_CreateApiKey","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/v1CreateApiKeyRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/v1CreateApiKeyResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"CreateApiKey creates a new API Key","tags":["UsersMsgService"]}}}}
```

## UpdateApiKey overwrite the Api key information (scopes)

> Full replace of scopes and expires\_at. The key material itself is\
> unchanged. Use RotateApiKey to replace credentials instead

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"name":"UsersMsgService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["users.api.update"]},{"BearerAuth":["users.api.update"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"UsersMsgServiceUpdateApiKeyBody":{"properties":{"expiresAt":{"format":"date-time","title":"expires_at is the date RFC 3339 (ISO 8601) when the Api key will expire","type":"string"},"scopes":{"items":{"type":"string"},"title":"scopes is the list of scopes asociated to the Api key","type":"array"}},"required":["scopes"],"title":"UpdateApiKeyRequest represents the request body of the UpdateApi endpoint","type":"object"},"v1UpdateApiKeyResponse":{"title":"UpdateApiKeyResponse represents the response body from the UpdateApi endpoint","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/users/v1/api/{apiKeyId}":{"patch":{"description":"Full replace of scopes and expires_at. The key material itself is\nunchanged. Use RotateApiKey to replace credentials instead","operationId":"UsersMsgService_UpdateApiKey","parameters":[{"description":"api_key represents the api key returned after successfully creation","in":"path","name":"apiKeyId","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsersMsgServiceUpdateApiKeyBody"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/v1UpdateApiKeyResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"UpdateApiKey overwrite the Api key information (scopes)","tags":["UsersMsgService"]}}}}
```

## DeleteApiKey deletes the provided api key id

> Immediate and irreversible. Any client still using this key starts\
> failing authentication right away

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"name":"UsersMsgService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["users.api.delete"]},{"BearerAuth":["users.api.delete"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"v1DeleteApiKeyResponse":{"title":"DeleteApiKeyResponse represents the response body from the DeleteApi endpoint","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/users/v1/api/{apiKeyId}/delete":{"delete":{"description":"Immediate and irreversible. Any client still using this key starts\nfailing authentication right away","operationId":"UsersMsgService_DeleteApiKey","parameters":[{"description":"api_key represents the api key returned after successfully creation","in":"path","name":"apiKeyId","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/v1DeleteApiKeyResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"DeleteApiKey deletes the provided api key id","tags":["UsersMsgService"]}}}}
```

## RotateApiKey takes the provided Api Key and rotates credentials (changes Api Key, Pub Key and Priv Key)

> The old api\_key stops working immediately. Priv\_key is only returned\
> in this response, same as on creation

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"name":"UsersMsgService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["users.api.write"]},{"BearerAuth":["users.api.write"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"v1RotateApiKeyResponse":{"properties":{"apiKey":{"title":"api_key represents the new api key after rotataion","type":"string"},"privKey":{"title":"priv_key is the new base64 generated after rotation","type":"string"},"pubKey":{"title":"pub_key is the new base64 generated after rotation","type":"string"}},"required":["apiKey","pubKey","privKey"],"title":"RotateApiKeyResponse represents the response body from the RotateApiKey endpoint","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/users/v1/api/{apiKeyId}/rotate":{"patch":{"description":"The old api_key stops working immediately. Priv_key is only returned\nin this response, same as on creation","operationId":"UsersMsgService_RotateApiKey","parameters":[{"description":"api_key represents the provided api key","in":"path","name":"apiKeyId","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/v1RotateApiKeyResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"RotateApiKey takes the provided Api Key and rotates credentials (changes Api Key, Pub Key and Priv Key)","tags":["UsersMsgService"]}}}}
```

## GetApiKeyScopes returns the scopes associated to the provided api key id

> Scopes an API key carries directly, distinct from the calling user's own\
> role-based scopes (see GetUserRoles)

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"name":"UsersQueryService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["users.api.read"]},{"BearerAuth":["users.api.read"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"v1GetApiKeyScopesResponse":{"properties":{"scopes":{"items":{"type":"string"},"title":"scopes is the list of scopes asociated to the Api key","type":"array"}},"required":["scopes"],"title":"GetApiKeyScopesScopes represents the response body from the GetApiKeyScopes endpoint","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/users/v1/api/{apiKeyId}/scopes":{"get":{"description":"Scopes an API key carries directly, distinct from the calling user's own\nrole-based scopes (see GetUserRoles)","operationId":"UsersQueryService_GetApiKeyScopes","parameters":[{"description":"api_key represents the provided api key","in":"path","name":"apiKeyId","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/v1GetApiKeyScopesResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"GetApiKeyScopes returns the scopes associated to the provided api key id","tags":["UsersQueryService"]}}}}
```

## GetUserApiKeys returns all the user api keys

> Never includes priv\_key. That's only ever returned once, at\
> creation/rotation time

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"name":"UsersQueryService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["users.api.read","users.api.read:all"]},{"BearerAuth":["users.api.read","users.api.read:all"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"v1GetUserApiKeysResponse":{"properties":{"apiKey":{"items":{"$ref":"#/components/schemas/v1ApiKey"},"title":"api_keys is the list of api keys asociated to the user","type":"array"}},"required":["apiKey"],"title":"GetUserApiKeysResponse represents the response body from the GetUserApiKeys endpoint","type":"object"},"v1ApiKey":{"properties":{"apiKey":{"title":"api_key is the opaque string related to the api key","type":"string"},"createdAt":{"format":"date-time","title":"created_at is the date when the api key was created","type":"string"},"expiresAt":{"format":"date-time","title":"revoked_at is the date when the api key was revoked","type":"string"},"id":{"title":"id is the api key identifier","type":"string"},"lastUsedAt":{"format":"date-time","title":"last_used_at is the date when the api key was last used","type":"string"},"name":{"title":"name is the user-assigned name of the api key","type":"string"},"privKey":{"title":"priv_key is the base64 generated private key","type":"string"},"pubKey":{"title":"pub_key is the base64 generated public key","type":"string"},"revokedAt":{"format":"date-time","title":"revoked_at is the date when the api key was revoked","type":"string"},"scopes":{"items":{"type":"string"},"title":"scopes is the list of scopes asociated to the Api key","type":"array"}},"required":["id","name","apiKey","scopes","pubKey","privKey","createdAt"],"title":"ApiKey contains all information with a api key","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/users/v1/api/{userId}/api-keys":{"get":{"description":"Never includes priv_key. That's only ever returned once, at\ncreation/rotation time","operationId":"UsersQueryService_GetUserApiKeys","parameters":[{"description":"user_id represents the user identifier","in":"path","name":"userId","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/v1GetUserApiKeysResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"GetUserApiKeys returns all the user api keys","tags":["UsersQueryService"]}}}}
```

## Me is the endpoint to get the current authenticated user

> Also returns the active account (with KYC and wallets) and the caller's\
> roles, which GetUser doesn't include

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"name":"UsersQueryService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["users.profile.read"]},{"BearerAuth":["users.profile.read"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"v1MeResponse":{"properties":{"account":{"$ref":"#/components/schemas/v1Account"},"roles":{"items":{"type":"string"},"title":"roles contains the list of roles associated to the user","type":"array"},"user":{"$ref":"#/components/schemas/v1User"}},"required":["user","account","roles"],"title":"MeResponse is the body response structure from the Me endpoint","type":"object"},"v1Account":{"properties":{"accountName":{"title":"account_name is the name of the account","type":"string"},"accountType":{"title":"account_type is the type of the account","type":"string"},"countries":{"items":{"type":"string"},"title":"countries is the list of countries associated to the account, in ISO 3166-1 alpha-3 format","type":"array"},"createdAt":{"format":"date-time","title":"created_at is the date when the account was created","type":"string"},"deletedAt":{"format":"date-time","title":"deleted_at is the date when the account was deleted","type":"string"},"id":{"title":"id is the account identifier","type":"string"},"kycInfo":{"$ref":"#/components/schemas/v1KycInfo"},"privyId":{"title":"privy_id is the identifier of the account on Privy, which is the Wallet provider used by default","type":"string"},"updatedAt":{"format":"date-time","title":"updated_at is the date when the account was updated","type":"string"},"userId":{"title":"account_name is the user-assigned name of the account","type":"string"},"wallets":{"items":{"$ref":"#/components/schemas/v1Wallet"},"title":"wallets is the information about the wallets associated to the account","type":"array"}},"required":["id","userId","accountName","accountType","wallets","kycInfo","createdAt","updatedAt","privyId"],"title":"Account contains all information with a account","type":"object"},"v1KycInfo":{"properties":{"level":{"format":"int32","title":"level is the name of the KYC level approved","type":"integer"},"provider":{"title":"provider is the KYC provider name","type":"string"},"requestedAt":{"format":"date-time","title":"requested_at is the date when the KYC was requested","type":"string"},"status":{"title":"status is the KYC status","type":"string"},"verifiedAt":{"format":"date-time","title":"verified_at is the date when the KYC was verified","type":"string"}},"required":["provider","level","status","requestedAt","verifiedAt"],"title":"KycInfo contains the KYC information per account","type":"object"},"v1Wallet":{"properties":{"address":{"title":"address is the unique wallet address","type":"string"},"chainType":{"title":"chain_type is which chain is using this wallet","type":"string"},"id":{"title":"id is the wallet identifier","type":"string"}},"required":["id","address","chainType"],"title":"Wallet contains all information about a wallet","type":"object"},"v1User":{"properties":{"admin":{"title":"admin is the boolean flag to know if the user is an admin (has access to the admin panel)","type":"boolean"},"createdAt":{"format":"date-time","title":"created_at is the date when the user was created","type":"string"},"deletedAt":{"format":"date-time","title":"deleted_at is the date when the user was deleted","type":"string"},"displayName":{"title":"display_name is the user display name","type":"string"},"email":{"title":"email is the user email","type":"string"},"emailVerified":{"title":"email_verified indicates whether the user's email has been verified","type":"boolean"},"id":{"title":"id is the user identifier","type":"string"},"isMfaEnabled":{"title":"isMfaEnabled is the boolean flag to enable/disable MFA","type":"boolean"},"language":{"title":"language contains the current user language which will be used on notifications","type":"string"},"lockReason":{"title":"lock_reason is the reason when the user is locked","type":"string"},"locked":{"title":"locked is the boolean flag to lock/unlock the user","type":"boolean"},"passwordChangedAt":{"format":"date-time","title":"password_changed_at is the date when the password was changed","type":"string"},"superAdmin":{"title":"super_admin is the boolean flag to enable/disable super admin permissions","type":"boolean"},"updatedAt":{"format":"date-time","title":"updated_at is the date when the user was updated","type":"string"}},"required":["id","email","displayName","isMfaEnabled","locked","superAdmin","language","createdAt","updatedAt","admin","emailVerified"],"title":"User contains all information with a user","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/users/v1/users/me":{"get":{"description":"Also returns the active account (with KYC and wallets) and the caller's\nroles, which GetUser doesn't include","operationId":"UsersQueryService_Me","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/v1MeResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"Me is the endpoint to get the current authenticated user","tags":["UsersQueryService"]}}}}
```

## UpdateMyProfile is the endpoint for a user to update their own profile (display\_name, language).

> Self-service only. No user\_id in the request, it always acts on the\
> caller.

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"name":"UsersMsgService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["users.profile.write"]},{"BearerAuth":["users.profile.write"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"v1UpdateMyProfileRequest":{"properties":{"displayName":{"title":"display_name is the user display name","type":"string"},"language":{"title":"language is the user language","type":"string"}},"required":["displayName","language"],"title":"UpdateMyProfileRequest is the body request for the user self-update profile endpoint","type":"object"},"v1UpdateMyProfileResponse":{"title":"UpdateMyProfileResponse is the body response for the user self-update profile endpoint","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/users/v1/users/me/change_profile":{"patch":{"description":"Self-service only. No user_id in the request, it always acts on the\ncaller.","operationId":"UsersMsgService_UpdateMyProfile","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/v1UpdateMyProfileRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/v1UpdateMyProfileResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"UpdateMyProfile is the endpoint for a user to update their own profile (display_name, language).","tags":["UsersMsgService"]}}}}
```

## GetUser returns a single user

> Lookup by user\_id. For the caller's own profile use Me instead

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"name":"UsersQueryService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["users.profile.read","users.profile.read:all"]},{"BearerAuth":["users.profile.read","users.profile.read:all"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"v1GetUserResponse":{"properties":{"accounts":{"items":{"type":"string"},"title":"accounts contains the list of accounts the user belongs to","type":"array"},"user":{"$ref":"#/components/schemas/v1User"}},"required":["user","accounts"],"title":"GetUserResponse is the body response structure from the Get user endpoint","type":"object"},"v1User":{"properties":{"admin":{"title":"admin is the boolean flag to know if the user is an admin (has access to the admin panel)","type":"boolean"},"createdAt":{"format":"date-time","title":"created_at is the date when the user was created","type":"string"},"deletedAt":{"format":"date-time","title":"deleted_at is the date when the user was deleted","type":"string"},"displayName":{"title":"display_name is the user display name","type":"string"},"email":{"title":"email is the user email","type":"string"},"emailVerified":{"title":"email_verified indicates whether the user's email has been verified","type":"boolean"},"id":{"title":"id is the user identifier","type":"string"},"isMfaEnabled":{"title":"isMfaEnabled is the boolean flag to enable/disable MFA","type":"boolean"},"language":{"title":"language contains the current user language which will be used on notifications","type":"string"},"lockReason":{"title":"lock_reason is the reason when the user is locked","type":"string"},"locked":{"title":"locked is the boolean flag to lock/unlock the user","type":"boolean"},"passwordChangedAt":{"format":"date-time","title":"password_changed_at is the date when the password was changed","type":"string"},"superAdmin":{"title":"super_admin is the boolean flag to enable/disable super admin permissions","type":"boolean"},"updatedAt":{"format":"date-time","title":"updated_at is the date when the user was updated","type":"string"}},"required":["id","email","displayName","isMfaEnabled","locked","superAdmin","language","createdAt","updatedAt","admin","emailVerified"],"title":"User contains all information with a user","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/users/v1/users/{userId}":{"get":{"description":"Lookup by user_id. For the caller's own profile use Me instead","operationId":"UsersQueryService_GetUser","parameters":[{"description":"user_id represents the user identifier","in":"path","name":"userId","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/v1GetUserResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"GetUser returns a single user","tags":["UsersQueryService"]}}}}
```

## UpdateLanguage is the endpoint to update the user language

> Callable on any user. For a user updating\
> their own language use UpdateMyProfile instead

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"name":"UsersMsgService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["users.profile.write","users.profile.write:all"]},{"BearerAuth":["users.profile.write","users.profile.write:all"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"UsersMsgServiceUpdateLanguageBody":{"properties":{"language":{"title":"language represents the desired language","type":"string"}},"required":["language"],"title":"UpdateLanguageRequest is the body request for the update language endpoint","type":"object"},"v1UpdateLanguageResponse":{"title":"UpdateLanguageResponse is the body response for the update language endpoint","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/users/v1/users/{userId}/language":{"patch":{"description":"Callable on any user. For a user updating\ntheir own language use UpdateMyProfile instead","operationId":"UsersMsgService_UpdateLanguage","parameters":[{"description":"user_id represents the user identifier","in":"path","name":"userId","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsersMsgServiceUpdateLanguageBody"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/v1UpdateLanguageResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"UpdateLanguage is the endpoint to update the user language","tags":["UsersMsgService"]}}}}
```

## GetUserRoles is the endpoint to get the user roles and scopes

> scopes is the flattened, deduplicated union of every role's scopes\
> This is what actually determines the user's permissions

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"name":"UsersQueryService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["users.profile.read","users.profile.read:all"]},{"BearerAuth":["users.profile.read","users.profile.read:all"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"v1GetUserRolesResponse":{"properties":{"roles":{"items":{"$ref":"#/components/schemas/v1UserRole"},"title":"roles contains the list of role objects associated to the user","type":"array"},"scopes":{"items":{"type":"string"},"title":"scopes contains the list of scopes associated to the user through its roles","type":"array"}},"required":["roles","scopes"],"type":"object"},"v1UserRole":{"properties":{"id":{"format":"int64","title":"id represents the role identifier","type":"string"},"name":{"title":"name represents the role name","type":"string"}},"required":["id","name"],"title":"GetUserRolesResponse is the body response structure from the GetUserRoles endpoint.\nIt returns the list of roles and scopes associated to the user, it is used to determine the user permissions in the system","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/users/v1/users/{userId}/roles":{"get":{"description":"scopes is the flattened, deduplicated union of every role's scopes\nThis is what actually determines the user's permissions","operationId":"UsersQueryService_GetUserRoles","parameters":[{"description":"user_id represents the user identifier","in":"path","name":"userId","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/v1GetUserRolesResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"GetUserRoles is the endpoint to get the user roles and scopes","tags":["UsersQueryService"]}}}}
```

## GetUserSettings returns the settings for a user

> Currently just max\_allowance. Update via PatchUserSettings

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"name":"UsersQueryService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["users.settings.read","users.settings.read:all"]},{"BearerAuth":["users.settings.read","users.settings.read:all"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"v1GetUserSettingsResponse":{"properties":{"settings":{"$ref":"#/components/schemas/v1UserSettings"}},"required":["settings"],"title":"GetUserSettingsResponse is the response for the get user settings endpoint","type":"object"},"v1UserSettings":{"properties":{"id":{"title":"id is the settings row identifier","type":"string"},"maxAllowance":{"title":"max_allowance controls whether max allowance is enabled for the user","type":"boolean"},"userId":{"title":"user_id is the user this settings row belongs to","type":"string"}},"required":["id","userId","maxAllowance"],"title":"UserSettings holds the settings for a user","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/users/v1/users/{userId}/settings":{"get":{"description":"Currently just max_allowance. Update via PatchUserSettings","operationId":"UsersQueryService_GetUserSettings","parameters":[{"description":"user_id is the user identifier","in":"path","name":"userId","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/v1GetUserSettingsResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"GetUserSettings returns the settings for a user","tags":["UsersQueryService"]}}}}
```

## PatchUserSettings partially updates the settings for a user. Any setting not set in the body will be left unchanged.

> max\_allowance is optional in the request specifically so it can be\
> omitted to leave the current value untouched

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"name":"UsersMsgService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["users.settings.write","users.settings.write:all"]},{"BearerAuth":["users.settings.write","users.settings.write:all"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"UsersMsgServicePatchUserSettingsBody":{"properties":{"maxAllowance":{"title":"max_allowance when set, updates whether max allowance is enabled for the user","type":"boolean"}},"title":"PatchUserSettingsRequest is the request for the patch user settings endpoint","type":"object"},"v1PatchUserSettingsResponse":{"title":"PatchUserSettingsResponse is the response for the patch user settings endpoint","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/users/v1/users/{userId}/settings":{"patch":{"description":"max_allowance is optional in the request specifically so it can be\nomitted to leave the current value untouched","operationId":"UsersMsgService_PatchUserSettings","parameters":[{"description":"user_id is the user identifier","in":"path","name":"userId","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsersMsgServicePatchUserSettingsBody"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/v1PatchUserSettingsResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"PatchUserSettings partially updates the settings for a user. Any setting not set in the body will be left unchanged.","tags":["UsersMsgService"]}}}}
```

## GetMfaMethods returns the Mfa method registered for the user (if any)

> Only non-sensitive info per method (type, label, verified/primary\
> flags). Never secrets like the TOTP seed

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"name":"UsersQueryService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["users.profile.mfa","users.profile.mfa:all"]},{"BearerAuth":["users.profile.mfa","users.profile.mfa:all"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"v1GetMfaMethodsResponse":{"properties":{"methods":{"items":{"$ref":"#/components/schemas/v1MfaMethod"},"type":"array"}},"required":["methods"],"title":"GetMfaMethodsResponse is the response body structure from the Get Mfa Methods endpoint","type":"object"},"v1MfaMethod":{"properties":{"isPrimary":{"title":"is_primary is a flag that represents if this Mfa method is the primary one","type":"boolean"},"isVerified":{"title":"is_verified is a flag that represents if this Mfa method is verified","type":"boolean"},"label":{"title":"label means the name of the method provided by the user","type":"string"},"lastUsedAt":{"format":"date-time","title":"last_used_at is the date when the mfa method was last used","type":"string"},"mfaId":{"title":"mfa_id contains the identifier of the method","type":"string"},"mfaType":{"title":"mfa_type represents the desired mfa method","type":"string"}},"required":["mfaId","mfaType","label","isPrimary","isVerified"],"title":"MfaMethod is the custom type for a Mfa Method with only the information\nand non-sensitive information that can be shown to the user","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/users/v1/{userId}/mfa/methods":{"get":{"description":"Only non-sensitive info per method (type, label, verified/primary\nflags). Never secrets like the TOTP seed","operationId":"UsersQueryService_GetMfaMethods","parameters":[{"description":"user_id represents the user identifier","in":"path","name":"userId","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/v1GetMfaMethodsResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"GetMfaMethods returns the Mfa method registered for the user (if any)","tags":["UsersQueryService"]}}}}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.kiiglobal.io/docs/kiichain-pay/api-reference/users.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
