User Managementv2.0pilot-root.1kosmos.net/users-mgmtOpenAPI
1Kosmos · User Management

User Management API

The system of record for users — attributes, passkeys, factors and policy.

The User Management service is the system of record for identities. Manage users and their attributes, passkeys, PINs and factors; wire up authentication modules and broker connections; and enforce account-lockout and behavioral-auth policy.

63 endpoints

across 22 resource groups.

ECDSA-signed

every request is signed with your key pair.

JSON over HTTPS

predictable REST, conventional status codes.

Reference

Base URL

All User Management endpoints are relative to your environment host. Examples on this page use the 1Kosmos pilot environment — swap in your production root when you go live.

Pilot https://pilot-root.1kosmos.net/users-mgmt

Content type

Requests and responses use application/json.

GEThttps://pilot-root.1kosmos.net/users-mgmt/healthz
curl -X GET 'https://pilot-root.1kosmos.net/users-mgmt/healthz' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY'
Security

Authentication

User Management uses ECDSA key-pair authentication. Each request carries your credentials as HTTP headers; verification-grade calls additionally sign the request body. Retrieve the system signing key from /publickeys.

Credentials
keyIdECDSA Public Keyheader
keySecretECDSA Private Keyheader
licenseLicense key from License Microserviceheader
GEThttps://pilot-root.1kosmos.net/users-mgmt/healthz
cURL
Node.js
Python
curl -X GET 'https://pilot-root.1kosmos.net/users-mgmt/healthz' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY'
Reference

Errors

User Management uses conventional HTTP status codes: 2xx success, 4xx a problem with the request, 5xx a service-side error.

StatusMeaningDescription
200 / 204OKThe request succeeded.
400Bad RequestValidation failed.
401UnauthorizedMissing or invalid credentials.
403ForbiddenAuthenticated, but not permitted.
404Not FoundThe resource does not exist.
500Server ErrorSomething went wrong on our side.
4XXerror response
{
  "statusCode": 400,
  "error": "Bad Request",
  "message": "Validation error"
}
User Management

User Management

Core user create / read / update / delete.

POST/tenant/{tenantId}/community/{communityId}/admin/changepassword

Change user password (role = none and type = basic).

Change user password (role = none and type = basic).

  • Only a system, service and service_ext key can be used.
  • Auth module must be available and enabled for the community.

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Request Body

data (required)

authModule, username and newPassword json, encrypted with ECDSA.

Returns

Returns empty response.

This API throw an error if something goes wrong.

Path parameters
NameTypeDescription
tenantIdrequiredstringID of tenant
communityIdrequiredstringID of community
Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize 🔒
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize 🔒
publickeyrequiredstringPublic Key / Try Authorize 🔒
Request body

Request body contains 'data' field with encrypted object below:

IMPORTANT - you can send unencrypted data and you will get unecrypted data as well, it is only a preview available in Swagger.

{
    "authModule": "ObjectId required, ID of auth module",
    "username": "string required",
    "newPassword": "string required",
    "eventData": "object optional. Key: `mode` — string. Allowed values: email_link_with_otp, email_link, id_proofing, authenticator, other."
}
FieldTypeDescription
datastring
POSThttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/admin/changepassword
cURL
Node.js
Python
curl -X POST 'https://pilot-root.1kosmos.net/users-mgmt/tenant/xxxxxxxxxx/community/xxxxxxxxxxxxxxxxxxxxxxxx/admin/changepassword' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"data": "xxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxx="}'
RESPONSE
200
400
401
Success Empty response
// no response body
POST/tenant/{tenantId}/community/{communityId}/user/authenticate

Authenticate user (password, otp, ktoken, or pin)

Authenticate a user using at least one of the following factors: password, otp, ktoken, or pin.

  • Any valid community license key can be used.
  • If an otp code is provided, it will be verified for username against {adminconsole}/r2 OTP apis.
  • This API now generates "proof_of_authentication" which can be encrypted for a referrer using ECDSA
  • IIF user type is basic - Auth module must be available and enabled for the community.
  • PIN is compared as sha512 hash with the stored value.
  • At least one factor is required.
  • If PIN is validated, "user_pin" will be included in the JWT methods array.
  • If OTP is generated by serviceName then pass serviceName as optional.

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Request Body

Request body contains 'data' field with encrypted object below:

{
  "authModule": "ObjectId optional, ID of auth module",
  "authModules": ["ObjectId of auth module Optional"],
  "username": "string optional",
  "password": "string optional",
  "ktoken": "string optional",
  "otp": "string optional",
  "pin": "string optional",
  "referrerPublicKey": "string optional",
  "scep": "boolean optional",
  "serviceName": "string optional"
}
Path parameters
NameTypeDescription
tenantIdrequiredstringID of tenant
communityIdrequiredstringID of community
Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
Request body

Request body contains 'data' field with encrypted object below:

IMPORTANT - you can send unencrypted data and you will get unecrypted data as well, it is only a preview available in Swagger.

{
    "authModule": "ObjectId optional, ID of auth module",
    "authModules": ["ObjectId of auth module Optional"],
    "username": "string optional",
    "password": "string optional",
    "ktoken": "string optional",
    "otp": "string optional",
    "pin": "string optional",
    "referrerPublicKey": "string optional",
    "scep": "boolean optional",
    "serviceName": "string optional"
}
FieldTypeDescription
dataobject
POSThttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/user/authenticate
cURL
Node.js
Python
curl -X POST 'https://pilot-root.1kosmos.net/users-mgmt/tenant/xxxxxxxxxx/community/xxxxxxxxxxxxxxxxxxxxxxxx/user/authenticate' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"data": {"authModule": "string", "authModules": ["string"], "username": "string", "password": "string", "ktoken": "string", "otp": "string", "pin": "string", "referrerPublicKey": "string", "scep": true, "serviceName": "string"}}'
RESPONSE
200
400
401
Success Authenticated user object: ``` { "data":{ "username": "username", "uid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "dguid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "status": "active", "roleValue": "none", "type": "basic", "moduleId": "moduleId", "onboarding_status": "tbd", "email": "email", "firstname": "Firstname", "lastname": "Lastname", "phone": "xxxxxx", "urn": "xxx:xxx:xxxxxxxxxxxx:xxx:xxxxxxxxxxxxxxxxxxxx:xxx:xxxxxxxxxxxxxx:xxx:xxxxxxxxxxx:xxx:xxxxxxxxxxxx", "proof_of_authentication_jwt":"xxx" }, "publicKey": "xxxxxx" } ```
{
  "data": {
    "username": "xxxxxx",
    "uid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "dguid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "status": "xxxxxx",
    "roleValue": "xxxxx",
    "type": "xxxxx",
    "moduleId": "xxxxxx",
    "onboarding_status": "tbd",
    "email": "xxxxx",
    "firstname": "xxxxx",
    "lastname": "xxxxx",
    "phone": "xxxxx",
    "urn": "xxx:xxx:xxxxxxxxxxxx:xxx:xxxxxxxxxxxxxxxxxxxx:xxx:xxxxxxxxxxxxxx:xxx:xxxxxxxxxxx:xxx:xxxxxxxxxxxx",
    "proof_of_authentication_jwt": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
  },
  "publicKey": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
POST/tenant/{tenantId}/community/{communityId}/user/changepassword

Change user password (role = none).

Change user password (role = none).

  • Only a system, service, service_ext, app and app_ext key can be used.
  • A user must provide an existing password OR an OTP code which can be verified against username with {adminconsole}/r2 OTP apis
  • If APP or APP_EXT licenses provided, A caller should provide an user did AND user publicKey which can be verified against username PON data {adminconsole} fetch userinfo apis
  • Auth module must be available and enabled for the community.
  • User with role 'none' is allowed.

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Request Body

data (required)

authModule, username, currentPassword and newPassword json, encrypted with ECDSA.

Returns

Returns empty response.

This API throw an error if something goes wrong.

Path parameters
NameTypeDescription
tenantIdrequiredstringID of tenant
communityIdrequiredstringID of community
Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
Request body

Request body contains 'data' field with encrypted object below:

IMPORTANT - you can send unencrypted data and you will get unecrypted data as well, it is only a preview available in Swagger.

{
    "authModule": "ObjectId required, ID of auth module",
    "username": "string required",
    "currentPassword": "string optional: only one of currentPassword | otp is required",
    "otp": "string optional: only one of currentPassword | otp is required",
    "userDid": "string optional, required for app/app_ext authLevel keys",
    "userPublicKey": "string optional, required for app/app_ext authLevel keys",
    "newPassword": "string required"
    "eventData": "object optional. Key: `mode` — string. Allowed values: email_link_with_otp, email_link, id_proofing, authenticator, other."
}
FieldTypeDescription
datastring
POSThttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/user/changepassword
cURL
Node.js
Python
curl -X POST 'https://pilot-root.1kosmos.net/users-mgmt/tenant/xxxxxxxxxx/community/xxxxxxxxxxxxxxxxxxxxxxxx/user/changepassword' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"data": "xxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxx="}'
RESPONSE
200
400
401
Success Empty response
// no response body
POST/tenant/{tenantId}/community/{communityId}/user/fetch_single_user_by_username

Fetch single basic user.

Fetch single basic user.

  • Any valid key can be used to fetch user.
  • If scep is true, basic key cannot be used
  • Auth module must be available and enabled for the community.
  • Returned users will be the type of 'basic'.

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Request Body

authModule (optional)

ID of auth module is optional. If authModule is provided, fetch users from that particular authModule only. If authModule is not provided OR is null OR empty string THEN

  • fetch default AUTHSCHEME(enabled: true && isDefault: true) from AuthN
  • If no authScheme found, return ZERO results in the response.
  • If authScheme is found, collect authModules in following order
  • dbModule goes at location 0.
  • other modules: [] get added IN ORDER.
username (required)
attributes (optional)

This will drive response_user.dir_attributes.

checkAliases (optional)

If it's true, first it will be search w/ username and if it's not found, then search username as alias in user-properties. default is false

do_transformation (optional)

IF it's true, THEN only transaform user object. default is true

check_locks (optional)

IF it's true, THEN only it will check for user locks status in DB default is true

load_props (optional)

IF it's true, THEN only it will fetch user-properties default is true

includeProperties (optional)

IF it's true, THEN only it will fetch user-properties, default is false

Returns

Returns the single user.

This API throw an error if something goes wrong.

Path parameters
NameTypeDescription
tenantIdrequiredstringID of tenant
communityIdrequiredstringID of community
Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
Request body

Request body contains object below:

{
    "authModule": "ObjectId optional, ID of authModule",
    "username": "username of user required",
    "attributes": "array of user attributes, optional",
    "checkAliases": boolean optional - default false,
    "do_transformation": boolean optional - default true,
    "check_locks": boolean optional - default true,
    "load_props": boolean optional - default true,
    "includeProperties": boolean optional - default false
}
FieldTypeDescription
authModulestring
usernamestring
attributesarray<object>
checkAliasesboolean
do_transformationboolean
check_locksboolean
load_propsboolean
includePropertiesboolean
POSThttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/user/fetch_single_user_by_username
cURL
Node.js
Python
curl -X POST 'https://pilot-root.1kosmos.net/users-mgmt/tenant/xxxxxxxxxx/community/xxxxxxxxxxxxxxxxxxxxxxxx/user/fetch_single_user_by_username' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"authModule": "xxxxxxxxxxxxxxxxxxxxxxxx", "username": "", "attributes": [], "checkAliases": false, "do_transformation": true, "check_locks": true, "load_props": true, "includeProperties": false}'
RESPONSE
200
400
401
404
500
Success Single user fetch result. ``` { "data": { "username": "username", "uid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "dguid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "status": "active", "roleValue": "none", "type": "basic", "moduleId": "moduleId", "onboarding_status": "tbd", "email": "email", "firstname": "Firstname", "lastname": "Lastname", "phone": "xxxxxx", "forcePasswordReset": true/false, // it return, if forcePasswordResetEnabled for AD Broker Auth module "urn": "xxx:xxx:xxxxxxxxxxxx:xxx:xxxxxxxxxxxxxxxxxxxx:xxx:xxxxxxxxxxxxxx:xxx:xxxxxxxxxxx:xxx:xxxxxxxxxxxx", "scepCredentials": {} // if scep is true and system/service level licensekey used "user_certificate": ecdsa($scepCredentials) // if scep is true and service_ext/app/app_ext level licensekey used "typing_phrase": "typing phrase", "is_user_pin_enrolled": true/false, "userProperties": { mobiles: [], landlines: [], aliases: {} } // if includeProperties is true }, publicKey: "servicekey's publickey" } ```
{
  "data": {
    "username": "xxxxx",
    "uid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "dguid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "status": "xxxxxx",
    "roleValue": "xxxxx",
    "type": "xxxxx",
    "moduleId": "xxxxxx",
    "onboarding_status": "tbd",
    "email": "xxxxxx",
    "firstname": "xxxxxx",
    "lastname": "xxxxxx",
    "phone": "xxxxxx",
    "urn": "xxx:xxx:xxxxxxxxxxxx:xxx:xxxxxxxxxxxxxxxxxxxx:xxx:xxxxxxxxxxxxxx:xxx:xxxxxxxxxxx:xxx:xxxxxxxxxxxx",
    "typing_phrase": "xxx",
    "is_user_pin_enrolled": true,
    "userProperties": {
      "mobiles": [],
      "landlines": [],
      "aliases": {}
    }
  }
}
POST/tenant/{tenantId}/community/{communityId}/user/scepcredentials

scep credentials for user.

Obtain the scep credentials for given userName without password authentication.

  • Only permit system or service key to request a user's scep credentials

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Request Body

data (required)

authModule, username json, encrypted with ECDSA.

Returns

Returns the ECDSA encrypted scep credentials.

This API throw an error if something goes wrong.

Path parameters
NameTypeDescription
tenantIdrequiredstringID of tenant
communityIdrequiredstringID of community
Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
Request body

Request body contains 'data' field with encrypted object below:

IMPORTANT - you can send unencrypted data and you will get unecrypted data as well, it is only a preview available in Swagger.

{
    "authModule": "ObjectId required, ID of auth module",
    "username": "string required"
}
FieldTypeDescription
datastring
POSThttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/user/scepcredentials
cURL
Node.js
Python
curl -X POST 'https://pilot-root.1kosmos.net/users-mgmt/tenant/xxxxxxxxxx/community/xxxxxxxxxxxxxxxxxxxxxxxx/user/scepcredentials' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"authModule": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "username": "xxxxxxxxxx"}'
RESPONSE
200
400
401
Success Authenticated user object: ``` { scepCredentials": { "certificate": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx "privatekey" : "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "publickey": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" } ```
{
  "scepCredentials": {
    "certificate": "xxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxx=",
    "privatekey": "xxxxxxx/xxxxxxxxxxxxxxxxx=",
    "publickey": "xx/xxxxxxxxxxxxx="
  }
}
POST/tenant/{tenantId}/community/{communityId}/user/validate_user_password

Verify user password.

Verify user password.

  • Any valid community license key can be used.
  • This API now generates "proof_of_authentication" which can be encrypted for a referrer using ECDSA

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Request Body

data (required)

authModule, username, password encrypted with ECDSA.

Returns

Returns the ECDSA encrypted user, and public key.

This API throw an error if something goes wrong.

Path parameters
NameTypeDescription
tenantIdrequiredstringID of tenant
communityIdrequiredstringID of community
Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
Request body

Request body contains 'data' field with encrypted object below:

IMPORTANT - you can send unencrypted data and you will get unecrypted data as well, it is only a preview available in Swagger.

