# Create User

Creates a new user, either End-User or Service User.

* End-User Accounts are assigned to employees. To create an end user account, the `accountType` field must be `NORMAL`.
* Service User Accounts are a type of account used for bots or applications, rather than end-users. To create a service user account, the `accountType` field must be `SYSTEM`.

See [User Attributes](ref:user-attributes), [Password Object](ref:password-object), and [Roles Object](ref:roles-object) for user creation parameters.

## POST /v2/admin/user/create

> Create a new V2 User

```json
{"openapi":"3.1.1","info":{"title":"Pod API","version":"20.17.1"},"servers":[{"url":"http://yourpodURL.symphony.com/pod"}],"paths":{"/v2/admin/user/create":{"post":{"summary":"Create a new V2 User","parameters":[{"schema":{"type":"string"},"name":"sessionToken","description":"Session authentication token.","in":"header","required":true}],"tags":["User"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V2UserDetail"}}}},"400":{"description":"Client error, see response body for further details.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized: Invalid session token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden: Caller lacks necessary entitlement.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Server error, see response body for further details.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/V2UserCreate"}}},"required":true}}}},"components":{"schemas":{"V2UserDetail":{"description":"V2 Detailed User record.","type":"object","properties":{"userAttributes":{"$ref":"#/components/schemas/V2UserAttributes"},"userSystemInfo":{"$ref":"#/components/schemas/UserSystemInfo"},"features":{"$ref":"#/components/schemas/IntegerList"},"apps":{"$ref":"#/components/schemas/IntegerList"},"groups":{"$ref":"#/components/schemas/IntegerList"},"roles":{"$ref":"#/components/schemas/StringList"},"disclaimers":{"$ref":"#/components/schemas/IntegerList"},"avatar":{"$ref":"#/components/schemas/Avatar"}}},"V2UserAttributes":{"description":"V2 User record.","type":"object","properties":{"emailAddress":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"userName":{"type":"string"},"displayName":{"type":"string"},"companyName":{"type":"string"},"department":{"type":"string"},"division":{"type":"string"},"title":{"type":"string"},"workPhoneNumber":{"type":"string"},"mobilePhoneNumber":{"type":"string"},"twoFactorAuthPhone":{"type":"string"},"smsNumber":{"type":"string"},"accountType":{"type":"string","enum":["NORMAL","SYSTEM","SDL"]},"location":{"type":"string"},"recommendedLanguage":{"type":"string"},"jobFunction":{"type":"string"},"assetClasses":{"type":"array","items":{"type":"string"}},"industries":{"type":"array","items":{"type":"string"}},"marketCoverage":{"type":"array","items":{"type":"string"}},"responsibility":{"type":"array","items":{"type":"string"}},"function":{"type":"array","items":{"type":"string"}},"instrument":{"type":"array","items":{"type":"string"}},"currentKey":{"$ref":"#/components/schemas/V2UserKeyRequest"},"previousKey":{"$ref":"#/components/schemas/V2UserKeyRequest"},"userMetadata":{"type":"object","description":"Metadata map of key/values","additionalProperties":{"type":"object"}}}},"V2UserKeyRequest":{"description":"User RSA key information.","type":"object","properties":{"key":{"description":"User RSA public key.","type":"string"},"expirationDate":{"description":"RSA key expiration date. This value is set just for rotated keys.","type":"integer","format":"int64"},"action":{"description":"Action to be performed on the RSA key.\nThe following actions can be performed onto the user's active RSA key:\n  - SAVE\n  - REVOKE\nThe following actions can be performed onto the user's rotated RSA key:\n  - REVOKE\n  - EXTEND\n","type":"string"}}},"UserSystemInfo":{"description":"User Status Information.","type":"object","properties":{"id":{"type":"integer","format":"int64"},"status":{"type":"string","enum":["ENABLED","DISABLED"]},"suspended":{"type":"boolean","description":"An optional attribute indicating whether the user is temporarily suspended or not. Since SBE 20.14."},"suspendedUntil":{"type":"integer","format":"int64","description":"An optional unix timestamp until which the suspension is effective. Since SBE 20.14."},"suspensionReason":{"type":"string","description":"An optional description of the suspension reason. Since SBE 20.14."},"createdDate":{"type":"integer","format":"int64"},"createdBy":{"type":"string"},"lastUpdatedDate":{"type":"integer","format":"int64"},"lastLoginDate":{"type":"integer","format":"int64"},"lastPasswordReset":{"type":"integer","format":"int64"},"deactivatedDate":{"type":"integer","format":"int64"}}},"IntegerList":{"type":"array","items":{"type":"integer","format":"int64"}},"StringList":{"type":"array","items":{"type":"string"}},"Avatar":{"type":"object","properties":{"size":{"description":"The Avatar Size","type":"string"},"url":{"description":"Url of the image","type":"string"}}},"Error":{"type":"object","properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}},"V2UserCreate":{"description":"V2 User Creation Object.\nAfter creation, modify roles, features etc via the specific API calls.\n","type":"object","properties":{"userAttributes":{"$ref":"#/components/schemas/V2UserAttributes"},"password":{"$ref":"#/components/schemas/Password"},"roles":{"type":"array","items":{"type":"string"}}}},"Password":{"description":"Password. Stored as derived password in both the Pod and the Key Manager using PBKDF2 function. Number of iterations should be 10000 and desired length 256 bits.","type":"object","properties":{"hSalt":{"description":"Pod password salt used for PBKDF2 derivation.","type":"string"},"hPassword":{"description":"Pod password derived with PBKDF2.","type":"string"},"khSalt":{"description":"Key Manager password salt used for PBKDF2 derivation.","type":"string"},"khPassword":{"description":"Key Manager password derived with PBKDF2.","type":"string"}}}}}}
```