{
    "authModule": "ObjectId required, ID of auth module",
    "username": "string required",
    "dn": "string optional",
    "password": "string required"
}
FieldTypeDescription
datastring
POSThttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/user/validate_user_password
cURL
Node.js
Python
curl -X POST 'https://pilot-root.1kosmos.net/users-mgmt/tenant/xxxxxxxxxx/community/xxxxxxxxxxxxxxxxxxxxxxxx/user/validate_user_password' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"data": "xxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxx="}'
RESPONSE
200
400
401
404
500
Success Authenticated user object: ``` { "data":{ "username": "username", "moduleId": "moduleId", "proof_of_authentication_jwt":"xxx" }, "publicKey": "xxxxxx" } ```
{
  "data": {
    "username": "xxxxxx",
    "moduleId": "xxxxxx",
    "proof_of_authentication_jwt": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
  },
  "publicKey": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
POST/tenant/{tenantId}/community/{communityId}/user/verify_user_ktoken

Verify user ktoken.

Verify user ktoken.

  • Any valid community license key can be used.
  • This API now generates "proof_of_authentication" which can be encrypted for a referrer using ECDSA

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Request Body

data (required)

ktoken, attributes encrypted with ECDSA.

Returns

Returns the ECDSA encrypted user, and public key.

This API throw an error if something goes wrong.

Path parameters
NameTypeDescription
tenantIdrequiredstringID of tenant
communityIdrequiredstringID of community
Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
Request body

Request body contains 'data' field with encrypted object below:

IMPORTANT - you can send unencrypted data and you will get unecrypted data as well, it is only a preview available in Swagger.

{
    "ktoken": "string required",
    "attributes": [] // optional
}
FieldTypeDescription
datastring
POSThttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/user/verify_user_ktoken
cURL
Node.js
Python
curl -X POST 'https://pilot-root.1kosmos.net/users-mgmt/tenant/xxxxxxxxxx/community/xxxxxxxxxxxxxxxxxxxxxxxx/user/verify_user_ktoken' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"data": "xxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxx="}'
RESPONSE
200
400
401
404
500
Success Authenticated user object: ``` { "data":{ "username": "", "uid": "", "dguid": "", "status": "", "roleValue": "", "type": "", "moduleId": "", "onboarding_status": "tbd", "email": "", "firstname": "", "lastname": "", "phone": "", "urn": "", "proof_of_authentication_jwt":"" }, "publicKey": "" } ```
{
  "data": {
    "username": "xxxxxx",
    "moduleId": "xxxxxx",
    "proof_of_authentication_jwt": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
  },
  "publicKey": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
POST/tenant/{tenantId}/community/{communityId}/users/count

Count all basic users.

Count all basic users for AzureAD only.

  • Any valid key can be used to count users.
  • Auth module must be available for the community.

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Request Body

authModule (required)

ID of auth module.

query (optional)

The query to filter users.

Returns

Returns the users with pagination.

This API throw an error if something goes wrong.

Path parameters
NameTypeDescription
tenantIdrequiredstringID of tenant
communityIdrequiredstringID of community
Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
Request body

Request body contains object below:

{
    "authModule": "ObjectId required, ID of authModule",
    "query": "query object optional",
}
FieldTypeDescription
authModulestring
queryobject
POSThttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/users/count
cURL
Node.js
Python
curl -X POST 'https://pilot-root.1kosmos.net/users-mgmt/tenant/xxxxxxxxxx/community/xxxxxxxxxxxxxxxxxxxxxxxx/users/count' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"authModule": "xxxxxxxxxxxxxxxxxxxxxxxx", "query": {}}'
RESPONSE
200
400
401
Success Users count result. ``` { "count": 50, "id": "ObjectID", "type": "azuread", } ```
{
  "id": "xxxxx",
  "type": "xxxxxxxx",
  "count": "XX"
}
POST/tenant/{tenantId}/community/{communityId}/users/fetch

Fetch all basic users.

Fetch all basic users.

  • Any valid key can be used to fetch users.
  • If scep is true, basic key cannot be used
  • Auth module must be available and enabled for the community.
  • If includeProperties is requested true, it will add userProperties in response.
  • Returned users will be the type of 'basic'.

--- SCEP/JWT Mandate (effective Jan 20, 2026):

  • When called with a system/service key, behavior is unchanged.
  • When called with an service/app/app_ext key and scep: true:
  • If current date is after Jan 20, 2026 (or the value of scep_jwt_mandate_epoch from CaaS config), a JWT is mandatory in the request body (data.jwt).
  • If JWT is missing or invalid, returns 401 Unauthorized.
  • JWT is validated via /authn/jwt/verifyToken and must have isAuthenticated: true.
  • If current date is before the mandate, JWT is not required and behavior is unchanged.
  • Response format remains unchanged.

---

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Request Body

authModule (optional)

ID of auth module is optional. If authModule is provided, fetch users from that particular authModule only. If authModule is not provided OR is null OR empty string THEN

  • fetch default AUTHSCHEME(enabled: true && isDefault: true) from AuthN
  • If no authScheme found, return ZERO results in the response.
  • If authScheme is found, collect authModules in following order
  • dbModule goes at location 0.
  • other modules: [] get added IN ORDER.
pIndex (optional)

The pIndex key is a cursor for the pagination.

pSize (optional)

A limit on the number of objects to be returned. The range between 1 to 100 and the default is 25.

query (optional)

The query to filter users.

attributes (optional)

This will drive response_user.dir_attributes.

scep (optional Boolean)

If scep provided true. then it will return scep if requested query contains only username or uid.

  • For service/app/app_ext keys after mandate date, JWT is required in data.jwt.
maximumCount (optional)

If maximumCount (>= 1) attribute is provided, then it will return quickly - as soon as it finds maximumCount number of users, without fetching all users count among all available directories(authSchemes)

includeBrokerConnectionId (optional)

If includeBrokerConnectionId is provided, then request should forward to that specific broker and fetch the user using that specific broker.

excludeBrokerConnectionId (optional)

If excludeBrokerConnectionId is provided, then request should not forward to that specific broker

includeProperties (optional)

If includeProperties is requested true, then it will return the user properties in response.

Returns

Returns the users with pagination.

This API throw an error if something goes wrong.

Path parameters
NameTypeDescription
tenantIdrequiredstringID of tenant
communityIdrequiredstringID of community
Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
Request body

Request body contains object below:

{
    "authModule": "ObjectId optional, ID of authModule",
    "pIndex": "number optional, default = 0",
    "pSize": "number optional, default = 25, min = 1, max = 100",
    "query": "query object optional",
    "attributes": "array of user attributes, optional",
    "scep": "boolean optional",
    "maximumCount": "number optional",
    "includeBrokerConnectionId": ["optional"],
    "excludeBrokerConnectionId": ["optional"],
    "checkAliases": boolean optional
    "includeProperties": boolean optional,
    "jwt": "string, required for app/app_ext keys with scep after mandate date"
}
FieldTypeDescription
authModulestring
pIndexnumber
pSizenumber
queryobject
attributesarray<object>
includeBrokerConnectionIdarray<object>
excludeBrokerConnectionIdarray<object>
checkAliasesboolean
includePropertiesboolean
POSThttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/users/fetch
cURL
Node.js
Python
curl -X POST 'https://pilot-root.1kosmos.net/users-mgmt/tenant/xxxxxxxxxx/community/xxxxxxxxxxxxxxxxxxxxxxxx/users/fetch' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"authModule": "xxxxxxxxxxxxxxxxxxxxxxxx", "pIndex": 0, "pSize": 25, "query": {}, "attributes": [], "includeBrokerConnectionId": [], "excludeBrokerConnectionId": [], "checkAliases": false, "includeProperties": false}'
RESPONSE
200
400
401
Success Users fetch result with pagination details. ``` { "page": { "index": 0, page number, starting from 0 "total": 50, total number of records "size": 10 number of records, per page }, "data": [ { "username": "username", "uid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "dguid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "status": "active", "roleValue": "none", "type": "basic", "moduleId": "moduleId", "onboarding_status": "tbd", "email": "email", "firstname": "Firstname", "lastname": "Lastname", "phone": "xxxxxx", "forcePasswordReset": true/false, // it return, if forcePasswordResetEnabled for AD Broker Auth module "urn": "xxx:xxx:xxxxxxxxxxxx:xxx:xxxxxxxxxxxxxxxxxxxx:xxx:xxxxxxxxxxxxxx:xxx:xxxxxxxxxxx:xxx:xxxxxxxxxxxx", "scepCredentials": {} // if scep is true and system/service level licensekey used "user_certificate": ecdsa($scepCredentials) // if scep is true and service_ext/app/app_ext level licensekey used, "typing_phrase": "typing phrase", "is_user_pin_enrolled": true/false, "userProperties": { mobiles: [], landlines: [], aliases: {} } // if includeProperties is true } ], publicKey: "servicekey's publickey" } ```
{
  "page": {
    "index": 0,
    "total": 50,
    "size": 25
  },
  "publicKey": "xxxxxxx",
  "data": [
    {
      "username": "xxxxx",
      "uid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "dguid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "status": "xxxxxx",
      "roleValue": "xxxxx",
      "type": "xxxxx",
      "moduleId": "xxxxxx",
      "onboarding_status": "tbd",
      "email": "xxxxxx",
      "firstname": "xxxxxx",
      "lastname": "xxxxxx",
      "phone": "xxxxxx",
      "urn": "xxx:xxx:xxxxxxxxxxxx:xxx:xxxxxxxxxxxxxxxxxxxx:xxx:xxxxxxxxxxxxxx:xxx:xxxxxxxxxxx:xxx:xxxxxxxxxxxx",
      "typing_phrase": "xxx",
      "is_user_pin_enrolled": true,
      "userProperties": {
        "mobiles": [],
        "landlines": [],
        "aliases": {}
      }
    }
  ]
}
PUT/tenant/{tenantId}/community/{communityId}/users/create

Create bulk users.

Create bulk users.

  • Only a system, service and service_ext key can be used to create bulk users.
  • A app, app_ext key can be used to create single user as long as an otp is provided.
  • Use app | app_ext key w/ OTP to support "self-registration" from an app (eg: mobile app)
  • User {adminconsole}/r2 OTP api to request an otp for the user
  • Created users will be the type of basic with the role none.
  • Auth module must be available and enabled for the community.
  • Username is unique by community.

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Request Body

authModule (required)

ID of auth module.

users (required)

List of users to import.

Returns

Returns the counts of requested, created, failed, and the number of errors.

This API throw an error if something goes wrong.

Path parameters
NameTypeDescription
tenantIdrequiredstringID of tenant
communityIdrequiredstringID of community
Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
Request body

Request body contains below fields to create users.

{
    "authModule": "ObjectId required, ID of auth module.",
    "users": [
        {
            "username": "string required",
            "password": "string required",
            "status": "string optional - active or locked or disabled, default = active",
            "firstname": "string required",
            "middlename": "string optional",
            "lastname": "string required",
            "email1": "string required - valid email address",
            "email1_verified": "boolean optional",
            "email2": "string optional - valid email address",
            "email2_verified": "boolean optional",
            "phone1": "string optional - only digits",
            "phone1_verified": "boolean optional",
            "address": {
                "house": "string optional",
                "streetname": "string optional",
                "city": "string optional",
                "state": "string optional",
                "country": "string optional",
                "zip": "string optional"
            },
            "address_verified": "boolean optional",
            "disabled": "boolean optional",
            "otp": "string optional",
            "idpId": "string optional"
        }
    ]
}
FieldTypeDescription
authModulestring
usersarray<object>
PUThttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/users/create
cURL
Node.js
Python
curl -X PUT 'https://pilot-root.1kosmos.net/users-mgmt/tenant/xxxxxxxxxx/community/xxxxxxxxxxxxxxxxxxxxxxxx/users/create' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"authModule": "xxxxxxxxxxxxxxxxxxxxxxxx", "users": [{"username": "string", "password": "string", "status": "string", "firstname": "string", "middlename": "string-optional", "lastname": "string", "email1": "string", "email1_verified": true, "email2": "string-optional", "email2_verified": true, "phone1": "string-only-digits", "phone1_verified": true, "address": {}, "address_verified": true, "disabled": false, "idpId": "string"}]}'
RESPONSE
200
400
401
405
Success User import statistics, errors (if any): ``` { "requested": "number of user requested", "created": "number of user created successfully", "failed": "number of user import failed", "errors": [] } ```
{
  "requested": 10,
  "created": 10,
  "failed": 0,
  "errors": []
}
PATCH/tenant/{tenantId}/community/{communityId}/user/update

Update user by username.

Update user by username.

  • Only a system, service and service_ext key can be used to update user.
  • Auth module must be available and enabled for the community.
  • Only basic user will be updated.
  • roleValue, uid, username, password cannot be updated.
  • Only provided attributes will be updated.

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Request Body

authModule (required)

ID of auth module.

username (required)

Username of user, used to identify user.

type (optional)

This key sets the type of a user. The type key only accept these values ("systemuser", "basic").

status (optional)

This key sets the status of a user. The type key only accept these values ("active", "locked", "disabled").

firstname (optional)

This key sets the first name of a user.

middlename (optional)

This key sets the middle name of a user.

lastname (optional)

This key sets the last name of a user.

email1 (optional)

This key sets the first email of a user.

email1_verified (optional)

This key sets the verification status of the first email.

email2 (optional)

This key sets the second email of the user.

emaild_verified (optional)

This key sets the verification status of the second email.

phone1 (optional)

This key sets the phone number of a user.

phone1_verified (optional)

This key sets the verification status of the phone number.

address (optional object)

This key sets the address of the user.

address_verified (optional)

This key sets the verification status of the address.

disabled (optional)

This key set disabled status of a user. The disabled key only accept these values (true, false).

attributes (optional)

This key accepts an array of attributes that need to return in the response.

Returns

Returns the updated system user.

This API throw an error if something goes wrong.

Path parameters
NameTypeDescription
tenantIdrequiredstringID of tenant
communityIdrequiredstringID of community
Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
Request body

Request body contains below fields to update user.

{
    "authModule": "string required, ObjectId of auth module",
    "username": "string required",
    "type": "string optional - systemuser or basic",
    "status": "string optional - active or locked or disabled",
    "firstname": "string optional",
    "middlename": "string optional",
    "lastname": "string optional",
    "email1": "string optional - valid email address",
    "email1_verified": "boolean optional",
    "email2": "string optional - valid email address",
    "email2_verified": "boolean optional",
    "phone1": "string optional - only digits",
    "phone1_verified": "boolean optional",
    "address": {
        "house": "string optional",
        "streetname": "string optional",
        "city": "string optional",
        "state": "string optional",
        "country": "string optional",
        "zip": "string optional"
    },
    "address_verified": "boolean optional",
    "disabled": "boolean optional"
    "attributes": []
}
FieldTypeDescription
authModulestring
usernamestring
typestring
statusstring
firstnamestring
middlenamestring
lastnamestring
email1string
email1_verifiedstring
email2string
email2_verifiedstring
phone1string
phone1_verifiedstring
addressstring
address_verifiedstring
disabledstring
PATCHhttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/user/update
cURL
Node.js
Python
curl -X PATCH 'https://pilot-root.1kosmos.net/users-mgmt/tenant/xxxxxxxxxx/community/xxxxxxxxxxxxxxxxxxxxxxxx/user/update' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"authModule": "xxxxxxxxxxxxxxxxxxxxxxxx", "username": "xxxxx", "status": "xxxxxx", "firstname": "xxxxxxxx", "middlename": "xxxxxxxx", "lastname": "xxxxxxxx", "email1": "xxxxx@xxxxxxxx.xxx", "email1_verified": true, "email2": "xxxxx@xxxxxxxx.xxx", "email2_verified": true, "phone1": "xxxxxxxxxx", "phone1_verified": true, "address": {}, "address_verified": false, "disabled": false}'
RESPONSE
200
400
401
404
405
Success Updated user object: - default returning attribute: username, uid, status, moduleId - all other attributes will be returned based on supplied attributes ``` { "uid": "748da031-c45e-4abd-930e-75b4929e6503", "tenantId": "123-456", "communityId": "any", "roleValue": "none", "username": "Username", "type": "systemuser", "status": "active", "firstname": "First name", "middlename": "Middle name", "lastname": "Last name", "email1": "bu-1@gmail.com", "email1_verified": true, "email2": "bu-11@gmail.com", "email2_verified": true, "phone1": "11111111", "phone1_verified": true, "address": { "house": "House", "streetname": "Street name", "city": "City", "state": "State", "country": "Country", "zip": "11111" }, "address_verified": true, "disabled": false, "urn": "urn:dns:blockid.1kosmos.net:community:any:mod:123-456:uid:748da031-c45e-4abd-930e-75b4929e6503" } ```
{
  "uid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "tenantId": "xxxxxxxxxx",
  "communityId": "xxxxxxxxxxxxxxxxxxxxxxxx",
  "username": "xxxxxx",
  "type": "xxxxx",
  "roleValue": "xxxxx",
  "status": "xxxxxx",
  "firstname": "xxxxxxxx",
  "middlename": "xxxxxxxx",
  "lastname": "xxxxxxxx",
  "email1": "xxxxx@xxxxxxxx.xxx",
  "email1_verified": true,
  "email2": "xxxxx@xxxxxxxx.xxx",
  "email2_verified": true,
  "phone1": "xxxxxxxxxx",
  "phone1_verified": true,
  "address": {},
  "address_verified": false,
  "disabled": false,
  "urn": "xxx:xxx:xxxxxxxxxxxx:xxx:xxxxxxxxxxxxxxxxxxxx:xxx:xxxxxxxxxxxxxx:xxx:xxxxxxxxxxx:xxx:xxxxxxxxxxxx"
}
User Management

Auth Module

Per-user authentication modules.

GET/tenant/{tenantId}/community/{communityId}/module/{moduleId}

Get auth module by moduleId.

Get auth module by moduleId.

  • Key must be authorized for community.
  • Only a system, service and service_ext key can be used to fetch auth module.

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Parameters

No Parameters

Returns

Returns the auth module, encrypted with ECDSA and public key.

This API throw an error if something goes wrong.

Path parameters
NameTypeDescription
tenantIdrequiredstring
communityIdrequiredstring
moduleIdrequiredstring
Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
GEThttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/module/{moduleId}
cURL
Node.js
Python
curl -X GET 'https://pilot-root.1kosmos.net/users-mgmt/tenant/xxxxxxxxxx/community/xxxxxxxxxxxxxxxxxxxxxxxx/module/xxxxxxxxxxxxxxxxxxxxxxxx' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY'
RESPONSE
200
400
401
404
Success publicKey is publicKey of User Management API, useful for decryption response data is ECDSA encrypted object represents auth module: ``` { "_id": "ObjectID", "communityId": "ObjectID", "type": "db", "subtype": "datastore", "method": "authn", "name": "Auth Module Name", "enabled": true, "mode": "broker/direct", "lastEnabledAt": "date optional", "enhanced_security_on": false, "config": {} // see below config response samples } ``` config object for type **ad** or **ldap**: ``` { "hosts": [{ "server": "string", "port": "string", "lastSuccessAt": date, "lastNotifiedAt": date }], "hostTimeoutSeconds": "number optional - default = 10s", "hostRetryAfterMinutes": "number optional - default = 30m", "serverprotocol": "ldap", "server": "string", "serverport": "string", "binddn": "string", "bindpassword": "string", "basedn": "string", "securityauthentication": "Simple", "forcePasswordResetEnabled": false, "filter": "string", "serviceacctreadonly": true, "scepenabled": "boolean optional", "scepurl": "string optional", "challengeurl": "string optional", "scepagent": "string optional", "cert_enabled": "boolean optional", "cert_template": "string optional", // Alphabets, numerals, spaces, special characters allowed "dc_dns": "string optional", // DNS names can contain only alphabetic characters (A-Z, a-z), numeric characters (0-9), the minus sign (-), and the period (.) "dc_ca": "string optional", // up to 64 characters, ANSI character set "ldapqueryfilter": "string optional", "transformationJSB64": "string optional", "logfilesizemb": number, // it's only for BROKER "logfilecount": number, // it's only for BROKER "modified_at": date, // it's only for BROKER "etag": uuid, // it's only for BROKER "notificationAfterNoOfMinsDisconnect": "number optional", // default 5 "brokerDisconnectNotificationTo": "array optional", "brokerNotificationsEnabled": "boolean optional", // default false "hostStatusChangeNotificationsTo": "array optional", "hostStatusChangeNotificationsEnabled": "boolean optional", // default false "passwordPolicy": { "authtype": "string required", // Face | Fingerprint "allowed": boolean required, "rules": { "min": "number required", "min_enabled": boolean required, "min_special": "number required", "min_special_enabled": boolean required, "min_numbers": "number required", "min_numbers_enabled": boolean required, "special_chars_allowed": "string required", "special_chars_allowed_enabled": boolean required, "min_alpha_caps": "number required", "min_alpha_caps_enabled": boolean required, "noUsername": boolean required, "noUsername_enabled": boolean required, "allowInRow": "number required", "allowInRow_enabled": boolean required }, "descriptions": [ "string required" ] } } ``` config object for type **azuread**: ``` { "appName": "string", "tenantId": "string", "tenantName": "string", "clientId": "string", "clientSecret": "string", "loginBasePath": "string", "graphApiBasePath": "string" } ``` config object for type **db**: ``` { "passwordPolicy": { "authtype": "string required", // Face | Fingerprint "allowed": boolean required, "rules": { "min": "number required", "min_enabled": boolean required, "min_special": "number required", "min_special_enabled": boolean required, "min_numbers": "number required", "min_numbers_enabled": boolean required, "special_chars_allowed": "string required", "special_chars_allowed_enabled": boolean required, "min_alpha_caps": "number required", "min_alpha_caps_enabled": boolean required, "noUsername": boolean required, "noUsername_enabled": boolean required, "allowInRow": "number required", "allowInRow_enabled": boolean required }, "descriptions": [ "string required" ] } } ```
{
  "data": "xxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxx="
}
GET/tenant/{tenantId}/community/{communityId}/module/{moduleId}/pwd-policy

Get password policy by moduleId.

Get password policy by moduleId.

  • Any license.

Returns

Password policy rules with descriptions.

This API throw an error if something goes wrong.

Path parameters
NameTypeDescription
tenantIdrequiredstring
communityIdrequiredstring
moduleIdrequiredstring
Headers
NameTypeDescription
requestidstringJSON string
GEThttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/module/{moduleId}/pwd-policy
cURL
Node.js
Python
curl -X GET 'https://pilot-root.1kosmos.net/users-mgmt/tenant/xxxxxxxxxx/community/xxxxxxxxxxxxxxxxxxxxxxxx/module/xxxxxxxxxxxxxxxxxxxxxxxx/pwd-policy' \
  -H 'requestid: <ecdsa-requestid>'
RESPONSE
200
400
404
Success data is an object which returns rules and descriptions: ``` { "passwordPolicy": { "authtype": "string required", // Face | Fingerprint "allowed": boolean required, "rules": { "min": "number required", "min_enabled": boolean required, "min_special": "number required", "min_special_enabled": boolean required, "min_numbers": "number required", "min_numbers_enabled": boolean required, "special_chars_allowed": "string required", "special_chars_allowed_enabled": boolean required, "min_alpha_caps": "number required", "min_alpha_caps_enabled": boolean required, "noUsername": boolean required, "noUsername_enabled": boolean required, "allowInRow": "number required", "allowInRow_enabled": boolean required }, "descriptions": [ "string required" ] } } ```
{
  "data": "xxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxx="
}
GET/tenant/{tenantId}/community/{communityId}/module/{moduleId}/test-connection

test auth module.

test auth module.

  • Key must be authorized for community.
  • Only a system, service and service_ext key can be used to update auth module.

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Returns

Returns the updated auth module, encrypted with ECDSA and public key.

This API throw an error if something goes wrong.

Path parameters
NameTypeDescription
tenantIdrequiredstringID of tenant
communityIdrequiredstringID of community
moduleIdrequiredstringID of module
Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
GEThttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/module/{moduleId}/test-connection
cURL
Node.js
Python
curl -X GET 'https://pilot-root.1kosmos.net/users-mgmt/tenant/xxxxxxxxxx/community/xxxxxxxxxxxxxxxxxxxxxxxx/module/xxxxxxxxxxxxxxxxxxxxxxxx/test-connection' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY'
RESPONSE
200
400
401
Success publicKey is publicKey of User Management API, useful for decryption response data is ECDSA encrypted object represents updated auth module: ``` { "_id": "ObjectID", "communityId": "ObjectID", "type": "db", // ad | ldap | db | azuread "subtype": "datastore", // for ad | ldap | azuread: "directory", for db: "datastore" "method": "authn", // for ad | ldap | db | azuread : "authn" "name": "Auth Module Name", "enabled": true, "mode": "broker/direct", "status": true, "message": "connection success/failed", "config": {} // see below config response samples } ``` config object for type **azuread**: ``` { "appName": "string", "tenantId": "string", "tenantName": "string", "clientId": "string", "clientSecret": "string", "loginBasePath": "string", "graphApiBasePath": "string" } ```
{
  "data": "xxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxx="
}
POST/tenant/{tenantId}/community/{communityId}/module/{moduleId}/update-hosts-status

Update auth module hosts status

Update the status of hosts in an auth module.

Path parameters
NameTypeDescription
tenantIdrequiredstring
communityIdrequiredstring
moduleIdrequiredstring
Headers
NameTypeDescription
licensekeyrequiredstring
requestidrequiredstring
publickeyrequiredstring
Request body
FieldTypeDescription
datarequiredobject
POSThttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/module/{moduleId}/update-hosts-status
cURL
Node.js
Python
curl -X POST 'https://pilot-root.1kosmos.net/users-mgmt/tenant/xxxxxxxxxxxxxxxxxxxxxxxx/community/xxxxxxxxxxxxxxxxxxxxxxxx/module/xxxxxxxxxxxxxxxxxxxxxxxx/update-hosts-status' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"data": {"hosts": {"attempts": [{"host": {"server": "ldap.example.com", "port": "389"}, "status": "failed", "ts": "2025-12-05T10:30:00Z"}]}, "app_name": "My Application", "app_id": "app-123456"}}'
RESPONSE
200
400
401
404
Success
{
  "message": "success"
}
POST/tenant/{tenantId}/community/{communityId}/modules/fetch

Fetch all auth modules.

Fetch all auth modules.

  • Key must be authorized for community.
  • Only a system, service and service_ext key can be used to fetch auth modules.

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Parameters

No Parameters

Returns

Returns all auth modules, encrypted with ECDSA and public key.

This API throw an error if something goes wrong.

Path parameters
NameTypeDescription
tenantIdrequiredstring
communityIdrequiredstring
Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
POSThttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/modules/fetch
cURL
Node.js
Python
curl -X POST 'https://pilot-root.1kosmos.net/users-mgmt/tenant/xxxxxxxxxx/community/xxxxxxxxxxxxxxxxxxxxxxxx/modules/fetch' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{}'
RESPONSE
200
400
401
404
Success publicKey is publicKey of User Management API, useful for decryption response data is ECDSA encrypted object represents auth modules: ``` { "modules": [ { "_id": "ObjectID", "communityId": "ObjectID", "type": "db", "subtype": "datastore", "method": "authn", "name": "Auth Module Name", "enabled": true, "lastEnabledAt": "date optional", "enhanced_security_on": false, "mode": "broker/direct", "config": {} // see below config response samples } ] } ``` config object for type **ad** or **ldap**: ``` { "hosts": [{ "server": "string", "port": "string", "lastSuccessAt": date, "lastNotifiedAt": date }], "hostTimeoutSeconds": "number optional - default = 10s", "hostRetryAfterMinutes": "number optional - default = 30m", "serverprotocol": "ldap", "server": "string", "serverport": "string", "binddn": "string", "bindpassword": "string", "basedn": "string", "securityauthentication": "Simple", "forcePasswordResetEnabled": false, "filter": "string", "serviceacctreadonly": true, "scepenabled": "boolean optional", "scepurl": "string optional", "challengeurl": "string optional", "scepagent": "string optional", "cert_enabled": "boolean optional", "cert_template": "string optional", // Alphabets, numerals, spaces, special characters allowed "dc_dns": "string optional", // DNS names can contain only alphabetic characters (A-Z, a-z), numeric characters (0-9), the minus sign (-), and the period (.) "dc_ca": "string optional", // up to 64 characters, ANSI character set "ldapqueryfilter": "string optional", "transformationJSB64": "string optional", "logfilesizemb": number, // it's only for BROKER "logfilecount": number, // it's only for BROKER "modified_at": date, // it's only for BROKER "etag": uuid, // it's only for BROKER "notificationAfterNoOfMinsDisconnect": "number optional", // default 5 "brokerDisconnectNotificationTo": "array optional", "brokerNotificationsEnabled": "boolean optional", // default false "hostStatusChangeNotificationsTo": "array optional", "hostStatusChangeNotificationsEnabled": "boolean optional", // default false "passwordPolicy": { "authtype": "string required", // Face | Fingerprint "allowed": boolean required, "rules": { "min": "number required", "min_enabled": boolean required, "min_special": "number required", "min_special_enabled": boolean required, "min_numbers": "number required", "min_numbers_enabled": boolean required, "special_chars_allowed": "string required", "special_chars_allowed_enabled": boolean required, "min_alpha_caps": "number required", "min_alpha_caps_enabled": boolean required, "noUsername": boolean required, "noUsername_enabled": boolean required, "allowInRow": "number required", "allowInRow_enabled": boolean required }, "descriptions": [ "string required" ] } } ``` config object for type **azuread**: ``` { "appName": "string", "tenantId": "string", "tenantName": "string", "clientId": "string", "clientSecret": "string", "loginBasePath": "string", "graphApiBasePath": "string" } ``` config for type **db**: ``` { "passwordPolicy": { "authtype": "string required", // Face | Fingerprint "allowed": boolean required, "rules": { "min": "number required", "min_enabled": boolean required, "min_special": "number required", "min_special_enabled": boolean required, "min_numbers": "number required", "min_numbers_enabled": boolean required, "special_chars_allowed": "string required", "special_chars_allowed_enabled": boolean required, "min_alpha_caps": "number required", "min_alpha_caps_enabled": boolean required, "noUsername": boolean required, "noUsername_enabled": boolean required, "allowInRow": "number required", "allowInRow_enabled": boolean required }, "descriptions": [ "string required" ] } } ```
{
  "data": "xxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxx="
}
PUT/tenant/{tenantId}/community/{communityId}/module/create

Create auth module.

Create auth module.

  • Only a system, service and service_ext key can be used to create auth module.
  • Key must be authorized for community.
  • Uniquey by type and community.
  • A keytab_uuid is issued if and when a kerberos.keytab_file is added

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Request Body

data (required)

Auth module data encrypted with ECDSA.

Returns

Returns the created auth module, encrypted with ECDSA and public key.

This API throw an error if something goes wrong.

Path parameters
NameTypeDescription
tenantIdrequiredstringID of tenant
communityIdrequiredstringID of community
Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
Request body

Request body contains 'data' field with encrypted object below:

IMPORTANT - you can send unencrypted data and you will get unecrypted data as well, it is only a preview available in Swagger.

for type db:

{
    "type": "db",
    "subtype": "datastore",
    "method": "authn",
    "name": "string required",
    "enabled": true,
    "mode": "direct",
    "config": {
        "passwordPolicy": {
           "authtype": "string required", // Face | Fingerprint
           "rules": {
           	"min": "number required",
           	"min_enabled": boolean required,
           	"min_special": "number required",
           	"min_special_enabled": boolean required,
           	"min_numbers": "number required",
           	"min_numbers_enabled": boolean required,
           	"special_chars_allowed": "string required",
           	"special_chars_allowed_enabled": boolean required,
           	"min_alpha_caps": "number required",
           	"min_alpha_caps_enabled": boolean required,
           	"noUsername": boolean required,
           	"noUsername_enabled": boolean required,
           	"allowInRow": "number required",
           	"allowInRow_enabled": boolean required
           },
           "descriptions": [
               "string required"
           ]
        }
    }
}

for direct ad/ldap:

{
    "type": "ad/ldap",
    "subtype": "directory",
    "method": "authn",
    "name": "string required",
    "enabled": true,
    "mode": "direct",
    "config": {
        "hosts": [{
            "server": "string optional",
            "port": "string optional",
        }],
        "hostTimeoutSeconds": "number optional - default = 10s",
        "hostRetryAfterMinutes": "number optional - default = 30m",
        "caList": [{
            "cert_template": "string optional",
            "dc_dns": "string optional",
            "dc_ca": "string optional"
        }],
        "caTimeoutSeconds": "number optional - default = 10s",
        "caRetryAfterMinutes": "number optional - default = 30m",
        "serverprotocol": "string required - ldap or ldaps",
        "server": "string required",
        "serverport": "string required",
        "binddn": "string required",
        "bindpassword": "string required",
        "basedn": "string required",
        "securityauthentication": "string required - Simple or Secure or Sealing or Encryption or SecureSocketLayer or ServerBind",
        "forcePasswordResetEnabled": "boolean optional",
        "filter": "string required",
        "serviceacctreadonly": "boolean required",
        "ldapqueryfilter": "string optional",
        "passwordPolicy": {
           "authtype": "string required", // Face | Fingerprint
           "rules": {
           	"min": "number required",
           	"min_enabled": boolean required,
           	"min_special": "number required",
           	"min_special_enabled": boolean required,
           	"min_numbers": "number required",
           	"min_numbers_enabled": boolean required,
           	"special_chars_allowed": "string required",
           	"special_chars_allowed_enabled": boolean required,
           	"min_alpha_caps": "number required",
           	"min_alpha_caps_enabled": boolean required,
           	"noUsername": boolean required,
           	"noUsername_enabled": boolean required,
           	"allowInRow": "number required",
           	"allowInRow_enabled": boolean required
           },
           "descriptions": [
               "string required"
           ]
        }
    }
}

for direct azuread:

{
    "type": "azuread",
    "subtype": "directory",
    "method": "authn",
    "name": "string required",
    "enabled": true,
    "mode": "direct",
    "config": {
        "appName": "string required",
        "tenantId": "string required",
        "tenantName": "string required",
        "clientId": "string required",
        "clientSecret": "string required",
        "loginBasePath": "string required",
        "graphApiBasePath": "string required"
    }
}

for broker ad/ldap:

{
    "type": "ad/ldap",
    "subtype": "directory",
    "method": "authn",
    "name": "string required",
    "enabled": true,
    "mode": "broker",
    "config": {
        "hosts": [{
            "server": "string optional",
            "port": "string optional",
        }],
        "hostTimeoutSeconds": "number optional - default = 10s",
        "hostRetryAfterMinutes": "number optional - default = 30m",
        "caList": [{
            "cert_template": "string optional",
            "dc_dns": "string optional",
            "dc_ca": "string optional"
        }],
        "caTimeoutSeconds": "number optional - default = 10s",
        "caRetryAfterMinutes": "number optional - default = 30m",
        "serverprotocol": "string optional - ldap or ldaps",
        "server": "string optional",
        "serverport": "string optional",
        "binddn": "string optional",
        "basedn": "string optional",
        "securityauthentication": "string optional - Simple or Secure or Sealing or Encryption or SecureSocketLayer or ServerBind",
        "forcePasswordResetEnabled": "boolean optional",
        "filter": "string optional",
        "serviceacctreadonly": "boolean optional",
        "scepenabled": "boolean optional",
        "scepurl": "string optional",
        "challengeurl": "string optional",
        "scepagent": "string optional",
        "cert_enabled": "boolean optional",
        "cert_template": "string optional", // Alphabets, numerals, spaces, special characters allowed
        "dc_dns": "string optional",  // DNS names can contain only alphabetic characters (A-Z, a-z), numeric characters (0-9), the minus sign (-), and the period (.)
        "dc_ca": "string optional", // up to 64 characters, ANSI character set
        "ldapqueryfilter": "string optional",
        "transformationJSB64": "string optional",
        "logfilesizemb": number optional, // default is 10, it's only for BROKER
        "logfilecount": number optional,  // default is 10, it's only for BROKER, floating values like 0.2 or 10.3  will be considered 0 or 10 respectively
        "notificationAfterNoOfMinsDisconnect": "number optional", // default 5
        "brokerDisconnectNotificationTo": "array optional",
        "brokerNotificationsEnabled": "boolean optional",         // default false
        "hostStatusChangeNotificationsTo": "array optional",
        "hostStatusChangeNotificationsEnabled": "boolean optional",         // default false
        "caStatusChangeNotificationsTo": "array optional",
        "caStatusChangeNotificationsEnabled": "boolean optional",         // default false
        "passwordPolicy": {
           "authtype": "string required", // Face | Fingerprint
           "rules": {
           	"min": "number required",
           	"min_enabled": boolean required,
           	"min_special": "number required",
           	"min_special_enabled": boolean required,
           	"min_numbers": "number required",
           	"min_numbers_enabled": boolean required,
           	"special_chars_allowed": "string required",
           	"special_chars_allowed_enabled": boolean required,
           	"min_alpha_caps": "number required",
           	"min_alpha_caps_enabled": boolean required,
           	"noUsername": boolean required,
           	"noUsername_enabled": boolean required,
           	"allowInRow": "number required",
           	"allowInRow_enabled": boolean required
           },
           "descriptions": [
               "string required"
           ]
        }
    },
    "kerberos_config": {
        "enabled": "boolean, required if kerberos_config is included",
        "keytab_file": "string (base64) required if kerberos_config is included",
    }
}
FieldTypeDescription
datastring
PUThttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/module/create
cURL
Node.js
Python
curl -X PUT 'https://pilot-root.1kosmos.net/users-mgmt/tenant/xxxxxxxxxx/community/xxxxxxxxxxxxxxxxxxxxxxxx/module/create' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"data": "xxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxx="}'
RESPONSE
200
400
401
Success publicKey is publicKey of User Management API, useful for decryption response data is ECDSA encrypted object represents created auth module: ``` { "_id": "ObjectID", "communityId": "ObjectID", "type": "db", // ad | ldap | db | azuread "subtype": "datastore", // for ad | ldap | azuread : "directory", for db: "datastore" "method": "authn", // for ad | ldap | db : "authn" "name": "Auth Module Name", "enabled": true, "mode": "broker/direct", "lastEnabledAt": "date optional", "enhanced_security_on": false, "config": {} // see below config response samples } ``` config object for type **ad** or **ldap**: ``` { "hosts": [{ "server": "string", "port": "string", "lastSuccessAt": date, "lastNotifiedAt": date }], "hostTimeoutSeconds": "number optional - default = 10s", "hostRetryAfterMinutes": "number optional - default = 30m", "caList": [{ "cert_template": "string optional", "dc_dns": "string optional", "dc_ca": "string optional" }], "caTimeoutSeconds": "number optional - default = 10s", "caRetryAfterMinutes": "number optional - default = 30m", "serverprotocol": "ldap", "server": "string" "serverport": "string" "binddn": "string", "bindpassword": "string", "basedn": "string", "securityauthentication": "Simple", "forcePasswordResetEnabled": false, "forcePasswordResetEnabled" : false, "filter": "string", "serviceacctreadonly": true, "scepenabled": "boolean", "scepurl": "string", "challengeurl": "string", "scepagent": "string", "cert_enabled": "boolean", "cert_template": "string", "dc_dns": "string", "dc_ca": "string", "ldapqueryfilter": "string", "transformationJSB64": "string optional", "logfilesizemb": number, // it's only for BROKER "logfilecount": number, // it's only for BROKER "modified_at": date, // it's only for BROKER "etag": uuid, // it's only for BROKER "notificationAfterNoOfMinsDisconnect": "number optional", // default 5 "brokerDisconnectNotificationTo": "array optional", "brokerNotificationsEnabled": "boolean optional", // default false "hostStatusChangeNotificationsTo": "array optional", "hostStatusChangeNotificationsEnabled": "boolean optional", // default false "caStatusChangeNotificationsTo": "array optional", "caStatusChangeNotificationsEnabled": "boolean optional", // default false "passwordPolicy": { "authtype": "string required", // Face | Fingerprint "allowed": boolean required, "rules": { "min": "number required", "min_enabled": boolean required, "min_special": "number required", "min_special_enabled": boolean required, "min_numbers": "number required", "min_numbers_enabled": boolean required, "special_chars_allowed": "string required", "special_chars_allowed_enabled": boolean required, "min_alpha_caps": "number required", "min_alpha_caps_enabled": boolean required, "noUsername": boolean required, "noUsername_enabled": boolean required, "allowInRow": "number required", "allowInRow_enabled": boolean required }, "descriptions": [ "string required" ] } } ``` config object for type **azuread** : ``` { "appName": "string", "tenantId": "string", "tenantName": "string", "clientId": "string", "clientSecret": "string", "loginBasePath": "string", "graphApiBasePath": "string" } ``` config for type **db**: ``` { "passwordPolicy": { "authtype": "string required", // Face | Fingerprint "allowed": boolean required, "rules": { "min": "number required", "min_enabled": boolean required, "min_special": "number required", "min_special_enabled": boolean required, "min_numbers": "number required", "min_numbers_enabled": boolean required, "special_chars_allowed": "string required", "special_chars_allowed_enabled": boolean required, "min_alpha_caps": "number required", "min_alpha_caps_enabled": boolean required, "noUsername": boolean required, "noUsername_enabled": boolean required, "allowInRow": "number required", "allowInRow_enabled": boolean required }, "descriptions": [ "string required" ] } } ```
{
  "data": "xxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxx="
}
PATCH/tenant/{tenantId}/community/{communityId}/module/{moduleId}

Update auth module.

Update auth module.

  • Key must be authorized for community.
  • Only a system, service and service_ext key can be used to update auth module.
  • A keytab_uuid is issued if and when a kerberos.keytab_file is added

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Request Body

data (required)

Auth module data encrypted with ECDSA.

Returns

Returns the updated auth module, encrypted with ECDSA and public key.

This API throw an error if something goes wrong.

Path parameters
NameTypeDescription
tenantIdrequiredstringID of tenant
communityIdrequiredstringID of community
moduleIdrequiredstring
Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
Request body

Request body contains 'data' field with encrypted object below:

IMPORTANT - you can send unencrypted data and you will get unecrypted data as well, it is only a preview available in Swagger.

IMPORTANT - you can set enabled = true only if config is valid

for type db:

{
    "name": "string optional",
    "enabled": true,
    "config": {
        "passwordPolicy": {
           "authtype": "string required", // Face | Fingerprint
           "rules": {
           	"min": "number required",
           	"min_enabled": boolean required,
           	"min_special": "number required",
           	"min_special_enabled": boolean required,
           	"min_numbers": "number required",
           	"min_numbers_enabled": boolean required,
           	"special_chars_allowed": "string required",
           	"special_chars_allowed_enabled": boolean required,
           	"min_alpha_caps": "number required",
           	"min_alpha_caps_enabled": boolean required,
           	"noUsername": boolean required,
           	"noUsername_enabled": boolean required,
           	"allowInRow": "number required",
           	"allowInRow_enabled": boolean required
           },
           "descriptions": [
               "string required"
           ]
        }
    }
}

for direct ad/ldap:

{
    "name": "string optional",
    "enabled": true,
    "config": {
        "hosts": [{
            "server": "string optional",
            "port": "string optional",
        }],
        "hostTimeoutSeconds": "number optional - default = 10s",
        "hostRetryAfterMinutes": "number optional - default = 30m",
        "serverprotocol": "string required - ldap or ldaps",
        "server": "string required",
        "serverport": "string required",
        "binddn": "string required",
        "bindpassword": "string required",
        "basedn": "string required",
        "securityauthentication": "string required - Simple or Secure or Sealing or Encryption or SecureSocketLayer or ServerBind",
        "forcePasswordResetEnabled": "boolean optional",
        "filter": "string required",
        "serviceacctreadonly": "boolean required",
        "ldapqueryfilter": "string optional",
        "passwordPolicy": {
           "authtype": "string required", // Face | Fingerprint
           "rules": {
           	"min": "number required",
           	"min_enabled": boolean required,
           	"min_special": "number required",
           	"min_special_enabled": boolean required,
           	"min_numbers": "number required",
           	"min_numbers_enabled": boolean required,
           	"special_chars_allowed": "string required",
           	"special_chars_allowed_enabled": boolean required,
           	"min_alpha_caps": "number required",
           	"min_alpha_caps_enabled": boolean required,
           	"noUsername": boolean required,
           	"noUsername_enabled": boolean required,
           	"allowInRow": "number required",
           	"allowInRow_enabled": boolean required
           },
           "descriptions": [
               "string required"
           ]
        }
    }
}

for direct azuread:

{
    "name": "string optional",
    "enabled": true,
    "config": {
        "appName": "string",
        "tenantId": "string",
        "tenantName": "string",
        "clientId": "string",
        "clientSecret": "string",
        "loginBasePath": "string",
        "graphApiBasePath": "string"
    }
}

for type broker ad/ldap:

{
    "name": "string optional",
    "enabled": true,
    "config": {
        "hosts": [{
            "server": "string optional",
            "port": "string optional",
        }],
        "hostTimeoutSeconds": "number optional - default = 10s",
        "hostRetryAfterMinutes": "number optional - default = 30m",
        "caList": [{
            "cert_template": "string optional",
            "dc_dns": "string optional",
            "dc_ca": "string optional"
        }],
        "caTimeoutSeconds": "number optional - default = 10s",
        "caRetryAfterMinutes": "number optional - default = 30m",
        "serverprotocol": "string optional - ldap or ldaps",
        "server": "string optional",
        "serverport": "string optional",
        "binddn": "string optional",
        "basedn": "string optional",
        "securityauthentication": "string optional - Simple or Secure or Sealing or Encryption or SecureSocketLayer or ServerBind",
        "forcePasswordResetEnabled" : "boolean optional",
        "filter": "string optional",
        "serviceacctreadonly": "boolean optional",
        "scepenabled": "boolean optional",
        "scepurl": "string optional",
        "challengeurl": "string optional",
        "scepagent": "string optional",
        "cert_enabled": "boolean optional",
        "cert_template": "string optional", // Alphabets, numerals, spaces, special characters allowed
        "dc_dns": "string optional",  // DNS names can contain only alphabetic characters (A-Z, a-z), numeric characters (0-9), the minus sign (-), and the period (.)
        "dc_ca": "string optional", // up to 64 characters, ANSI character set
        "ldapqueryfilter": "string optional",
        "transformationJSB64": "string optional",
        "logfilesizemb": number optional, // default is 10, it's only for BROKER
        "logfilecount": number optional,  // default is 10, it's only for BROKER
        "notificationAfterNoOfMinsDisconnect": "number optional", // default 5
        "brokerDisconnectNotificationTo": "array optional",
        "brokerNotificationsEnabled": "boolean optional",        // default false
        "hostStatusChangeNotificationsTo": "array optional",
        "hostStatusChangeNotificationsEnabled": "boolean optional",         // default false
        "caStatusChangeNotificationsTo": "array optional",
        "caStatusChangeNotificationsEnabled": "boolean optional",         // default false
        "passwordPolicy": {
           "authtype": "string required", // Face | Fingerprint
           "rules": {
           	"min": "number required",
           	"min_enabled": boolean required,
           	"min_special": "number required",
           	"min_special_enabled": boolean required,
           	"min_numbers": "number required",
           	"min_numbers_enabled": boolean required,
           	"special_chars_allowed": "string required",
           	"special_chars_allowed_enabled": boolean required,
           	"min_alpha_caps": "number required",
           	"min_alpha_caps_enabled": boolean required,
           	"noUsername": boolean required,
           	"noUsername_enabled": boolean required,
           	"allowInRow": "number required",
           	"allowInRow_enabled": boolean required
           },
           "descriptions": [
               "string required"
           ]
        }
    },
    "kerberos_config": {
        "enabled": "boolean optional",
        "keytab_file": "base64 string optional"
    }
}
FieldTypeDescription
datastring
PATCHhttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/module/{moduleId}
cURL
Node.js
Python
curl -X PATCH 'https://pilot-root.1kosmos.net/users-mgmt/tenant/xxxxxxxxxx/community/xxxxxxxxxxxxxxxxxxxxxxxx/module/xxxxxxxxxxxxxxxxxxxxxxxx' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"data": "xxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxx="}'
RESPONSE
200
400
401
Success publicKey is publicKey of User Management API, useful for decryption response data is ECDSA encrypted object represents updated auth module: ``` { "_id": "ObjectID", "communityId": "ObjectID", "type": "db", // ad | ldap | db "subtype": "datastore", // for ad | ldap: "directory", for db: "datastore" "method": "authn", // for ad | ldap | db : "authn" "name": "Auth Module Name", "enabled": true, "mode": "broker/direct", "lastEnabledAt": "date optional", "enhanced_security_on": false, "config": {} // see below config response samples } ``` config object for type **ad** or **ldap**: ``` { "hosts": [{ "server": "string optional", "port": "string optional", "lastSuccessAt": date, "lastNotifiedAt": date }], "hostTimeoutSeconds": "number optional - default = 10s", "hostRetryAfterMinutes": "number optional - default = 30m", "caList": [{ "cert_template": "string optional", "dc_dns": "string optional", "dc_ca": "string optional" }], "caTimeoutSeconds": "number optional - default = 10s", "caRetryAfterMinutes": "number optional - default = 30m", "serverprotocol": "ldap", "server": "string", "serverport": "string", "binddn": "string", "bindpassword": "string", "basedn": "string", "securityauthentication": "Simple", "forcePasswordResetEnabled": false, "forcePasswordResetEnabled": false, "filter": "string", "serviceacctreadonly": true, "ldapqueryfilter": "string optional", "scepenabled": "boolean optional", "scepurl": "string optional", "challengeurl": "string optional", "scepagent": "string optional", "cert_enabled": "boolean optional", "cert_template": "string optional", // Alphabets, numerals, spaces, special characters allowed "dc_dns": "string optional", // DNS names can contain only alphabetic characters (A-Z, a-z), numeric characters (0-9), the minus sign (-), and the period (.) "dc_ca": "string optional", // up to 64 characters, ANSI character set "ldapqueryfilter": "string optional", "transformationJSB64": "string optional", "logfilesizemb": number, // it's only for BROKER "logfilecount": number, // it's only for BROKER "modified_at": date, // it's only for BROKER "etag": uuid, // it's only for BROKER "notificationAfterNoOfMinsDisconnect": "number optional", // default 5 "brokerDisconnectNotificationTo": "array optional", "brokerNotificationsEnabled": "boolean optional", // default false "hostStatusChangeNotificationsTo": "array optional", "hostStatusChangeNotificationsEnabled": "boolean optional", // default false "caStatusChangeNotificationsTo": "array optional", "caStatusChangeNotificationsEnabled": "boolean optional", // default false "passwordPolicy": { "authtype": "string required", // Face | Fingerprint "allowed": boolean required, "rules": { "min": "number required", "min_enabled": boolean required, "min_special": "number required", "min_special_enabled": boolean required, "min_numbers": "number required", "min_numbers_enabled": boolean required, "special_chars_allowed": "string required", "special_chars_allowed_enabled": boolean required, "min_alpha_caps": "number required", "min_alpha_caps_enabled": boolean required, "noUsername": boolean required, "noUsername_enabled": boolean required, "allowInRow": "number required", "allowInRow_enabled": boolean required }, "descriptions": [ "string required" ] } } ``` config object for type **azuread**: ``` { "appName": "string", "tenantId": "string", "tenantName": "string", "clientId": "string", "clientSecret": "string", "loginBasePath": "string", "graphApiBasePath": "string" } ``` config for type **db**: ``` { "passwordPolicy": { "authtype": "string required", // Face | Fingerprint "allowed": boolean required, "rules": { "min": "number required", "min_enabled": boolean required, "min_special": "number required", "min_special_enabled": boolean required, "min_numbers": "number required", "min_numbers_enabled": boolean required, "special_chars_allowed": "string required", "special_chars_allowed_enabled": boolean required, "min_alpha_caps": "number required", "min_alpha_caps_enabled": boolean required, "noUsername": boolean required, "noUsername_enabled": boolean required, "allowInRow": "number required", "allowInRow_enabled": boolean required }, "descriptions": [ "string required" ] } } ```
{
  "data": "xxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxx="
}
DELETE/tenant/{tenantId}/community/{communityId}/module/{moduleId}

Delete auth module by moduleId.

Delete auth module by moduleId.

  • Key must be authorized for community.
  • Only a system, service and service_ext key can be used to delete auth modules.
  • <b>WARNING: When deleting auth module of type db, All users of the related community will be deleted from DB.</b>

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Parameters

No Parameters

Returns

No content.

This API throw an error if something goes wrong.

Path parameters
NameTypeDescription
tenantIdstring
communityIdrequiredstring
moduleIdrequiredstring
Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
DELETEhttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/module/{moduleId}
cURL
Node.js
Python
curl -X DELETE 'https://pilot-root.1kosmos.net/users-mgmt/tenant/xxxxxxxxxx/community/xxxxxxxxxxxxxxxxxxxxxxxx/module/xxxxxxxxxxxxxxxxxxxxxxxx' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY'
RESPONSE
204
400
401
404
Success Empty response
// no response body
User Management