### Request Examples

```bash
curl -X POST \
https://acme.symphony.com/pod/v2/admin/user/create \
-H "sessionToken: SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d '{   
    "userAttributes": {
        "accountType": "NORMAL",
        "emailAddress": "janedoe@symphony.com",
        "firstName": "Jane",
        "lastName": "Doe",
        "userName": "janedoe",
        "displayName": "Jane Doe",
        "companyName": "",
        "department": "",
        "division": "",
        "title": "Sales",
        "twoFactorAuthPhone": "",
        "workPhoneNumber": "",
        "mobilePhoneNumber": "",
        "location": "San Francisco",
        "jobFunction": "Sales",
        "assetClasses": ["Commodities"],
        "industries": ["Basic Materials"],
        "marketCoverage": ["LATAM"],
        "responsibility": ["BAU"],
        "function": ["Trade Management"],
        "instrument": ["Securities"],
        "currentKey": {"key": "-----BEGIN PUBLIC KEY-----\nMIICIjAN...==\n-----END PUBLIC KEY-----"
}
        
    },
    "password": {
        "hSalt": "password",
        "hPassword": "password",
        "khSalt": "password",
        "khPassword": "password"
    }
}'
```

```bash
curl -X POST \
https://acme.symphony.com/pod/v2/admin/user/create \
-H "sessionToken: SESSION_TOKEN" -H "Content-Type: application/json" \
-d '{
  "userAttributes": {
    "accountType": "SYSTEM",
    "emailAddress": "apiuser@symphony.com",
    "userName": "apiuser",
    "displayName": "API User",
    "companyName": "Symphony",
    "department": "Client Application",
    "division": "Technology",
    "workPhoneNumber": "+33600000000",
    "mobilePhoneNumber": "+33600000001",
    "twoFactorAuthPhone": "+33600000002",
    "recommendedLanguage": "english",
    "location": "Sophia Antipolis",
    "jobFunction": "Sales",
    "assetClasses": ["Commodities"],
    "industries": ["Basic Materials"],
    "marketCoverage": ["LATAM"],
    "responsibility": ["BAU"],
    "function": ["Trade Management"],
    "instrument": ["Securities"],
    "currentKey": {
        "key": "-----BEGIN PUBLIC KEY-----MII...Q==-----END PUBLIC KEY-----"
    }

  },
  "roles": ["INDIVIDUAL", "USER_PROVISIONING", "SCOPE_MANAGEMENT", "CONTENT_MANAGEMENT", "MALWARE_SCAN_MANAGER", "MALWARE_SCAN_STATE_USER", "AUDIT_TRAIL_MANAGEMENT"]
}'
```