User Attribute

Manage user attributes.

GET/tenant/{tenantId}/community/{communityId}/attribute/{attributeId}/attributes

Get attributes shared authModule with attributeId.

Get all user attributes of the same directory/authModule as to the attribute identified by attributId.

  • Key must be authorized for community.
  • Only a system, service and service_ext key can be used to create user attributes.

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Returns

Returns all user attributes of auth module.

This API throw an error if something goes wrong.

Path parameters
NameTypeDescription
tenantIdrequiredstringID of tenant
communityIdrequiredstringID of community
attributeIdrequiredstringID of an User Attribute
Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
GEThttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/attribute/{attributeId}/attributes
cURL
Node.js
Python
curl -X GET 'https://pilot-root.1kosmos.net/users-mgmt/tenant/xxxxxxxxxx/community/xxxxxxxxxxxxxxxxxxxxxxxx/attribute/xxxxxxxxxxxxxxxxxxxxxxxx/attributes' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY'
RESPONSE
200
400
401
Success User attributes list: ``` [ { "_id": "ObjectID", "name": "first_name", "attribute": "firstname", "moduleId": "ObjectId" } ] ``` User attributes list not found: ``` [] ```
[
  {
    "_id": "xxxxxxxxxxxxxxxxxxxxxxxx",
    "name": "xxxx",
    "attribute": "xxxx",
    "moduleId": "xxxxxxxxxxxxxxxxxxxxxxxx"
  }
]
GET/tenant/{tenantId}/community/{communityId}/attributes

Get all user attribute of auth module.

Get all user attribute for auth module.

  • Key must be authorized for community.
  • Only a system, service and service_ext key can be used to create user attributes.

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Returns

Returns all user attributes of auth module.

This API throw an error if something goes wrong.

Path parameters
NameTypeDescription
tenantIdrequiredstringID of tenant
communityIdrequiredstringID of community
Query parameters
NameTypeDescription
moduleIdrequiredstringID of auth module
Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
GEThttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/attributes
cURL
Node.js
Python
curl -X GET 'https://pilot-root.1kosmos.net/users-mgmt/tenant/xxxxxxxxxx/community/xxxxxxxxxxxxxxxxxxxxxxxx/attributes?moduleId=xxxxxxxxxxxxxxxxxxxxxxxx' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY'
RESPONSE
200
400
401
Success User attributes list: ``` [ { "_id": "ObjectID", "name": "first_name", "attribute": "firstname", "moduleId": "ObjectId" } ] ``` User attributes list not found: ``` [] ```
[
  {
    "_id": "xxxxxxxxxxxxxxxxxxxxxxxx",
    "name": "xxxx",
    "attribute": "xxxx",
    "moduleId": "xxxxxxxxxxxxxxxxxxxxxxxx"
  }
]
POST/tenant/{tenantId}/community/{communityId}/directoryattributes

Get Directory Attributes for the auth module.

Get directory attributes for the auth module.

  • Key must be authorized for community.
  • Only a system, service and service_ext key can be used to create user attributes.

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Request Body

pIndex (optional)

The pIndex key is a cursor for the pagination.

pSize (optional)

A limit on the number of objects to be returned. The range between 1 to 100 and the default is 25.

Returns

Returns directory attributes of auth module.

This API throw an error if something goes wrong.

Path parameters
NameTypeDescription
tenantIdrequiredstringID of tenant
communityIdrequiredstringID of community
Query parameters
NameTypeDescription
moduleIdrequiredstringID of auth module
Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
Request body

Request body contains object below:

{
    "pIndex": "number optional, default = 0",
    "pSize": "number optional, default = 25, min = 1, max = 100"
}
FieldTypeDescription
pIndexnumber
pSizenumber
POSThttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/directoryattributes
cURL
Node.js
Python
curl -X POST 'https://pilot-root.1kosmos.net/users-mgmt/tenant/xxxxxxxxxx/community/xxxxxxxxxxxxxxxxxxxxxxxx/directoryattributes?moduleId=xxxxxxxxxxxxxxxxxxxxxxxx' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"pIndex": 0, "pSize": 25}'
RESPONSE
200
400
401
404
Success Directory attributes of auth module: ``` { "page": { "index": 0, "total": 19, "size": 19 }, "data": [ "uid", "tenantId", "communityId", "username", "type", "roleValue", "status", "firstname", "middlename", "lastname", "email1", "email1_verified", "email2", "email2_verified", "phone1", "phone1_verified", "address", "address_verified", "disabled" ] } ```
{
  "page": {
    "index": 0,
    "total": 50,
    "size": 25
  },
  "data": [
    "attr1",
    "attr2"
  ]
}
PUT/tenant/{tenantId}/community/{communityId}/attributes

Create user attribute for auth module.

Create user attribute for auth module.

  • Key must be authorized for community.
  • Only a system, service and service_ext key can be used to create user attributes.

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Request Body

attributes (required)

List of user attributes to add for auth module.

Returns

Returns the created user attributes and errors if any.

This API throw an error if something goes wrong.

Path parameters
NameTypeDescription
tenantIdrequiredstringID of tenant
communityIdrequiredstringID of community
Query parameters
NameTypeDescription
moduleIdrequiredstringID of auth module
Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
Request body

List of user attributes to add for auth module.

{
    "attributes": [
        {
            "name": "string required, name of attribute",
            "attribute": "string required, attribute in data source"
        }
    ]
}
FieldTypeDescription
attributesarray<object>
PUThttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/attributes
cURL
Node.js
Python
curl -X PUT 'https://pilot-root.1kosmos.net/users-mgmt/tenant/xxxxxxxxxx/community/xxxxxxxxxxxxxxxxxxxxxxxx/attributes?moduleId=xxxxxxxxxxxxxxxxxxxxxxxx' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"attributes": [{"name": "xxxx", "attribute": "xxxx"}]}'
RESPONSE
200
400
401
Success Created user attributes and list of errors (if any): ``` { "created": [ { "_id": "ObjectID", "name": "first_name", "attribute": "firstname", "moduleId": "ObjectId" }, { "_id": "ObjectID", "name": "last_name", "attribute": "lastname", "moduleId": "ObjectId" } ] "errors": [ ] } ```
{
  "created": [
    {
      "_id": "xxxxxxxxxxxxxxxxxxxxxxxx",
      "name": "xxxx",
      "attribute": "xxxx",
      "moduleId": "xxxxxxxxxxxxxxxxxxxxxxxx"
    },
    {
      "_id": "xxxxxxxxxxxxxxxxxxxxxxxx",
      "name": "xxxx",
      "attribute": "xxxx",
      "moduleId": "xxxxxxxxxxxxxxxxxxxxxxxx"
    }
  ],
  "errors": [
    {
      "code": 401,
      "message": "xxxxxxxxxxx"
    }
  ]
}
PATCH/tenant/{tenantId}/community/{communityId}/attribute/{attributeId}

Update user attribute.

Update user attribute.

  • Key must be authorized for community.
  • Only a system, service and service_ext key can be used to create user attributes.

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Request Body

name (optional)

Name of attribute.

attribute (optional)

Identifier of attribute

Returns

Returns the updated user attributes.

This API throw an error if something goes wrong.

Path parameters
NameTypeDescription
tenantIdrequiredstringID of tenant
communityIdrequiredstringID of community
attributeIdrequiredstringID of user attribute
Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
Request body

User attribute fields to update.

{
    "name": "string required, name of attribute",
    "attribute": "string required, attribute in data source"
}
FieldTypeDescription
namestring
attributestring
PATCHhttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/attribute/{attributeId}
cURL
Node.js
Python
curl -X PATCH 'https://pilot-root.1kosmos.net/users-mgmt/tenant/xxxxxxxxxx/community/xxxxxxxxxxxxxxxxxxxxxxxx/attribute/xxxxxxxxxxxxxxxxxxxxxxxx' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"name": "xxxx", "attribute": "xxxx"}'
RESPONSE
200
400
401
404
Success Updated user attribute: ``` { "_id": "ObjectID", "name": "first_name", "attribute": "firstname", "moduleId": "ObjectId" } ```
{
  "_id": "xxxxxxxxxxxxxxxxxxxxxxxx",
  "name": "xxxx",
  "attribute": "xxxx",
  "moduleId": "xxxxxxxxxxxxxxxxxxxxxxxx"
}
PATCH/tenant/{tenantId}/community/{communityId}/attributes

Bulk update user attributes.

Bulk update user attributes.

  • Key must be authorized for community.
  • Only a system, service and service_ext key can be used to update user attributes.

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Returns

Returns updated attributes of auth module and errors (if any).

This API throw an error if something goes wrong.

Path parameters
NameTypeDescription
tenantIdrequiredstringID of tenant
communityIdrequiredstringID of community
Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
Request body

List of user attributes to add for auth module.

{
    "attributes": [
        {
            "id": "string required",
            "name": "string required, name of attribute",
            "attribute": "string required, attribute in data source"
        }
    ]
}
FieldTypeDescription
attributesarray<object>
PATCHhttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/attributes
cURL
Node.js
Python
curl -X PATCH 'https://pilot-root.1kosmos.net/users-mgmt/tenant/xxxxxxxxxx/community/xxxxxxxxxxxxxxxxxxxxxxxx/attributes' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"attributes": [{"id": "xxxx", "name": "xxxx", "attribute": "xxxx"}]}'
RESPONSE
200
400
401
404
Success Created user attributes and list of errors (if any): ``` { "updated": [ { "_id": "ObjectID", "name": "first_name", "attribute": "firstname", "moduleId": "ObjectId" }, { "_id": "ObjectID", "name": "last_name", "attribute": "lastname", "moduleId": "ObjectId" } ] "errors": [ ] } ```
{
  "updated": [
    {
      "_id": "xxxxxxxxxxxxxxxxxxxxxxxx",
      "name": "xxxx",
      "attribute": "xxxx",
      "moduleId": "xxxxxxxxxxxxxxxxxxxxxxxx"
    },
    {
      "_id": "xxxxxxxxxxxxxxxxxxxxxxxx",
      "name": "xxxx",
      "attribute": "xxxx",
      "moduleId": "xxxxxxxxxxxxxxxxxxxxxxxx"
    }
  ],
  "errors": [
    {
      "code": 401,
      "message": "xxxxxxxxxxx"
    }
  ]
}
DELETE/tenant/{tenantId}/community/{communityId}/attribute/{attributeId}

Delete user attribute.

Remove user attribute.

  • Key must be authorized for community.
  • Only a system, service and service_ext key can be used to create user attributes.

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Request Body

name (optional)

Name of attribute.

attribute (optional)

Identifier of attribute

Returns

No content.

This API throw an error if something goes wrong.

Path parameters
NameTypeDescription
tenantIdrequiredstringID of tenant
communityIdrequiredstringID of community
attributeIdrequiredstringID of user attribute
Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
DELETEhttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/attribute/{attributeId}
cURL
Node.js
Python
curl -X DELETE 'https://pilot-root.1kosmos.net/users-mgmt/tenant/xxxxxxxxxx/community/xxxxxxxxxxxxxxxxxxxxxxxx/attribute/xxxxxxxxxxxxxxxxxxxxxxxx' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY'
RESPONSE
204
400
401
404
Success No Content
// no response body
User Management

System User

System User endpoints.

POST/systemuser/authenticate

Verify system user password.

Verify system user password.

  • Any valid key can be used to verify system user password.
  • Only systemuser type user will be verified.

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Request Body

data (required)

username and password json, encrypted with ECDSA.

Returns

Returns the verification status.

This API throw an error if something goes wrong.

Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
Request body

Request body contains 'data' field with encrypted object below:

IMPORTANT - you can send unencrypted data and you will get unecrypted data as well, it is only a preview available in Swagger.

{
    "username": "string required",
    "password": "string required"
}
FieldTypeDescription
datastring
POSThttps://pilot-root.1kosmos.net/users-mgmt/systemuser/authenticate
cURL
Node.js
Python
curl -X POST 'https://pilot-root.1kosmos.net/users-mgmt/systemuser/authenticate' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"data": "xxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxx="}'
RESPONSE
200
400
401
Success
{
  "status": true
}
POST/systemuser/changepassword

Change system user password.

Change system user password.

  • Only a system and a service key can be used to change system user password.

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Request Body

data (required)

username and newPassword json, encrypted with ECDSA.

Returns

Returns empty response.

This API throw an error if something goes wrong.

Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
Request body

Request body contains 'data' field with encrypted object below:

IMPORTANT - you can send unencrypted data and you will get unecrypted data as well, it is only a preview available in Swagger.

{
    "username": "string required",
    "newPassword": "string required"
}
FieldTypeDescription
datastring
POSThttps://pilot-root.1kosmos.net/users-mgmt/systemuser/changepassword
cURL
Node.js
Python
curl -X POST 'https://pilot-root.1kosmos.net/users-mgmt/systemuser/changepassword' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"data": "xxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxx="}'
RESPONSE
200
400
401
Success Empty response
// no response body
POST/systemusers/fetch

Fetch all system users.

Fetch all system users.

  • Only a system and a service key can be used to fetch system users.
  • Returned users will be the type of 'systemuser'.

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Request Body

pIndex (optional)

The pIndex key is a cursor for the pagination. Default is 0.

pSize (optional)

A limit on the number of objects to be returned. The range between 1 to 100 and the default is 25.

query (optional)

The query to filter users.

attributes (optional)

This will drive response_user.dir_attributes.

authModule (optional)

This tells what auth module should be used for attribute mapping.

Returns

Returns the system users with pagination.

This API throw an error if something goes wrong.

Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
Request body

Request body contains object below:

{
    "pIndex": "number optional, default = 0",
    "pSize": "number optional, default = 25, min = 1, max = 100",
    "query": "query object optional",
    "attributes": "array of attributes, optional",
    "authModule": "string optional"
}
FieldTypeDescription
pIndexnumber
pSizenumber
queryobject
attributesarray<object>
authModulestring
POSThttps://pilot-root.1kosmos.net/users-mgmt/systemusers/fetch
cURL
Node.js
Python
curl -X POST 'https://pilot-root.1kosmos.net/users-mgmt/systemusers/fetch' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"pIndex": 0, "pSize": 25, "query": {}, "attributes": [], "authModule": "xxxxxxxxxxx"}'
RESPONSE
200
400
401
Success System users fetch result with pagination details. ``` { "page": { "index": 0, page number, starting from 0 "total": 50, total number of records "size": 10 number of records, per page }, "data": [{ "username": "username", "uid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "dguid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "status": "active", "roleValue": "none", "type": "basic", "moduleId": "moduleId", "onboarding_status": "tbd", "email": "email", "firstname": "Firstname", "lastname": "Lastname", "phone": "xxxxxx" }] } ```
{
  "page": {
    "index": 0,
    "total": 50,
    "size": 25
  },
  "data": [
    {
      "username": "xxxxx",
      "uid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "dguid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "status": "xxxxxx",
      "roleValue": "xxxxx",
      "type": "xxxxx",
      "moduleId": "xxxxxx",
      "onboarding_status": "tbd",
      "email": "xxxxxx",
      "firstname": "xxxxxx",
      "lastname": "xxxxxx",
      "phone": "xxxxxx"
    }
  ]
}
PUT/systemuser

Create system user.

Create system user.

  • Only a system and a service key can be used to create a system user.
  • Created user will be the type of 'systemuser'.
  • The communityId will be set to 'any' for the created user.
  • The roleValue will be set to 'none'

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Request Body

data (required)

User data encrypted with ECDSA

Returns

Returns the created system user, encrypted with ECDSA and public key.

This API throw an error if something goes wrong.

Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
Request body

Request body contains 'data' field with encrypted object below:

IMPORTANT - you can send unencrypted data and you will get unecrypted data as well, it is only a preview available in Swagger.

{
    "tenantId": "string required",
    "username": "string required",
    "password": "string required",
    "status": "string optional - active or locked or disabled, default = active",
    "firstname": "string required",
    "middlename": "string optional",
    "lastname": "string required",
    "email1": "string required - valid email address",
    "email1_verified": "boolean required",
    "email2": "string optional - valid email address",
    "email2_verified": "boolean optional",
    "phone1": "string optional - only digits",
    "phone1_verified": "boolean optional",
    "address": {
        "house": "string optional",
        "streetname": "string optional",
        "city": "string optional",
        "state": "string optional",
        "country": "string optional",
        "zip": "string optional"
    },
    "address_verified": "boolean optional",
    "disabled": "boolean optional",
    "roleValue": "string optional"
}
FieldTypeDescription
datastring
PUThttps://pilot-root.1kosmos.net/users-mgmt/systemuser
cURL
Node.js
Python
curl -X PUT 'https://pilot-root.1kosmos.net/users-mgmt/systemuser' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"data": "xxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxx="}'
RESPONSE
200
400
401
Success publicKey is publicKey of User Management API, useful for decryption response data is ECDSA encrypted object represents created user: ``` { "uid": "748da031-c45e-4abd-930e-75b4929e6503", "tenantId": "123-456", "communityId": "any", "roleValue": "none", "username": "Username", "type": "systemuser", "status": "active", "firstname": "First name", "middlename": "Middle name", "lastname": "Last name", "email1": "bu-1@gmail.com", "email1_verified": true, "email2": "bu-11@gmail.com", "email2_verified": true, "phone1": "11111111", "phone1_verified": true, "address": { "house": "House", "streetname": "Street name", "city": "City", "state": "State", "country": "Country", "zip": "11111" }, "address_verified": true, "disabled": false } ```
{
  "data": "xxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxx="
}
PATCH/systemuser/{uid}

Update system user.

Update system user.

  • Only a system and a service key can be used to update system user.
  • Only systemuser user will be updated.
  • roleValue, uid, username, password cannot be updated.
  • Only provided attributes will be updated.

Parameters

uid (required)

The uid of system user.

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Request Body

tenantId (optional)

This key sets the tenant id of a user.

type (optional)

This key sets the type of a user. The type key only accept these values ("systemuser", "basic").

status (optional)

This key sets the status of a user. The type key only accept these values ("active", "locked", "disabled").

firstname (optional)

This key sets the first name of a user.

middlename (optional)

This key sets the middle name of a user.

lastname (optional)

This key sets the last name of a user.

email1 (optional)

This key sets the first email of a user.

email1_verified (optional)

This key sets the verification status of the first email.

email2 (optional)

This key sets the second email of the user.

emaild_verified (optional)

This key sets the verification status of the second email.

phone1 (optional)

This key sets the phone number of a user.

phone1_verified (optional)

This key sets the verification status of the phone number.

address (optional object)

This key sets the address of the user.

address_verified (optional)

This key sets the verification status of the address.

disabled (optional)

This key sets disabled status of a user. The disabled key only accept these values (true, false).

roleValue (optional)

This key sets roleValue of the user

Returns

Returns the updated system user.

This API throw an error if something goes wrong.

Path parameters
NameTypeDescription
uidrequiredstringUID of user.
Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
Request body

Request body contains below fields to update system user.

{
    "tenantId": "string optional",
    "type": "string optional - systemuser or basic",
    "status": "string optional - active or locked or disabled",
    "firstname": "string optional",
    "middlename": "string optional",
    "lastname": "string optional",
    "email1": "string optional - valid email address",
    "email1_verified": "boolean optional",
    "email2": "string optional - valid email address",
    "email2_verified": "boolean optional",
    "phone1": "string optional - only digits",
    "phone1_verified": "boolean optional",
    "address": {
        "house": "string optional",
        "streetname": "string optional",
        "city": "string optional",
        "state": "string optional",
        "country": "string optional",
        "zip": "string optional"
    },
    "address_verified": "boolean optional",
    "disabled": "boolean optional",
    "roleValue": "none"
}
FieldTypeDescription
tenantIdstring
statusstring
firstnamestring
middlenamestring
lastnamestring
email1string
email1_verifiedstring
email2string
email2_verifiedstring
phone1string
phone1_verifiedstring
addressstring
address_verifiedstring
disabledstring
roleValuestring
PATCHhttps://pilot-root.1kosmos.net/users-mgmt/systemuser/{uid}
cURL
Node.js
Python
curl -X PATCH 'https://pilot-root.1kosmos.net/users-mgmt/systemuser/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"tenantId": "xxxxxxxxxx", "status": "xxxxxx", "firstname": "xxxxxxxx", "middlename": "xxxxxxxx", "lastname": "xxxxxxxx", "email1": "xxxxx@xxxxxxxx.xxx", "email1_verified": true, "email2": "xxxxx@xxxxxxxx.xxx", "email2_verified": true, "phone1": "xxxxxxxxxx", "phone1_verified": true, "address": {}, "address_verified": false, "disabled": false, "roleValue": "xxxxxx"}'
RESPONSE
200
400
401
404
Success Updated user object: ``` { "uid": "748da031-c45e-4abd-930e-75b4929e6503", "communityId": "any", "roleValue": "none", "tenantId": "123-456", "username": "Username", "type": "systemuser", "status": "active", "firstname": "First name", "middlename": "Middle name", "lastname": "Last name", "email1": "bu-1@gmail.com", "email1_verified": true, "email2": "bu-11@gmail.com", "email2_verified": true, "phone1": "11111111", "phone1_verified": true, "address": { "house": "House", "streetname": "Street name", "city": "City", "state": "State", "country": "Country", "zip": "11111" }, "address_verified": true, "disabled": false } ```
{
  "uid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "tenantId": "xxxxxxxxxx",
  "communityId": "xxxxxxxxxxxxxxxxxxxxxxxx",
  "username": "xxxxxx",
  "type": "xxxxx",
  "roleValue": "xxxxx",
  "status": "xxxxxx",
  "firstname": "xxxxxxxx",
  "middlename": "xxxxxxxx",
  "lastname": "xxxxxxxx",
  "email1": "xxxxx@xxxxxxxx.xxx",
  "email1_verified": true,
  "email2": "xxxxx@xxxxxxxx.xxx",
  "email2_verified": true,
  "phone1": "xxxxxxxxxx",
  "phone1_verified": true,
  "address": {},
  "address_verified": false,
  "disabled": false
}
User Management

Behavior Auth

Behavior Auth endpoints.

POST/tenant/{tenantId}/community/{communityId}/user/behavior_auth/random_phrase/fetch

Fetch random phrase for behavior authentication

Fetch a random phrase for behavior authentication.

Authorization:

  • System and infra_license_key callers do not require a JWT.
  • All other license auth levels (service, app, app_ext, etc.) must include a valid JWT.

Encrypted payload:

Request body must contain a data field (encrypted string) and a decrypted preview:

{
  "data": {
    "jwt": "string (optional — required for non-system/non-infra license)",
    "language": "string (optional — one of: en, es, pt, fr, de. Defaults to en if not provided)"
  }
}
  • If JWT is required, it must be verified and have "isAuthenticated: true".
  • If language is not provided or unsupported, defaults to "en". Empty string is not accepted.
Path parameters
NameTypeDescription
tenantIdrequiredstring
communityIdrequiredstring
Request body
FieldTypeDescription
datarequiredobject
POSThttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/user/behavior_auth/random_phrase/fetch
cURL
Node.js
Python
curl -X POST 'https://pilot-root.1kosmos.net/users-mgmt/tenant/<tenantId>/community/<communityId>/user/behavior_auth/random_phrase/fetch' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"data": {"jwt": "string", "language": "en"}}'
RESPONSE
200
400
401
Encrypted response containing random phrase and user token. Decrypted preview
{
  "data": {
    "phrase": "string",
    "user_token": "string",
    "language": "string"
  },
  "publicKey": "string"
}
POST/tenant/{tenantId}/community/{communityId}/user/behavior_auth/register

Register behavior authentication (phrase/pattern)

Register a phrase and typing pattern for a user.

Authorization:

  • Requires system/service level key.
  • If app/app_ext/service_ext key is used, request body must include a valid JWT.

Encrypted payload:

Request body must contain a data field (encrypted string) and a decrypted preview:

{
  "authModule": "string (required)",
  "username": "string (required)",
  "phrase": "string (required)",
  "pattern": "string (base64, required)",
  "jwt": "string (required for app/app_ext/service_ext)",
  "user_token": "string (required)",
  "eventInfo": {
    "clientIp": "string (optional)",
    "userAgent": "string (optional)"
  }
}
  • JWT must be verified and have "isAuthenticated: true".
  • Username in JWT must match username in request body.
  • user_token must be valid (private decryption).
  • If user already has a phrase registered, call fails (NOT_ALLOWED).
  • If first attempt, user-token.attempts = 0.
  • Calls Typing to delete and register pattern.
  • If attempts === required attempts (from CaaS config), updates user props.
  • If more attempts needed, bakes new user token.
  • Returns next_step: done | try again, user_token: encrypted.
  • Optional eventInfo allows passing custom client IP and user agent for event logging.
  • Emits E_BEHAVIOR_AUTH_ENROLLED event on success.
Path parameters
NameTypeDescription
tenantIdrequiredstring
communityIdrequiredstring
Request body
FieldTypeDescription
datarequiredobject
POSThttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/user/behavior_auth/register
cURL
Node.js
Python
curl -X POST 'https://pilot-root.1kosmos.net/users-mgmt/tenant/<tenantId>/community/<communityId>/user/behavior_auth/register' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"data": {"authModule": "string", "username": "string", "phrase": "string", "pattern": "string", "jwt": "string", "user_token": "string", "eventInfo": {"clientIp": "string", "userAgent": "string"}}}'
RESPONSE
200
400
401
405
Registration successful. Encrypted response with next_step and user_token.
{
  "next_step": "done",
  "user_token": "string"
}
POST/tenant/{tenantId}/community/{communityId}/user/behavior_auth/validate

Validate behavior authentication (typing pattern)

Validate a user's typing pattern for behavior authentication.

Authorization:

  • Any valid community license key can be used.

Encrypted payload:

Request body must contain a data field (encrypted string) and a decrypted preview:

{
  "authModule": "string (required)",
  "username": "string (required)",
  "pattern": "string (base64, required)",
  "eventInfo": {
    "clientIp": "string (optional)",
    "userAgent": "string (optional)"
  }
}
  • Validates caller and user (must not be locked or disabled).
  • Calls Typing to validate pattern using userId = SHA512(user.urn).
  • On any validation failure, returns 401 Unauthorized.
  • On success, returns same payload as user authenticate API, with JWT containing "methods": ["behavior_auth"].
  • Optional eventInfo allows passing custom client IP and user agent for event logging.
Path parameters
NameTypeDescription
tenantIdrequiredstring
communityIdrequiredstring
Request body
FieldTypeDescription
datarequiredobject
POSThttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/user/behavior_auth/validate
cURL
Node.js
Python
curl -X POST 'https://pilot-root.1kosmos.net/users-mgmt/tenant/<tenantId>/community/<communityId>/user/behavior_auth/validate' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"data": {"authModule": "string", "username": "string", "pattern": "string", "eventInfo": {"clientIp": "string", "userAgent": "string"}}}'
RESPONSE
200
400
401
Validation successful. Encrypted response with JWT and user info.
{
  "data": {
    "jwt": "string",
    "user": {},
    "methods": [
      "string"
    ]
  },
  "publicKey": "string"
}
DELETE/tenant/{tenantId}/community/{communityId}/user/behavior_auth/deregister

Deregister (unenroll) behavior authentication for a user

Deregisters (unenrolls) a user's behavior authentication (typing phrase/pattern).

Authorization:

  • Requires system/service key for the community, OR
  • A valid JWT in the request body (with isAuthenticated: true) and service_ext/app/app_ext license key.

Encrypted payload:

Request body must contain a data field (encrypted string) and a decrypted preview:

{
  "authModule": "string (required)",
  "username": "string (required)",
  "jwt": "string (required for app/app_ext license)",
  "eventInfo": {
    "clientIp": "string (optional)",
    "userAgent": "string (optional)",
    "initiatedBy": "string (optional, username of the initiator)"
  }
}
  • If JWT is required, it must be present, valid (via AuthN), and have isAuthenticated: true.
  • Optional eventInfo.initiatedBy specifies the username who initiated the action (for event logging).
  • Calls Typing to delete pattern using userId = SHA512(user.urn).
  • If no phrase is registered, returns 204 No Content.
  • If phrase is registered, deletes and returns 204 No Content.
  • Optional eventInfo allows passing custom client IP and user agent for event logging.
  • Emits E_BEHAVIOR_AUTH_UNENROLLED event with full context.
Path parameters
NameTypeDescription
tenantIdrequiredstring
communityIdrequiredstring
Request body
FieldTypeDescription
datarequiredobject
DELETEhttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/user/behavior_auth/deregister
cURL
Node.js
Python
curl -X DELETE 'https://pilot-root.1kosmos.net/users-mgmt/tenant/<tenantId>/community/<communityId>/user/behavior_auth/deregister' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"data": {"authModule": "string", "username": "string", "jwt": "string", "eventInfo": {"clientIp": "string", "userAgent": "string", "initiatedBy": "string"}}}'
RESPONSE
204
400
401
Unenrollment successful. No content.
// no response body
User Management

Broker Connection

Broker Connection endpoints.

GET/tenant/{tenantId}/community/{communityId}/module/{moduleId}/broker/fetch

Fetch Broker Connections by CommunityId and AuthModuleId

Fetch Broker Connections by CommunityId and AuthModuleId

  • License Key must be authorized for community.
  • Only a system and service key can be used to fetch brokerConnection of communityId and authModuleId.

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Returns

Returns all broker connections of community and authModule.

This API throw an error if something goes wrong.

Path parameters
NameTypeDescription
tenantIdrequiredstringID of tenant
communityIdrequiredstringID of community
moduleIdrequiredstringID of auth module
Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
GEThttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/module/{moduleId}/broker/fetch
cURL
Node.js
Python
curl -X GET 'https://pilot-root.1kosmos.net/users-mgmt/tenant/xxxxxxxxxx/community/xxxxxxxxxxxxxxxxxxxxxxxx/module/xxxxxxxxxxxxxxxxxxxxxxxx/broker/fetch' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY'
RESPONSE
200
400
401
Success List of Broker connection: ``` [ { "_id": "6144aa82eebec1d23cca4f2c", "uid": "6144aa82eebec1d23cca4f2c", "name": "Broker", "communityId": "5f3d8d0cd866fa61019cf969", "authModuleId": "614084282494d47759868179", "enabled": true, "authorized": true, "connected": true, "version": "V 13.3", "connectedAt": "2021-09-15T08:33:02.900Z" "lastPingAt": "2021-09-15T08:33:02.900Z", "lastDisconnectedAt": "2021-09-15T08:33:02.900Z", "lastNotificationSentAt": "2021-09-15T08:33:02.900Z", "ip": "123.123.123.123", "port": "1234" } ] ```
[
  {
    "_id": "xxxxxxxxxxxxxxxxxxxxxxxx",
    "uid": "xxxxxxxxxxxxxxxxxxxxxxxx",
    "name": "xxxxxx",
    "communityId": "xxxxxxxxxxxxxxxxxxxxxxxx",
    "authModuleId": "xxxxxxxxxxxxxxxxxxxxxxxx",
    "enabled": true,
    "authorized": true,
    "connected": true,
    "version": "xxxxx",
    "connectedAt": "xxxx-xx-xxTxx:xx:xx.xxxx",
    "lastPingAt": "xxxx-xx-xxTxx:xx:xx.xxxx",
    "lastDisconnectedAt": "xxxx-xx-xxTxx:xx:xx.xxxx",
    "lastNotificationSentAt": "xxxx-xx-xxTxx:xx:xx.xxxx",
    "ip": "xxxxx",
    "port": "xxxxx"
  }
]
PATCH/tenant/{tenantId}/community/{communityId}/module/{moduleId}/broker/changestatus

enable/disable broker by the community & auth module & uid

enable/disable broker by the community & auth module & uid.

  • Key must be authorized for community.
  • Only a system and service key can be used to enable/disable broker by the community & auth module & uid.
  • Broker with requested uid must be for requested community/authModule.
  • Only Authorized brokers (authorized = true) can be enabled.

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Request Body

uuid (required)

UUID of broker connection.

enabled (required)

This key sets the enable status of broker connection.

Returns

Returns the updated broker connection.

This API throw an error if something goes wrong.

Path parameters
NameTypeDescription
tenantIdrequiredstringID of tenant
communityIdrequiredstringID of community
moduleIdrequiredstringID of auth module
Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
Request body

Broker connection status to update.

{
    "uid": "required"
    "enabled": "boolean, true or false"
}
FieldTypeDescription
uidstring
enabledboolean
PATCHhttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/module/{moduleId}/broker/changestatus
cURL
Node.js
Python
curl -X PATCH 'https://pilot-root.1kosmos.net/users-mgmt/tenant/xxxxxxxxxx/community/xxxxxxxxxxxxxxxxxxxxxxxx/module/xxxxxxxxxxxxxxxxxxxxxxxx/broker/changestatus' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"uid": "xxxxxxxxxxxxxxxxxxxxxxxx", "enabled": true}'
RESPONSE
200
400
401
404
500
Success Updated broker connection: ``` { "_id": "xxxxxxxxxxxxxxxxxxxxxxxx", "uid": "xxxxxxxxxxxxxxxxxxxxxxxx", "name": "xxxxxx", "communityId": "xxxxxxxxxxxxxxxxxxxxxxxx", "authModuleId": "xxxxxxxxxxxxxxxxxxxxxxxx", "enabled": true, "authorized": true, "connected": true, "version": "V 13.3", "connectedAt": "xxxx-xx-xxTxx:xx:xx.xxxx" "lastPingAt": "xxxx-xx-xxTxx:xx:xx.xxxx", "lastDisconnectedAt": "xxxx-xx-xxTxx:xx:xx.xxxx", "lastNotificationSentAt": "xxxx-xx-xxTxx:xx:xx.xxxx", "ip": "xxxx", "port": "xxx" } ```
{
  "_id": "xxxxxxxxxxxxxxxxxxxxxxxx",
  "uid": "xxxxxxxxxxxxxxxxxxxxxxxx",
  "name": "xxxxxx",
  "communityId": "xxxxxxxxxxxxxxxxxxxxxxxx",
  "authModuleId": "xxxxxxxxxxxxxxxxxxxxxxxx",
  "enabled": true,
  "authorized": true,
  "connected": true,
  "version": "xxxxx",
  "connectedAt": "xxxx-xx-xxTxx:xx:xx.xxxx",
  "lastPingAt": "xxxx-xx-xxTxx:xx:xx.xxxx",
  "lastDisconnectedAt": "xxxx-xx-xxTxx:xx:xx.xxxx",
  "lastNotificationSentAt": "xxxx-xx-xxTxx:xx:xx.xxxx",
  "ip": "xxxxx",
  "port": "xxxxx"
}
PATCH/tenant/{tenantId}/community/{communityId}/module/{moduleId}/broker/update