> #### 📘 Note - Suspension
>
> Since 20.14, `userSystemInfo` from the payload includes suspension info:
>
> * if user is active, then the `suspended` attribute is set to false,
> * if user is suspended, then the `suspended` attribute is set to true and both `suspendedUntil` and `suspensionReason` are as well included in the payload.
>
> *Please note that even if the suspendedUntil date is in the past, the user will remain suspended=true until he first logs on the client after the suspension ended. The suspended info are then automatically updated.*\
> See the [Suspend User Account](/main/user-management/suspend-user-v1.md) endpoint for more information.

> #### 🚧 Required Permissions
>
> Calling this endpoint requires the ACCESS\_USER\_PROVISIONING\_API and ACCESS\_ADMIN\_API privileges.\
> See [Bot Permissions](https://docs.developers.symphony.com/building-bots-on-symphony/configuration/bot-permissions) for a list of roles and associated privileges.

### The `Password` Object

The `password` object is optional for end-user accounts (`NORMAL`). For example, if your organization utilizes SSO, you may not want to specify the password.

*Please note the password object is not used for service accounts (`SYSTEM`) and therefore cannot be entered in the request payload.*

The following code snippets can be used to generate hashed passwords. Two implementations are provided, one using built-in Java classes and the other with Postman.

```java
@Test
public void test() throws NoSuchAlgorithmException, InvalidKeySpecException {
  String password = "ARandomPassword";
  SecureRandom sr = new SecureRandom();
  byte[] salt = new byte[16];
  sr.nextBytes(salt);
  assertTrue(Arrays.equals(generateStrongPasswordHash(password, salt), getSaltedPassword(password, salt)));
}

private static byte[] generateStrongPasswordHash(String password, byte[] salt)
throws NoSuchAlgorithmException, InvalidKeySpecException {
  int iterations = 10000;
  char[] pb = password.toCharArray();
  PBEKeySpec spec = new PBEKeySpec(pb, salt, iterations, 256);
  SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
  byte[] hash = skf.generateSecret(spec).getEncoded();
  return hash;
}

public static byte[] getSaltedPassword(String password, byte[] salt) {
  PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(new SHA256Digest());
  byte[] bytes = password.getBytes(StandardCharsets.UTF_8);
  gen.init(bytes, salt, 10000);
  byte[] newPasswordGen = ((KeyParameter) gen.generateDerivedParameters(256)).getKey();
  return newPasswordGen;
}
```

```javascript
// Example with Postman, as a Pre-Request script.

const password = 'SymphonyRocks123456789!'; // Replace with your password

// Generate a random salt of specified length
function generateSalt(length) {
    return CryptoJS.lib.WordArray.random(128 / 8);
}

// PBKDF2 function using CryptoJS
function derivePBKDF2(password, salt, iterations, keyLength) {
    return CryptoJS.PBKDF2(password, salt, {
        keySize: keyLength / 32, // Key size in words (32-bit units)
        iterations: iterations,
        hasher: CryptoJS.algo.SHA256
    });
}

// Parameters
const iterations = 10000;           // Number of iterations
const keyLength = 256;              // Key length in bits (256 = 32 bytes)
const saltLength = 16;              // Salt length in characters

// Generate random salts
const hSalt = generateSalt(saltLength);
const khSalt = generateSalt(saltLength);

// Derive PBKDF2 hashes
const hPassword = derivePBKDF2(password, hSalt, iterations, keyLength);
const khPassword = derivePBKDF2(password, khSalt, iterations, keyLength);

// Convert salts and hashes to B64 strings
const hSaltB64 = CryptoJS.enc.Base64.stringify(hSalt);
const khSaltB64 = CryptoJS.enc.Base64.stringify(khSalt);
const hPasswordB64 = CryptoJS.enc.Base64.stringify(hPassword);
const khPasswordB64 = CryptoJS.enc.Base64.stringify(khPassword);

// Set Postman environment variables for use in the request
pm.environment.set('hSalt', hSaltB64);
pm.environment.set('hPassword', hPasswordB64);
pm.environment.set('khSalt', khSaltB64);
pm.environment.set('khPassword', khPasswordB64);
```


---

# Agent Instructions: Querying This Documentation

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

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

```
GET https://rest-api.symphony.com/main/user-management/create-user-v2.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

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