Update broker connection name.

Update broker connection name.

  • Key must be authorized for community.
  • Only a system and service key can be used to enable/disable broker by the community & auth module & uid.
  • Broker with requested uid must be for requested community/authModule.
  • Only broker name can be edited via this API.

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Request Body

uuid (required)

UUID of broker connection.

name (required)

Name of broker connection.

Returns

Returns the updated broker connection.

This API throw an error if something goes wrong.

Path parameters
NameTypeDescription
tenantIdrequiredstringID of tenant
communityIdrequiredstringID of community
moduleIdrequiredstringID of auth module
Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
Request body

Broker connection name to update.

{
    "uid": "required",
    "name": "string required"
}
FieldTypeDescription
uidstring
namestring
PATCHhttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/module/{moduleId}/broker/update
cURL
Node.js
Python
curl -X PATCH 'https://pilot-root.1kosmos.net/users-mgmt/tenant/xxxxxxxxxx/community/xxxxxxxxxxxxxxxxxxxxxxxx/module/xxxxxxxxxxxxxxxxxxxxxxxx/broker/update' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"uid": "xxxxxxxxxxxxxxxxxxxxxxxx", "name": "xxxxxx"}'
RESPONSE
200
400
401
404
500
Success Updated broker connection: ``` { "_id": "ObjectID", "uid": "614084282494d47759868178", "name": "Broker name", "communityId": "5f3d8d0cd866fa61019cf969", "authModuleId": "614084282494d47759868179", "enabled": true, "authorized": true, "connected": true, "version": "V 13.3", "connectedAt": "2021-09-15T08:33:02.900Z" "lastPingAt": "2021-09-15T08:33:02.900Z", "lastDisconnectedAt": "2021-09-15T08:33:02.900Z", "lastNotificationSentAt": "2021-09-15T08:33:02.900Z", "ip": "123.123.123.123", "port": "1234" } ```
{
  "_id": "xxxxxxxxxxxxxxxxxxxxxxxx",
  "uid": "xxxxxxxxxxxxxxxxxxxxxxxx",
  "name": "xxxxxx",
  "communityId": "xxxxxxxxxxxxxxxxxxxxxxxx",
  "authModuleId": "xxxxxxxxxxxxxxxxxxxxxxxx",
  "enabled": true,
  "authorized": true,
  "connected": true,
  "version": "xxxxx",
  "connectedAt": "xxxx-xx-xxTxx:xx:xx.xxxx",
  "lastPingAt": "xxxx-xx-xxTxx:xx:xx.xxxx",
  "lastDisconnectedAt": "xxxx-xx-xxTxx:xx:xx.xxxx",
  "lastNotificationSentAt": "xxxx-xx-xxTxx:xx:xx.xxxx",
  "ip": "xxxxx",
  "port": "xxxx"
}
DELETE/tenant/{tenantId}/community/{communityId}/module/{moduleId}/broker/{uid}

Delete broker connection by communityId and authModuleId and uid of broker.

Delete broker connection by communityId and authModuleId and uid of broker.

  • License Key must be authorized for community.
  • Only a system and service key can be used to delete brokerConnection of communityId and authModuleId and uid of broker.
  • Broker with requested uid must be for requested community/authModule.

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Returns

No content.

This API throw an error if something goes wrong.

Path parameters
NameTypeDescription
tenantIdrequiredstringID of tenant
communityIdrequiredstringID of community
moduleIdrequiredstringID of auth module
uidrequiredstringUID of broker connection
Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
DELETEhttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/module/{moduleId}/broker/{uid}
cURL
Node.js
Python
curl -X DELETE 'https://pilot-root.1kosmos.net/users-mgmt/tenant/xxxxxxxxxx/community/xxxxxxxxxxxxxxxxxxxxxxxx/module/xxxxxxxxxxxxxxxxxxxxxxxx/broker/xxxxxxxxxxxxxxxxxxxxxxxx' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY'
RESPONSE
204
400
401
404
Success No Content
// no response body
User Management

Account Lockout

Lockout policy & state.

POST/tenant/{tenantId}/community/{communityId}/user/status

get user status.

get user status.

  • Only a system, service and service_ext key can be used to fetch a user status.

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Request Body

username (required)

username.

Returns

Returns get user statuses response.

This API throw an error if something goes wrong.

Path parameters
NameTypeDescription
tenantIdrequiredstringID of tenant
communityIdrequiredstringID of community
Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
Request body

Request body contains below fields to lock user.

{
    "username": "string required"
}
FieldTypeDescription
usernamestring
POSThttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/user/status
cURL
Node.js
Python
curl -X POST 'https://pilot-root.1kosmos.net/users-mgmt/tenant/xxxxxxxxxx/community/xxxxxxxxxxxxxxxxxxxxxxxx/user/status' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"username": "xxxxxx"}'
RESPONSE
200
400
401
404
Success get user status: ``` { "reasons": [{}] } ```
"string"
PUT/tenant/{tenantId}/community/{communityId}/user/lock

lock a user.

lock a user.

  • Only a system, service and service_ext key can be used to lock a user.
  • lock reason can be ['Admin Action'].

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Request Body

username (required)

username.

reason (required)

reasonCode: 0 and message: ['Admin Action'].

initiatedby (required)

initiatedby: [system]

Returns

Returns empty response.

This API throw an error if something goes wrong.

Path parameters
NameTypeDescription
tenantIdrequiredstringID of tenant
communityIdrequiredstringID of community
Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
Request body

Request body contains below fields to lock user.

{
    "username": "string required",
    "reason": {
    	"reasonCode": number required,  // 0 - Admin Action
        "message": "string required"    // ['Admin Action']
    },
    initiatedby: "string required"
}
FieldTypeDescription
usernamestring
reasonobject
initiatedbystring
PUThttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/user/lock
cURL
Node.js
Python
curl -X PUT 'https://pilot-root.1kosmos.net/users-mgmt/tenant/xxxxxxxxxx/community/xxxxxxxxxxxxxxxxxxxxxxxx/user/lock' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"username": "xxxxxx", "reason": {"reasonCode": 0, "message": "Admin Action"}, "initiatedby": "xxxxxxxx"}'
RESPONSE
200
400
401
404
Success Empty response
// no response body
PUT/tenant/{tenantId}/community/{communityId}/user/unlock

unlock a user.

unlock a user.

  • Only a system, service and service_ext key can be used to unlock a user.
  • lock reason can be ['Admin Action'].

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Request Body

username (required)

username.

reason (required)

reasonCode: 0/1 and message: ['Admin Action'].

initiatedby (required)

initiatedby: [system]

Returns

Returns empty response.

This API throw an error if something goes wrong.

Path parameters
NameTypeDescription
tenantIdrequiredstringID of tenant
communityIdrequiredstringID of community
Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
Request body

Request body contains below fields to lock user.

{
    "username": "string required",
    "reason": {
    	"reasonCode": number required,  // 0 - Admin Action
        "message": "string required"    // ['Admin Action']
    },
    initiatedby: "string required"
}
FieldTypeDescription
usernamestring
reasonobject
initiatedbystring
PUThttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/user/unlock
cURL
Node.js
Python
curl -X PUT 'https://pilot-root.1kosmos.net/users-mgmt/tenant/xxxxxxxxxx/community/xxxxxxxxxxxxxxxxxxxxxxxx/user/unlock' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"username": "xxxxxx", "reason": {"reasonCode": 0, "message": "Admin Action"}, "initiatedby": "xxxxxxxx"}'
RESPONSE
200
400
401
404
Success Empty response
// no response body
User Management

Account Lockout V 2

Account Lockout V 2 endpoints.

POST/v2/tenant/{tenantId}/community/{communityId}/user/lock/status

get user account status.

get user status.

  • Only a system and service key can be used to fetch a user status.

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Request Body

userId (required)

userId.

Returns

Returns get user statuses response.

This API throw an error if something goes wrong.

Path parameters
NameTypeDescription
tenantIdrequiredstringID of tenant
communityIdrequiredstringID of community
Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
Request body

Request body contains below fields to lock user.

{
    "userId": "string required"
}
FieldTypeDescription
userIdstring
POSThttps://pilot-root.1kosmos.net/users-mgmt/v2/tenant/{tenantId}/community/{communityId}/user/lock/status
cURL
Node.js
Python
curl -X POST 'https://pilot-root.1kosmos.net/users-mgmt/v2/tenant/xxxxxxxxxx/community/xxxxxxxxxxxxxxxxxxxxxxxx/user/lock/status' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"userId": "xxxxxx"}'
RESPONSE
200
400
401
404
Success get user status: ``` { "_id": "xxxxxxxxxxxx", "tenantId": "xxxxxxxxxx", "communityId": "xxxxxxxxxx", "userId": "xxxxxxxxxx", "lockedAt": "2023-10-03T14:38:49.708Z" "lockedBy": "xxxxxxxxxx", "locked": true, "message": "xxxxxxxxxxx", "expiryDate" : "2023-10-03T14:59:56.844Z", "updatedAt": "2023-10-03T14:38:49.708Z", } ```
{
  "_id": "xxxxxxxxx",
  "tenantId": "xxxxxxxx",
  "communityId": "xxxxxxxxx",
  "userId": "xxxxxx",
  "message": "Admin Action",
  "lockedBy": "xxxxxxxx",
  "locked": "true,",
  "lockedAt": "xxxxxxxxxxx",
  "expiresDate": "xxxxxxxxxxx",
  "updatedAt": "xxxxxxxxxxx"
}
PUT/v2/tenant/{tenantId}/community/{communityId}/user/lock

lock a user account.

lock a user account.

  • Only a system and service key can be used to lock a user.

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Request Body

userId (required)

userId.

message (optinal)

message: 'Admin Action'.

initiatedby (required)

initiatedby: [Admin userId]

expiryInMunites (optional)

expiryInMunites: Auto expiry time // expiryInMunites must be greater than current time. If Admin dont want to set auto expiry time then pass 0

Returns

Returns success message response.

This API throw an error if something goes wrong.

Path parameters
NameTypeDescription
tenantIdrequiredstringID of tenant
communityIdrequiredstringID of community
Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
Request body

Request body contains below fields to lock user.

{
    "userId": "string required",
    "message": "string optinal",   // ['Admin Action']
    "initiatedby": "string required",
    "expiryInMunites": 60

}
FieldTypeDescription
userIdstring
messagestring
initiatedbystring
expiryInMunitesstring
PUThttps://pilot-root.1kosmos.net/users-mgmt/v2/tenant/{tenantId}/community/{communityId}/user/lock
cURL
Node.js
Python
curl -X PUT 'https://pilot-root.1kosmos.net/users-mgmt/v2/tenant/xxxxxxxxxx/community/xxxxxxxxxxxxxxxxxxxxxxxx/user/lock' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"userId": "xxxxxx", "message": "Admin Action", "initiatedby": "xxxxxxxx", "expiryInMunites": 30}'
RESPONSE
200
400
401
404
Success
{
  "message": "xxxxxxxxxxx"
}
PUT/v2/tenant/{tenantId}/community/{communityId}/user/unlock

unlock a user account.

unlock a user.

  • Only a system and service key can be used to unlock a user.

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Request Body

userId (required)

userId.

message (optinal)

message: 'Admin Action'.

initiatedby (required)

initiatedby: [system]

Returns

Returns success response.

This API throw an error if something goes wrong.

Path parameters
NameTypeDescription
tenantIdrequiredstringID of tenant
communityIdrequiredstringID of community
Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
Request body

Request body contains below fields to lock user.

{
    "userId": "string required",
    "message": "string optinal"    // ['Admin Action']
    "initiatedby": "string required"
}
FieldTypeDescription
userIdstring
messagestring
initiatedbystring
PUThttps://pilot-root.1kosmos.net/users-mgmt/v2/tenant/{tenantId}/community/{communityId}/user/unlock
cURL
Node.js
Python
curl -X PUT 'https://pilot-root.1kosmos.net/users-mgmt/v2/tenant/xxxxxxxxxx/community/xxxxxxxxxxxxxxxxxxxxxxxx/user/unlock' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"userId": "xxxxxx", "message": "Admin Action", "initiatedby": "xxxxxxxx"}'
RESPONSE
200
400
401
404
Success
{
  "message": "xxxxxxxxxxx"
}
User Management

User PIN

User PIN endpoints.

POST/tenant/{tenantId}/community/{communityId}/user/user_pin/register

Register User PIN

Register a new PIN for a user.

  • Only a system, service, service_ext, app, app_ext, or basic key can be used.
  • system, service, and service_ext keys can register PIN without JWT.
  • For app/app_ext/basic keys, a valid JWT is required.
  • PIN is stored as SHA512 hash.

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Request Body

Request body contains 'data' field with encrypted object below:

IMPORTANT - you can send unencrypted data and you will get unencrypted data as well, it is only a preview available in Swagger.

{
  "data": {
    "user": {
      "username": "string (required)",
      "authModule": "string (required)"
    },
    "pin": "string (required)",
    "jwt": "string (optional, required for app/app_ext/basic)"
  }
}
Path parameters
NameTypeDescription
tenantIdrequiredstring
communityIdrequiredstring
Request body
FieldTypeDescription
datarequiredobject
POSThttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/user/user_pin/register
cURL
Node.js
Python
curl -X POST 'https://pilot-root.1kosmos.net/users-mgmt/tenant/<tenantId>/community/<communityId>/user/user_pin/register' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"data": {"user": {"username": "string", "authModule": "string"}, "pin": "string", "jwt": "string"}}'
RESPONSE
200
400
401
405
PIN registered successfully
{
  "status": true
}
PATCH/tenant/{tenantId}/community/{communityId}/user/user_pin/update

Update User PIN

Update a user's PIN.

  • system, service, or service_ext keys can update PIN without further checks.
  • For all other key types, one of the following is required:

&nbsp;&nbsp;• A valid JWT (must be present and pass verification)

&nbsp;&nbsp;• OR the correct currentPin (must match the user's existing PIN)

  • PIN is stored as SHA512 hash.

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Request Body

Request body contains 'data' field with encrypted object below:

IMPORTANT - you can send unencrypted data and you will get unencrypted data as well, it is only a preview available in Swagger.

{
  "data": {
    "user": {
      "username": "string (required)",
      "authModule": "string (required)"
    },
    "currentPin": "string (optional, required if no JWT)",
    "newPin": "string (required)",
    "jwt": "string (optional, required for app/app_ext/basic)"
  }
}
Path parameters
NameTypeDescription
tenantIdrequiredstring
communityIdrequiredstring
Request body
FieldTypeDescription
datarequiredobject
PATCHhttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/user/user_pin/update
cURL
Node.js
Python
curl -X PATCH 'https://pilot-root.1kosmos.net/users-mgmt/tenant/<tenantId>/community/<communityId>/user/user_pin/update' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"data": {"user": {"username": "string", "authModule": "string"}, "currentPin": "string", "newPin": "string", "jwt": "string"}}'
RESPONSE
200
400
401
404
PIN updated successfully
{
  "status": true
}
DELETE/tenant/{tenantId}/community/{communityId}/user/user_pin

Delete User PIN

Delete (unenroll) a user's PIN.

  • system, service, or service_ext keys can delete PIN without further checks.
  • For all other key types, one of the following is required:

&nbsp;&nbsp;• A valid JWT (must be present and pass verification)

&nbsp;&nbsp;• OR the correct currentPin (must match the user's existing PIN)

  • Emits E_USER_PIN_UNENROLLED event.

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Request Body

Request body contains 'data' field with encrypted object below:

{
  "data": {
    "user": {
      "username": "string (required)",
      "authModule": "string (required)"
    },
    "currentPin": "string (optional, required if no JWT)",
    "jwt": "string (optional, required for app/app_ext/basic)",
    "eventInfo": {
      "clientIp": "string (optional)",
      "userAgent": "string (optional)",
      "initiatedBy": "string (optional, username of the initiator)"
    }
  }
}
  • Optional eventInfo allows passing client IP, user agent, and initiator username for event logging.
Path parameters
NameTypeDescription
tenantIdrequiredstring
communityIdrequiredstring
Request body
FieldTypeDescription
datarequiredobject
DELETEhttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/user/user_pin
cURL
Node.js
Python
curl -X DELETE 'https://pilot-root.1kosmos.net/users-mgmt/tenant/<tenantId>/community/<communityId>/user/user_pin' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"data": {"user": {"username": "string", "authModule": "string"}, "currentPin": "string", "jwt": "string", "eventInfo": {"clientIp": "string", "userAgent": "string", "initiatedBy": "string"}}}'
RESPONSE
204
400
401
404
PIN deleted successfully (no content)
// no response body
User Management

Passkey Management

Manage user passkeys.

POST/tenant/{tenantId}/community/{communityId}/passkey

Get passkey credential for a user.

Fetch passkey credential for a given user.

  • Only permit system, service, or service_ext key to fetch a passkey without JWT.
  • For all other key types (app, app_ext, basic), a valid JWT is required.

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA

publickey (required)

Public key

Request Body

Request body contains 'data' field with encrypted object below:

IMPORTANT - you can send unencrypted data and you will get unencrypted data as well, it is only a preview available in Swagger.

userName (required)

Username (email)

Returns

Returns the passkey credential matching the request.

This API throws an error if something goes wrong.

Path parameters
NameTypeDescription
tenantIdrequiredstringID of tenant
communityIdrequiredstringID of community
Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
Request body
FieldTypeDescription
datarequiredobject
POSThttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/passkey
cURL
Node.js
Python
curl -X POST 'https://pilot-root.1kosmos.net/users-mgmt/tenant/xxxxxxxxxx/community/xxxxxxxxxxxxxxxxxxxxxxxx/passkey' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"data": {"userName": "string"}}'
RESPONSE
200
400
401
500
Success
{
  "success": true,
  "credential": {
    "id": "string",
    "privateKey": {},
    "rpId": "string",
    "userHandle": "string",
    "userName": "string",
    "userDisplayName": "string",
    "signCount": 0
  }
}
POST/tenant/{tenantId}/community/{communityId}/passkey/register

Register a passkey credential for a user.

Register a passkey credential for a given user.

  • Only permit system, service, or service_ext key to register a passkey without JWT.
  • For all other key types (app, app_ext, basic), a valid JWT is required.

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA

publickey (required)

Public key

Request Body

Request body contains 'data' field with encrypted object below:

IMPORTANT - you can send unencrypted data and you will get unencrypted data as well, it is only a preview available in Swagger.

credentialId (required)

Credential ID string

privateKey (required)

Private key object containing JWK

rpId (required)

Relying party ID

userId (required)

User handle / identifier

userName (required)

Username (email)

userDisplayName (optional)

Display name

entraAuthMethodId (optional)

Entra auth method ID

createdAt (optional)

Creation timestamp

Returns

Returns success status and credentialId.

This API throws an error if something goes wrong.

Path parameters
NameTypeDescription
tenantIdrequiredstringID of tenant
communityIdrequiredstringID of community
Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
Request body

Request body contains 'data' field with encrypted object below:

IMPORTANT - you can send unencrypted data and you will get unencrypted data as well, it is only a preview available in Swagger.

{
    "data": {
        "credentialId": "string required, credential ID",
        "privateKey": {
            "jwk": {
                "kty": "EC",
                "crv": "P-256",
                "key_ops": ["sign"],
                "ext": true,
                "d": "string",
                "x": "string",
                "y": "string"
            },
            "algorithm": "ES256",
            "curve": "P-256"
        },
        "rpId": "string required, relying party ID",
        "userId": "string required, user handle / identifier",
        "userName": "string required, username (email)",
        "userDisplayName": "string optional, display name",
        "entraAuthMethodId": "string optional, Entra auth method ID",
        "createdAt": "string optional, ISO 8601 timestamp"
    }
}
FieldTypeDescription
datarequiredobject
POSThttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/passkey/register
cURL
Node.js
Python
curl -X POST 'https://pilot-root.1kosmos.net/users-mgmt/tenant/xxxxxxxxxx/community/xxxxxxxxxxxxxxxxxxxxxxxx/passkey/register' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"data": {"credentialId": "string", "privateKey": {"jwk": {"kty": "string", "crv": "string", "key_ops": ["string"], "ext": true, "d": "string", "x": "string", "y": "string"}, "algorithm": "string", "curve": "string"}, "rpId": "string", "userId": "string", "userName": "string", "userDisplayName": "string", "entraAuthMethodId": "string", "createdAt": "string"}}'
RESPONSE
200
400
401
500
Success
{
  "success": true,
  "credentialId": "string"
}
User Management

Service Key

Service Key endpoints.

GET/servicekeys

Get service keys

This endpoint returns available service keys. The license you are using must be of authLevel 'system'

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Returns

Returns array with service keys

Headers
NameTypeDescription
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
GEThttps://pilot-root.1kosmos.net/users-mgmt/servicekeys
cURL
Node.js
Python
curl -X GET 'https://pilot-root.1kosmos.net/users-mgmt/servicekeys' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY'
RESPONSE
200
400
401
500
Success
[
  {
    "tag": "xxxxx",
    "keyId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx",
    "keySecret": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx",
    "type": "xxxxx"
  }
]
DELETE/servicekey/{keyId}

Reset Service Key

This endpoint resets service key for given keyId. Deletes current one and recreates a new one. The license you are using must be of authLevel 'system'

Parameters

keyId (required)

The keyId of service key to reset

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Returns

Returns re-created service key

Path parameters
NameTypeDescription
keyIdrequiredstringkeyId of service key to reset
Headers
NameTypeDescription
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
DELETEhttps://pilot-root.1kosmos.net/users-mgmt/servicekey/{keyId}
cURL
Node.js
Python
curl -X DELETE 'https://pilot-root.1kosmos.net/users-mgmt/servicekey/<keyId>' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY'
RESPONSE
200
400
401
500
Success
[
  {
    "tag": "xxxxx",
    "keyId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx",
    "keySecret": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx",
    "type": "xxxxx"
  }
]
User Management

EAM

EAM endpoints.

POST/tenant/{tenantId}/community/{communityId}/user/fetch_by_oid

Fetch user by Azure AD OID

Resolves a user by their Azure AD object ID (oid) and tenant ID (tid). Searches AzureAD auth modules where config.tenantId matches the provided tid. Returns the mapped user object or 404 if not found. Requires ECDSA service-to-service authentication and a valid SERVICE or SYSTEM license.

Path parameters
NameTypeDescription
tenantIdrequiredstring
communityIdrequiredstring
Request body
FieldTypeDescription
oidrequiredstringAzure AD object ID
tidrequiredstringAzure AD tenant ID
POSThttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/user/fetch_by_oid
cURL
Node.js
Python
curl -X POST 'https://pilot-root.1kosmos.net/users-mgmt/tenant/<tenantId>/community/<communityId>/user/fetch_by_oid' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"oid": "string", "tid": "string"}'
RESPONSE
200
401
404
User found and mapped
// no response body
User Management

ECDSA Helper

ECDSA Helper endpoints.

POST/ecdsa_helper/{method}

Encrypt and decrypt the data string by public key and private key.

Encrypt and decrypt the data string by public key and private key.

Parameters

method (optional)

The method parameter is type of enum. Default value is encrypt.

This parameter only accepts following values

encrypt, decrypt

Request Body

dataStr (required)

The dataStr key is type of string.

publicKey (required)

The publicKey is type of string.

privateKey (required)

The privateKey is type of string.

Returns

Returns the encrypted/decrypted string.

This API throw an error if something goes wrong. A common source of error is public or private key is not valid.

Path parameters
NameTypeDescription
methodstring
Request body
FieldTypeDescription
dataStrstring
publicKeystring
privateKeystring
POSThttps://pilot-root.1kosmos.net/users-mgmt/ecdsa_helper/{method}
cURL
Node.js
Python
curl -X POST 'https://pilot-root.1kosmos.net/users-mgmt/ecdsa_helper/<method>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"dataStr": "Hey, This is example data string.", "publicKey": "xxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxx=", "privateKey": "xxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxx="}'
RESPONSE
200
successful operation
{
  "data": "xxxxxxxxxxxxxxxxxxxx"
}
User Management

Environment

Environment endpoints.

GET/environment

/environment

Provide details regarding the environments.

Returns

Returns an environment object

GEThttps://pilot-root.1kosmos.net/users-mgmt/environment
cURL
Node.js
Python
curl -X GET 'https://pilot-root.1kosmos.net/users-mgmt/environment' \
  -H 'license: YOUR_LICENSE_KEY'
RESPONSE
200
Success
// no response body
User Management

Factor

Factor endpoints.

DELETE/tenant/{tenantId}/community/{communityId}/factor_lock

Delete FactorLock and FactorMistakes by communityId, tenantId, factor and userId.

Delete FactorLock and FactorMistakes by communityId and tenantId, factor and userId.

  • License Key must be authorized for community.
  • Only a system and service key can be used to delete user factor of communityId,tenantId.

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Request Body

userId (required)

userId of user.

factor (required)

Name of the factor

authModuleId (required)

moduleId

Returns

No content.

This API throw an error if something goes wrong.

Path parameters
NameTypeDescription
tenantIdrequiredstringID of tenant
communityIdrequiredstringID of community
Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
Request body

Request body contains below fields to delete user factor.

{
    "userId": "string required",
    "factor": "string required",
    "authModuleId" : "string required",
    "eventData": "object optional"
}
FieldTypeDescription
userIdstring
factorstring
authModuleIdstring
eventDataobject
DELETEhttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/factor_lock
cURL
Node.js
Python
curl -X DELETE 'https://pilot-root.1kosmos.net/users-mgmt/tenant/xxxxxxxxxx/community/xxxxxxxxxxxxxxxxxxxxxxxx/factor_lock' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"userId": "xxxxxxxxxx", "factor": "xxxxxx", "authModuleId": "xxxxxxx", "eventData": {}}'
RESPONSE
204
400
401
404
Success No Content
// no response body
User Management

Healthz

Healthz endpoints.

GET/healthz

Get healthz.

Get health information

Headers
NameTypeDescription
synthetic-heartbeatstringIf this field is set then additional health information is collection (will not be displayed). Valid values are all, onUserCreated, userStateEvents
licensekeystringplain text license key;
GEThttps://pilot-root.1kosmos.net/users-mgmt/healthz
cURL
Node.js
Python
curl -X GET 'https://pilot-root.1kosmos.net/users-mgmt/healthz' \
  -H 'synthetic-heartbeat: <value>' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'license: YOUR_LICENSE_KEY'
RESPONSE
200
Success ``` { "status": "all services operational", "publicKey": "string" //same as <service>/publickeys endpoint, "code": "200", "version": "<git-tag>.<commit-id>.<dob>" } Version value contains the following value if the code is build from a git-tag - ```git-tag```: When code is compiled from a git-tag, this must carry the tag name. This should match one of the git tags. - ```commit-id```: This is the git-commit-id. eg: When code is built from this, the hex code, in the end, is the commit it. - ```dob```: Date Of Build. This is epoc-time-in-se conds that tell the time when the build was created. Otherwise - ```commit-id```: This is the git-commit-id. eg: When code is built from this, the hex code, in the end, is the commit it. - ```dob```: Date Of Build. This is epoc-time-in-se conds that tell the time when the build was created.
{
  "status": "all services operational",
  "publicKey": "//same as <service>/publickeys endpoint",
  "code": "200",
  "version": "xxxx.xxxx.xxxx"
}
User Management

Infra

Infra endpoints.

POST/infra/checkBrokerStatusAndSendNotifications

Check broker connection status and send email.

Check broker connection status and send email.

  • Only a INFRA_LICENSE_KEY can be used.

Headers

licensekey (required)

Unencrypted infra key

Returns

204 No Content

Headers
NameTypeDescription
licensekeyrequiredstringInfra key
POSThttps://pilot-root.1kosmos.net/users-mgmt/infra/checkBrokerStatusAndSendNotifications
cURL
Node.js
Python
curl -X POST 'https://pilot-root.1kosmos.net/users-mgmt/infra/checkBrokerStatusAndSendNotifications' \
  -H 'licensekey: YOUR_LICENSE_KEY'
RESPONSE
204
401
Success No Content
// no response body
User Management

Internal Broker Call

Internal Broker Call endpoints.

POST/internal_call/broker_request

Make a broker request via socket

This endpoint only called internally from the one pod to another pod.

Returns

Return a response from broker.

Request body
FieldTypeDescription
communityIdstring
authModuleobject
dataPayloadobject
POSThttps://pilot-root.1kosmos.net/users-mgmt/internal_call/broker_request
cURL
Node.js
Python
curl -X POST 'https://pilot-root.1kosmos.net/users-mgmt/internal_call/broker_request' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"communityId": "string", "authModule": {}, "dataPayload": {}}'
RESPONSE
200
[
  {
    "metadata": {},
    "operationstatus": {},
    "totalRecords": null
  },
  {
    "cn": "string",
    "samaccountname": "string",
    "sn": "string"
  }
]
User Management

JWT

JWT endpoints.

POST/jwt/verifyToken

/jwt/verifyToken

Verify JWT token.

Request Body

token (required)

token : string

Returns

Returns a decoded token value.

Request body
FieldTypeDescription
tokenstring
POSThttps://pilot-root.1kosmos.net/users-mgmt/jwt/verifyToken
cURL
Node.js
Python
curl -X POST 'https://pilot-root.1kosmos.net/users-mgmt/jwt/verifyToken' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"token": "xxxx"}'
RESPONSE
200
401
{}
User Management

Public Key

Public Key endpoints.

GET/publickeys

Get system's public key.

Get system's public key.

Returns

Returns a public key object

GEThttps://pilot-root.1kosmos.net/users-mgmt/publickeys
cURL
Node.js
Python
curl -X GET 'https://pilot-root.1kosmos.net/users-mgmt/publickeys' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY'
RESPONSE
200
401
{
  "publicKey": ""
}
User Management

Service Directory

Service Directory endpoints.

GET/sd

Get all service directories.

Get all service directories.

Returns

Returns all service directories.

GEThttps://pilot-root.1kosmos.net/users-mgmt/sd
cURL
Node.js
Python
curl -X GET 'https://pilot-root.1kosmos.net/users-mgmt/sd' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY'
RESPONSE
200
{
  "name1": "https://xxx.xxxxxx.xxx/xxxxx",
  "name2": "https://xxx.xxxxxx.xxx/xxxxx",
  "name3": "https://xxx.xxxxxx.xxx/xxxxx"
}
User Management

User Properties

User Properties endpoints.

POST/tenant/{tenantId}/community/{communityId}/user_properties/update

update user properties.

update user properties.

  • Only a system, service and service_ext valid with community key can be used to update a user properties.

Headers

licensekey (required)

License key encrypted with ECDSA

requestid (required)

JSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now

publickey (required)

Public key

Request Body

data (required)

user properties data encrypted with ECDSA.

Returns

Returns the ECDSA encrypted updated user properties.

This API throw an error if something goes wrong.

Path parameters
NameTypeDescription
tenantIdrequiredstringID of tenant
communityIdrequiredstringID of community
Headers
NameTypeDescription
licensekeyrequiredstringLicense key encrypted with ECDSA / Try Authorize &#128274;
requestidrequiredstringJSON string encrypted with ECDSA which should contain "appid" (string), "uuid" (string) and "ts" (number) representing epoch timestamp in seconds - it shouldn't be more or less than 'environment.allowed_time_span' seconds from now / Try Authorize &#128274;
publickeyrequiredstringPublic Key / Try Authorize &#128274;
Request body

Request body contains 'data' field with encrypted object below:

IMPORTANT - you can send unencrypted data and you will get unecrypted data as well, it is only a preview available in Swagger.

{
    "data": {
        "user": {
            "username": "",
             "uid": "",
             "authModuleId": ""
        },
         "mobiles": [],
        "landlines": [],
        "aliases": {
            "alias1": "string",
            "alias2": null,
            "alias3": "string",
            "alias4": "string",
            "alias5": null,
            "alias6": null,
            "alias7": null,
            "alias8": null
        }
    }
}
FieldTypeDescription
dataobject
POSThttps://pilot-root.1kosmos.net/users-mgmt/tenant/{tenantId}/community/{communityId}/user_properties/update
cURL
Node.js
Python
curl -X POST 'https://pilot-root.1kosmos.net/users-mgmt/tenant/xxxxxxxxxx/community/xxxxxxxxxxxxxxxxxxxxxxxx/user_properties/update' \
  -H 'licensekey: YOUR_LICENSE_KEY' \
  -H 'requestid: <ecdsa-requestid>' \
  -H 'publickey: <public-key>' \
  -H 'keyId: YOUR_KEY_ID' \
  -H 'keySecret: YOUR_KEY_SECRET' \
  -H 'license: YOUR_LICENSE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"data": {"user": {"username": "", "uid": "", "authModuleId": ""}, "mobiles": [], "landlines": [], "aliases": {"alias1": "string", "alias2": null, "alias3": "string", "alias4": "string", "alias5": null, "alias6": null, "alias7": null, "alias8": null}}}'
RESPONSE
200
400
401
404
Success updated user properties: ``` { "data":{ "_id": "", "tenantId": "", "communityId": "", "user": { "uid": "", "username": "", "authModuleId": "" }, "mobiles": [], "landlines": [], "aliases": { "alias1": "string", "alias2": null, "alias3": "string", "alias4": "string", "alias5": null, "alias6": null, "alias7": null, "alias8": null } }, "publicKey": "xxxxxx" } ```
{
  "_id": "",
  "tenantId": "",
  "communityId": "",
  "user": {
    "uid": "",
    "username": "",
    "authModuleId": ""
  },
  "mobiles": [],
  "landlines": [],
  "aliases": {
    "alias1": "string",
    "alias2": null,
    "alias3": "string",
    "alias4": "string",
    "alias5": null,
    "alias6": null,
    "alias7": null,
    "alias8": null
  }
}
© 2026 1Kosmos · User Management Service v2.0Generated from the OpenAPI spec · users-mgmt.json